diff --git a/pkg/api/metrics.go b/pkg/api/metrics.go index 2b3e3c09cd4..717565cd4a1 100644 --- a/pkg/api/metrics.go +++ b/pkg/api/metrics.go @@ -43,7 +43,7 @@ func QueryMetrics(c *middleware.Context, reqDto dtos.MetricRequest) Response { }) } - resp, err := tsdb.HandleRequest(context.Background(), request) + resp, err := tsdb.HandleRequest(context.Background(), dsQuery.Result, request) if err != nil { return ApiError(500, "Metric request error", err) } @@ -100,16 +100,17 @@ func GetTestDataRandomWalk(c *middleware.Context) Response { timeRange := tsdb.NewTimeRange(from, to) request := &tsdb.TsdbQuery{TimeRange: timeRange} + dsInfo := &models.DataSource{Type: "grafana-testdata-datasource"} request.Queries = append(request.Queries, &tsdb.Query{ RefId: "A", IntervalMs: intervalMs, Model: simplejson.NewFromAny(&util.DynMap{ "scenario": "random_walk", }), - DataSource: &models.DataSource{Type: "grafana-testdata-datasource"}, + DataSource: dsInfo, }) - resp, err := tsdb.HandleRequest(context.Background(), request) + resp, err := tsdb.HandleRequest(context.Background(), dsInfo, request) if err != nil { return ApiError(500, "Metric request error", err) } diff --git a/pkg/services/alerting/conditions/query.go b/pkg/services/alerting/conditions/query.go index 417b3c96f10..d499c5e8532 100644 --- a/pkg/services/alerting/conditions/query.go +++ b/pkg/services/alerting/conditions/query.go @@ -112,7 +112,7 @@ func (c *QueryCondition) executeQuery(context *alerting.EvalContext, timeRange * req := c.getRequestForAlertRule(getDsInfo.Result, timeRange) result := make(tsdb.TimeSeriesSlice, 0) - resp, err := c.HandleRequest(context.Ctx, req) + resp, err := c.HandleRequest(context.Ctx, getDsInfo.Result, req) if err != nil { if err == gocontext.DeadlineExceeded { return nil, fmt.Errorf("Alert execution exceeded the timeout") diff --git a/pkg/services/alerting/conditions/query_test.go b/pkg/services/alerting/conditions/query_test.go index c5a15adf45b..0ea6470bc2d 100644 --- a/pkg/services/alerting/conditions/query_test.go +++ b/pkg/services/alerting/conditions/query_test.go @@ -168,7 +168,7 @@ func (ctx *queryConditionTestContext) exec() (*alerting.ConditionResult, error) ctx.condition = condition - condition.HandleRequest = func(context context.Context, req *tsdb.TsdbQuery) (*tsdb.Response, error) { + condition.HandleRequest = func(context context.Context, dsInfo *m.DataSource, req *tsdb.TsdbQuery) (*tsdb.Response, error) { return &tsdb.Response{ Results: map[string]*tsdb.QueryResult{ "A": {Series: ctx.series}, diff --git a/pkg/tsdb/fake_test.go b/pkg/tsdb/fake_test.go index ab1bc944eb8..572b3c77ff3 100644 --- a/pkg/tsdb/fake_test.go +++ b/pkg/tsdb/fake_test.go @@ -20,18 +20,18 @@ func NewFakeExecutor(dsInfo *models.DataSource) (*FakeExecutor, error) { }, nil } -func (e *FakeExecutor) Query(ctx context.Context, dsInfo *models.DataSource, context *TsdbQuery) *BatchResult { - result := &BatchResult{QueryResults: make(map[string]*QueryResult)} +func (e *FakeExecutor) Query(ctx context.Context, dsInfo *models.DataSource, context *TsdbQuery) (*Response, error) { + result := &Response{Results: make(map[string]*QueryResult)} for _, query := range context.Queries { if results, has := e.results[query.RefId]; has { - result.QueryResults[query.RefId] = results + result.Results[query.RefId] = results } if testFunc, has := e.resultsFn[query.RefId]; has { - result.QueryResults[query.RefId] = testFunc(context) + result.Results[query.RefId] = testFunc(context) } } - return result + return result, nil } func (e *FakeExecutor) Return(refId string, series TimeSeriesSlice) { diff --git a/pkg/tsdb/graphite/graphite.go b/pkg/tsdb/graphite/graphite.go index 273bf826de5..7cadf055ff6 100644 --- a/pkg/tsdb/graphite/graphite.go +++ b/pkg/tsdb/graphite/graphite.go @@ -37,8 +37,8 @@ func init() { tsdb.RegisterTsdbQueryEndpoint("graphite", NewGraphiteExecutor) } -func (e *GraphiteExecutor) Query(ctx context.Context, dsInfo *models.DataSource, tsdbQuery *tsdb.TsdbQuery) *tsdb.BatchResult { - result := &tsdb.BatchResult{} +func (e *GraphiteExecutor) Query(ctx context.Context, dsInfo *models.DataSource, tsdbQuery *tsdb.TsdbQuery) (*tsdb.Response, error) { + result := &tsdb.Response{} from := "-" + formatTimeRange(tsdbQuery.TimeRange.From) until := formatTimeRange(tsdbQuery.TimeRange.To) @@ -67,14 +67,12 @@ func (e *GraphiteExecutor) Query(ctx context.Context, dsInfo *models.DataSource, req, err := e.createRequest(dsInfo, formData) if err != nil { - result.Error = err - return result + return nil, err } httpClient, err := dsInfo.GetHttpClient() if err != nil { - result.Error = err - return result + return nil, err } span, ctx := opentracing.StartSpanFromContext(ctx, "graphite query") @@ -90,17 +88,15 @@ func (e *GraphiteExecutor) Query(ctx context.Context, dsInfo *models.DataSource, res, err := ctxhttp.Do(ctx, httpClient, req) if err != nil { - result.Error = err - return result + return nil, err } data, err := e.parseResponse(res) if err != nil { - result.Error = err - return result + return nil, err } - result.QueryResults = make(map[string]*tsdb.QueryResult) + result.Results = make(map[string]*tsdb.QueryResult) queryRes := tsdb.NewQueryResult() for _, series := range data { @@ -114,8 +110,8 @@ func (e *GraphiteExecutor) Query(ctx context.Context, dsInfo *models.DataSource, } } - result.QueryResults["A"] = queryRes - return result + result.Results["A"] = queryRes + return result, nil } func (e *GraphiteExecutor) parseResponse(res *http.Response) ([]TargetResponseDTO, error) { diff --git a/pkg/tsdb/influxdb/influxdb.go b/pkg/tsdb/influxdb/influxdb.go index e79e7b7790c..6100d3b401e 100644 --- a/pkg/tsdb/influxdb/influxdb.go +++ b/pkg/tsdb/influxdb/influxdb.go @@ -39,17 +39,17 @@ func init() { tsdb.RegisterTsdbQueryEndpoint("influxdb", NewInfluxDBExecutor) } -func (e *InfluxDBExecutor) Query(ctx context.Context, dsInfo *models.DataSource, tsdbQuery *tsdb.TsdbQuery) *tsdb.BatchResult { - result := &tsdb.BatchResult{} +func (e *InfluxDBExecutor) Query(ctx context.Context, dsInfo *models.DataSource, tsdbQuery *tsdb.TsdbQuery) (*tsdb.Response, error) { + result := &tsdb.Response{} query, err := e.getQuery(dsInfo, tsdbQuery.Queries, tsdbQuery) if err != nil { - return result.WithError(err) + return nil, err } rawQuery, err := query.Build(tsdbQuery) if err != nil { - return result.WithError(err) + return nil, err } if setting.Env == setting.DEV { @@ -58,21 +58,21 @@ func (e *InfluxDBExecutor) Query(ctx context.Context, dsInfo *models.DataSource, req, err := e.createRequest(dsInfo, rawQuery) if err != nil { - return result.WithError(err) + return nil, err } httpClient, err := dsInfo.GetHttpClient() if err != nil { - return result.WithError(err) + return nil, err } resp, err := ctxhttp.Do(ctx, httpClient, req) if err != nil { - return result.WithError(err) + return nil, err } if resp.StatusCode/100 != 2 { - return result.WithError(fmt.Errorf("Influxdb returned statuscode invalid status code: %v", resp.Status)) + return nil, fmt.Errorf("Influxdb returned statuscode invalid status code: %v", resp.Status) } var response Response @@ -82,17 +82,17 @@ func (e *InfluxDBExecutor) Query(ctx context.Context, dsInfo *models.DataSource, err = dec.Decode(&response) if err != nil { - return result.WithError(err) + return nil, err } if response.Err != nil { - return result.WithError(response.Err) + return nil, response.Err } - result.QueryResults = make(map[string]*tsdb.QueryResult) - result.QueryResults["A"] = e.ResponseParser.Parse(&response, query) + result.Results = make(map[string]*tsdb.QueryResult) + result.Results["A"] = e.ResponseParser.Parse(&response, query) - return result + return result, nil } func (e *InfluxDBExecutor) getQuery(dsInfo *models.DataSource, queries []*tsdb.Query, context *tsdb.TsdbQuery) (*Query, error) { diff --git a/pkg/tsdb/models.go b/pkg/tsdb/models.go index 2fa2ed06c95..cbda7c97515 100644 --- a/pkg/tsdb/models.go +++ b/pkg/tsdb/models.go @@ -22,24 +22,8 @@ type Query struct { } type Response struct { - BatchTimings []*BatchTiming `json:"timings"` - Results map[string]*QueryResult `json:"results"` - Message string `json:"message,omitempty"` -} - -type BatchTiming struct { - TimeElapsed int64 -} - -type BatchResult struct { - Error error - QueryResults map[string]*QueryResult - Timings *BatchTiming -} - -func (br *BatchResult) WithError(err error) *BatchResult { - br.Error = err - return br + Results map[string]*QueryResult `json:"results"` + Message string `json:"message,omitempty"` } type QueryResult struct { diff --git a/pkg/tsdb/mysql/mysql.go b/pkg/tsdb/mysql/mysql.go index b1e7e916787..19aa50096b1 100644 --- a/pkg/tsdb/mysql/mysql.go +++ b/pkg/tsdb/mysql/mysql.go @@ -85,9 +85,9 @@ func (e *MysqlExecutor) initEngine(dsInfo *models.DataSource) error { return nil } -func (e *MysqlExecutor) Query(ctx context.Context, dsInfo *models.DataSource, tsdbQuery *tsdb.TsdbQuery) *tsdb.BatchResult { - result := &tsdb.BatchResult{ - QueryResults: make(map[string]*tsdb.QueryResult), +func (e *MysqlExecutor) Query(ctx context.Context, dsInfo *models.DataSource, tsdbQuery *tsdb.TsdbQuery) (*tsdb.Response, error) { + result := &tsdb.Response{ + Results: make(map[string]*tsdb.QueryResult), } macroEngine := NewMysqlMacroEngine(tsdbQuery.TimeRange) @@ -102,7 +102,7 @@ func (e *MysqlExecutor) Query(ctx context.Context, dsInfo *models.DataSource, ts } queryResult := &tsdb.QueryResult{Meta: simplejson.New(), RefId: query.RefId} - result.QueryResults[query.RefId] = queryResult + result.Results[query.RefId] = queryResult rawSql, err := macroEngine.Interpolate(rawSql) if err != nil { @@ -138,7 +138,7 @@ func (e *MysqlExecutor) Query(ctx context.Context, dsInfo *models.DataSource, ts } } - return result + return result, nil } func (e MysqlExecutor) TransformToTable(query *tsdb.Query, rows *core.Rows, result *tsdb.QueryResult) error { diff --git a/pkg/tsdb/opentsdb/opentsdb.go b/pkg/tsdb/opentsdb/opentsdb.go index f965392de01..29daa0c3bb4 100644 --- a/pkg/tsdb/opentsdb/opentsdb.go +++ b/pkg/tsdb/opentsdb/opentsdb.go @@ -50,8 +50,8 @@ func init() { tsdb.RegisterTsdbQueryEndpoint("opentsdb", NewOpenTsdbExecutor) } -func (e *OpenTsdbExecutor) Query(ctx context.Context, dsInfo *models.DataSource, queryContext *tsdb.TsdbQuery) *tsdb.BatchResult { - result := &tsdb.BatchResult{} +func (e *OpenTsdbExecutor) Query(ctx context.Context, dsInfo *models.DataSource, queryContext *tsdb.TsdbQuery) (*tsdb.Response, error) { + result := &tsdb.Response{} var tsdbQuery OpenTsdbQuery @@ -69,29 +69,26 @@ func (e *OpenTsdbExecutor) Query(ctx context.Context, dsInfo *models.DataSource, req, err := e.createRequest(dsInfo, tsdbQuery) if err != nil { - result.Error = err - return result + return nil, err } httpClient, err := dsInfo.GetHttpClient() if err != nil { - result.Error = err - return result + return nil, err } res, err := ctxhttp.Do(ctx, httpClient, req) if err != nil { - result.Error = err - return result + return nil, err } queryResult, err := e.parseResponse(tsdbQuery, res) if err != nil { - return result.WithError(err) + return nil, err } - result.QueryResults = queryResult - return result + result.Results = queryResult + return result, nil } func (e *OpenTsdbExecutor) createRequest(dsInfo *models.DataSource, data OpenTsdbQuery) (*http.Request, error) { diff --git a/pkg/tsdb/prometheus/prometheus.go b/pkg/tsdb/prometheus/prometheus.go index 9ca45109835..33219837281 100644 --- a/pkg/tsdb/prometheus/prometheus.go +++ b/pkg/tsdb/prometheus/prometheus.go @@ -80,17 +80,17 @@ func (e *PrometheusExecutor) getClient(dsInfo *models.DataSource) (apiv1.API, er return apiv1.NewAPI(client), nil } -func (e *PrometheusExecutor) Query(ctx context.Context, dsInfo *models.DataSource, tsdbQuery *tsdb.TsdbQuery) *tsdb.BatchResult { - result := &tsdb.BatchResult{} +func (e *PrometheusExecutor) Query(ctx context.Context, dsInfo *models.DataSource, tsdbQuery *tsdb.TsdbQuery) (*tsdb.Response, error) { + result := &tsdb.Response{} client, err := e.getClient(dsInfo) if err != nil { - return result.WithError(err) + return nil, err } query, err := parseQuery(tsdbQuery.Queries, tsdbQuery) if err != nil { - return result.WithError(err) + return nil, err } timeRange := apiv1.Range{ @@ -108,15 +108,15 @@ func (e *PrometheusExecutor) Query(ctx context.Context, dsInfo *models.DataSourc value, err := client.QueryRange(ctx, query.Expr, timeRange) if err != nil { - return result.WithError(err) + return nil, err } queryResult, err := parseResponse(value, query) if err != nil { - return result.WithError(err) + return nil, err } - result.QueryResults = queryResult - return result + result.Results = queryResult + return result, nil } func formatLegend(metric model.Metric, query *PrometheusQuery) string { diff --git a/pkg/tsdb/query_endpoint.go b/pkg/tsdb/query_endpoint.go index 74759959b08..4e4f1c9ec9e 100644 --- a/pkg/tsdb/query_endpoint.go +++ b/pkg/tsdb/query_endpoint.go @@ -8,7 +8,7 @@ import ( ) type TsdbQueryEndpoint interface { - Query(ctx context.Context, ds *models.DataSource, query *TsdbQuery) *BatchResult + Query(ctx context.Context, ds *models.DataSource, query *TsdbQuery) (*Response, error) } var registry map[string]GetTsdbQueryEndpointFn diff --git a/pkg/tsdb/request.go b/pkg/tsdb/request.go index 6aa5f0efd38..162116fb2fa 100644 --- a/pkg/tsdb/request.go +++ b/pkg/tsdb/request.go @@ -2,25 +2,17 @@ package tsdb import ( "context" + + "github.com/grafana/grafana/pkg/models" ) -type HandleRequestFunc func(ctx context.Context, req *TsdbQuery) (*Response, error) +type HandleRequestFunc func(ctx context.Context, dsInfo *models.DataSource, req *TsdbQuery) (*Response, error) -func HandleRequest(ctx context.Context, req *TsdbQuery) (*Response, error) { - //TODO niceify - ds := req.Queries[0].DataSource - endpoint, err := getTsdbQueryEndpointFor(ds) +func HandleRequest(ctx context.Context, dsInfo *models.DataSource, req *TsdbQuery) (*Response, error) { + endpoint, err := getTsdbQueryEndpointFor(dsInfo) if err != nil { return nil, err } - res := endpoint.Query(ctx, ds, req) - if res.Error != nil { - return nil, res.Error - } - - return &Response{ - Results: res.QueryResults, - BatchTimings: []*BatchTiming{res.Timings}, - }, nil + return endpoint.Query(ctx, dsInfo, req) } diff --git a/pkg/tsdb/testdata/testdata.go b/pkg/tsdb/testdata/testdata.go index 2ed19651130..a1ab250ad37 100644 --- a/pkg/tsdb/testdata/testdata.go +++ b/pkg/tsdb/testdata/testdata.go @@ -24,19 +24,19 @@ func init() { tsdb.RegisterTsdbQueryEndpoint("grafana-testdata-datasource", NewTestDataExecutor) } -func (e *TestDataExecutor) Query(ctx context.Context, dsInfo *models.DataSource, tsdbQuery *tsdb.TsdbQuery) *tsdb.BatchResult { - result := &tsdb.BatchResult{} - result.QueryResults = make(map[string]*tsdb.QueryResult) +func (e *TestDataExecutor) Query(ctx context.Context, dsInfo *models.DataSource, tsdbQuery *tsdb.TsdbQuery) (*tsdb.Response, error) { + result := &tsdb.Response{} + result.Results = make(map[string]*tsdb.QueryResult) for _, query := range tsdbQuery.Queries { scenarioId := query.Model.Get("scenarioId").MustString("random_walk") if scenario, exist := ScenarioRegistry[scenarioId]; exist { - result.QueryResults[query.RefId] = scenario.Handler(query, tsdbQuery) - result.QueryResults[query.RefId].RefId = query.RefId + result.Results[query.RefId] = scenario.Handler(query, tsdbQuery) + result.Results[query.RefId].RefId = query.RefId } else { e.log.Error("Scenario not found", "scenarioId", scenarioId) } } - return result + return result, nil } diff --git a/pkg/tsdb/tsdb_test.go b/pkg/tsdb/tsdb_test.go index 5e84a646a31..3ce85cd8c7f 100644 --- a/pkg/tsdb/tsdb_test.go +++ b/pkg/tsdb/tsdb_test.go @@ -19,7 +19,7 @@ func TestMetricQuery(t *testing.T) { fakeExecutor := registerFakeExecutor() fakeExecutor.Return("A", TimeSeriesSlice{&TimeSeries{Name: "argh"}}) - res, err := HandleRequest(context.TODO(), req) + res, err := HandleRequest(context.TODO(), &models.DataSource{Id: 1, Type: "test"}, req) So(err, ShouldBeNil) Convey("Should return query results", func() { @@ -40,18 +40,13 @@ func TestMetricQuery(t *testing.T) { fakeExecutor.Return("A", TimeSeriesSlice{&TimeSeries{Name: "argh"}}) fakeExecutor.Return("B", TimeSeriesSlice{&TimeSeries{Name: "barg"}}) - res, err := HandleRequest(context.TODO(), req) + res, err := HandleRequest(context.TODO(), &models.DataSource{Id: 1, Type: "test"}, req) So(err, ShouldBeNil) Convey("Should return query results", func() { So(len(res.Results), ShouldEqual, 2) So(res.Results["B"].Series[0].Name, ShouldEqual, "barg") }) - - Convey("Should have been batched in one request", func() { - So(len(res.BatchTimings), ShouldEqual, 1) - }) - }) Convey("When query uses data source of unknown type", t, func() { @@ -61,7 +56,7 @@ func TestMetricQuery(t *testing.T) { }, } - _, err := HandleRequest(context.TODO(), req) + _, err := HandleRequest(context.TODO(), &models.DataSource{Id: 12, Type: "testjughjgjg"}, req) So(err, ShouldNotBeNil) }) }