func Expr(t miniprofiler.Timer, w http.ResponseWriter, r *http.Request) (interface{}, error) { e, err := expr.New(r.FormValue("q"), schedule.Conf.Funcs()) if err != nil { return nil, err } now, err := getTime(r) if err != nil { return nil, err } // it may not strictly be necessary to recreate the contexts each time, but we do to be safe tsdbContext := schedule.Conf.TSDBContext() graphiteContext := schedule.Conf.GraphiteContext() ls := schedule.Conf.LogstashElasticHosts res, queries, err := e.Execute(tsdbContext, graphiteContext, ls, cacheObj, t, now, 0, false, schedule.Search, nil, nil) if err != nil { return nil, err } for _, r := range res.Results { if r.Computations == nil { r.Computations = make(expr.Computations, 0) } } ret := struct { Type string Results []*expr.Result Queries map[string]opentsdb.Request }{ e.Tree.Root.Return().String(), res.Results, make(map[string]opentsdb.Request), } for _, q := range queries { if e, err := url.QueryUnescape(q.String()); err == nil { ret.Queries[e] = q } } return ret, nil }
func Expr(t miniprofiler.Timer, w http.ResponseWriter, r *http.Request) (v interface{}, err error) { defer func() { if pan := recover(); pan != nil { v = nil err = fmt.Errorf("%v", pan) } }() text, err := ioutil.ReadAll(r.Body) if err != nil { return nil, err } lines := strings.Split(strings.TrimSpace(string(text)), "\n") var expression string vars := map[string]string{} varRegex := regexp.MustCompile(`(\$\w+)\s*=(.*)`) for i, line := range lines { line = strings.TrimSpace(line) if line == "" { continue } // last line is expression we care about if i == len(lines)-1 { expression = schedule.Conf.Expand(line, vars, false) } else { // must be a variable declatation matches := varRegex.FindStringSubmatch(line) if len(matches) == 0 { return nil, fmt.Errorf("Expect all lines before final expression to be variable declarations of form `$foo = something`") } name := strings.TrimSpace(matches[1]) value := strings.TrimSpace(matches[2]) vars[name] = schedule.Conf.Expand(value, vars, false) } } e, err := expr.New(expression, schedule.Conf.Funcs()) if err != nil { return nil, err } now, err := getTime(r) if err != nil { return nil, err } // it may not strictly be necessary to recreate the contexts each time, but we do to be safe tsdbContext := schedule.Conf.TSDBContext() graphiteContext := schedule.Conf.GraphiteContext() ls := schedule.Conf.LogstashElasticHosts influx := schedule.Conf.InfluxConfig es := schedule.Conf.ElasticHosts res, queries, err := e.Execute(tsdbContext, graphiteContext, ls, es, influx, cacheObj, t, now, 0, false, schedule.Search, nil, nil) if err != nil { return nil, err } for _, r := range res.Results { if r.Computations == nil { r.Computations = make(models.Computations, 0) } } ret := struct { Type string Results []*expr.Result Queries map[string]opentsdb.Request }{ e.Tree.Root.Return().String(), res.Results, make(map[string]opentsdb.Request), } for _, q := range queries { if e, err := url.QueryUnescape(q.String()); err == nil { ret.Queries[e] = q } } return ret, nil }