From 771f21ed09f4b660273e106849daccb7f5fe3170 Mon Sep 17 00:00:00 2001 From: Marcus Efraimsson Date: Fri, 25 Oct 2019 15:28:26 +0200 Subject: [PATCH] api: new v2 metrics query endpoint Requests to endpoint will currently will error unless expressions feature flag is true. Co-authored-by: Sofia Papagiannaki --- pkg/api/api.go | 1 + pkg/api/metrics.go | 65 ++++++++++++++++++++++++++++++++ pkg/plugins/datasource_plugin.go | 12 +----- pkg/setting/setting.go | 8 ++++ 4 files changed, 76 insertions(+), 10 deletions(-) diff --git a/pkg/api/api.go b/pkg/api/api.go index 9fe67937bd4..9308403b276 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -327,6 +327,7 @@ func (hs *HTTPServer) registerRoutes() { // metrics apiRoute.Post("/tsdb/query", bind(dtos.MetricRequest{}), Wrap(hs.QueryMetrics)) + apiRoute.Post("/tsdb/query/v2", bind(dtos.MetricRequest{}), Wrap(hs.QueryMetricsV2)) apiRoute.Get("/tsdb/testdata/scenarios", Wrap(GetTestDataScenarios)) apiRoute.Get("/tsdb/testdata/gensql", reqGrafanaAdmin, Wrap(GenerateSQLTestData)) apiRoute.Get("/tsdb/testdata/random-walk", Wrap(GetTestDataRandomWalk)) diff --git a/pkg/api/metrics.go b/pkg/api/metrics.go index fb13e5a1f22..4a0a90c1030 100644 --- a/pkg/api/metrics.go +++ b/pkg/api/metrics.go @@ -4,6 +4,8 @@ import ( "context" "sort" + "github.com/grafana/grafana/pkg/setting" + "github.com/grafana/grafana/pkg/api/dtos" "github.com/grafana/grafana/pkg/bus" "github.com/grafana/grafana/pkg/components/simplejson" @@ -13,6 +15,69 @@ import ( "github.com/grafana/grafana/pkg/util" ) +// POST /api/tsdb/query/v2 +func (hs *HTTPServer) QueryMetricsV2(c *m.ReqContext, reqDto dtos.MetricRequest) Response { + if !setting.IsExpressionsEnabled() { + return Error(404, "Expressions feature toggle is not enabled", nil) + } + + timeRange := tsdb.NewTimeRange(reqDto.From, reqDto.To) + + if len(reqDto.Queries) == 0 { + return Error(400, "No queries found in query", nil) + } + + var datasourceID int64 + for _, query := range reqDto.Queries { + name, err := query.Get("datasource").String() + if err != nil { + return Error(500, "datasource missing name", err) + } + datasourceID, err = query.Get("datasourceId").Int64() + if err != nil { + return Error(400, "GEL datasource missing ID", nil) + } + if name == "-- GEL --" { + break + } + } + ds, err := hs.DatasourceCache.GetDatasource(datasourceID, c.SignedInUser, c.SkipCache) + if err != nil { + if err == m.ErrDataSourceAccessDenied { + return Error(403, "Access denied to datasource", err) + } + return Error(500, "Unable to load datasource meta data", err) + } + + request := &tsdb.TsdbQuery{TimeRange: timeRange, Debug: reqDto.Debug} + + for _, query := range reqDto.Queries { + request.Queries = append(request.Queries, &tsdb.Query{ + RefId: query.Get("refId").MustString("A"), + MaxDataPoints: query.Get("maxDataPoints").MustInt64(100), + IntervalMs: query.Get("intervalMs").MustInt64(1000), + Model: query, + DataSource: ds, + }) + } + + resp, err := tsdb.HandleRequest(c.Req.Context(), ds, request) + if err != nil { + return Error(500, "Metric request error", err) + } + + statusCode := 200 + for _, res := range resp.Results { + if res.Error != nil { + res.ErrorString = res.Error.Error() + resp.Message = res.ErrorString + statusCode = 400 + } + } + + return JSON(statusCode, &resp) +} + // POST /api/tsdb/query func (hs *HTTPServer) QueryMetrics(c *m.ReqContext, reqDto dtos.MetricRequest) Response { timeRange := tsdb.NewTimeRange(reqDto.From, reqDto.To) diff --git a/pkg/plugins/datasource_plugin.go b/pkg/plugins/datasource_plugin.go index 6d4a6a8aaf7..2b3cf742ff8 100644 --- a/pkg/plugins/datasource_plugin.go +++ b/pkg/plugins/datasource_plugin.go @@ -45,21 +45,13 @@ type DataSourcePlugin struct { client *plugin.Client } -func isExpressionsEnabled() bool { - v, ok := setting.FeatureToggles["expressions"] - if !ok { - return false - } - return v -} - func (p *DataSourcePlugin) Load(decoder *json.Decoder, pluginDir string) error { if err := decoder.Decode(&p); err != nil { return err } - if !p.isVersionOne() && !isExpressionsEnabled() { - return errors.New("A plugin version 2 was found but expressions feature toggle are not enabled") + if !p.isVersionOne() && !setting.IsExpressionsEnabled() { + return errors.New("A plugin version 2 was found but expressions feature toggle is not enabled") } if err := p.registerPlugin(pluginDir); err != nil { diff --git a/pkg/setting/setting.go b/pkg/setting/setting.go index 7d1208662c9..a83301dab8c 100644 --- a/pkg/setting/setting.go +++ b/pkg/setting/setting.go @@ -1094,3 +1094,11 @@ func (cfg *Cfg) LogConfigSources() { cfg.Logger.Info("Path Provisioning", "path", cfg.ProvisioningPath) cfg.Logger.Info("App mode " + Env) } + +func IsExpressionsEnabled() bool { + v, ok := FeatureToggles["expressions"] + if !ok { + return false + } + return v +}