diff --git a/pkg/services/pluginsintegration/plugins_integration_test.go b/pkg/services/pluginsintegration/plugins_integration_test.go index cfe8b05a5e3..ad03c22c67a 100644 --- a/pkg/services/pluginsintegration/plugins_integration_test.go +++ b/pkg/services/pluginsintegration/plugins_integration_test.go @@ -78,7 +78,7 @@ func TestIntegrationPluginManager(t *testing.T) { idb := influxdb.ProvideService(hcp, features) lk := loki.ProvideService(hcp, features, tracer) otsdb := opentsdb.ProvideService(hcp) - pr := prometheus.ProvideService(hcp, cfg, features) + pr := prometheus.ProvideService(hcp, cfg) tmpo := tempo.ProvideService(hcp) td := testdatasource.ProvideService() pg := postgres.ProvideService(cfg) diff --git a/pkg/tsdb/prometheus/healthcheck_test.go b/pkg/tsdb/prometheus/healthcheck_test.go index eaf38c317e7..88d55c25ca3 100644 --- a/pkg/tsdb/prometheus/healthcheck_test.go +++ b/pkg/tsdb/prometheus/healthcheck_test.go @@ -11,9 +11,9 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana-plugin-sdk-go/backend/datasource" "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient" - "github.com/grafana/grafana/pkg/services/featuremgmt" - "github.com/grafana/grafana/pkg/setting" "github.com/stretchr/testify/assert" + + "github.com/grafana/grafana/pkg/setting" ) type healthCheckProvider[T http.RoundTripper] struct { @@ -84,7 +84,7 @@ func Test_healthcheck(t *testing.T) { t.Run("should do a successful health check", func(t *testing.T) { httpProvider := getMockProvider[*healthCheckSuccessRoundTripper]() s := &Service{ - im: datasource.NewInstanceManager(newInstanceSettings(httpProvider, &setting.Cfg{}, &featuremgmt.FeatureManager{}, backend.NewLoggerWith("logger", "test"))), + im: datasource.NewInstanceManager(newInstanceSettings(httpProvider, &setting.Cfg{}, backend.NewLoggerWith("logger", "test"))), } req := &backend.CheckHealthRequest{ @@ -100,7 +100,7 @@ func Test_healthcheck(t *testing.T) { t.Run("should return an error for an unsuccessful health check", func(t *testing.T) { httpProvider := getMockProvider[*healthCheckFailRoundTripper]() s := &Service{ - im: datasource.NewInstanceManager(newInstanceSettings(httpProvider, &setting.Cfg{}, &featuremgmt.FeatureManager{}, backend.NewLoggerWith("logger", "test"))), + im: datasource.NewInstanceManager(newInstanceSettings(httpProvider, &setting.Cfg{}, backend.NewLoggerWith("logger", "test"))), } req := &backend.CheckHealthRequest{ diff --git a/pkg/tsdb/prometheus/heuristics_test.go b/pkg/tsdb/prometheus/heuristics_test.go index 70de2738dfc..89f1d5b9a88 100644 --- a/pkg/tsdb/prometheus/heuristics_test.go +++ b/pkg/tsdb/prometheus/heuristics_test.go @@ -14,7 +14,7 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana-plugin-sdk-go/backend/datasource" "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient" - "github.com/grafana/grafana/pkg/services/featuremgmt" + "github.com/grafana/grafana/pkg/setting" ) @@ -52,7 +52,7 @@ func Test_GetHeuristics(t *testing.T) { //httpProvider := getHeuristicsMockProvider(&rt) httpProvider := newHeuristicsSDKProvider(rt) s := &Service{ - im: datasource.NewInstanceManager(newInstanceSettings(httpProvider, &setting.Cfg{}, &featuremgmt.FeatureManager{}, backend.NewLoggerWith("logger", "test"))), + im: datasource.NewInstanceManager(newInstanceSettings(httpProvider, &setting.Cfg{}, backend.NewLoggerWith("logger", "test"))), } req := HeuristicsRequest{ @@ -72,7 +72,7 @@ func Test_GetHeuristics(t *testing.T) { } httpProvider := newHeuristicsSDKProvider(rt) s := &Service{ - im: datasource.NewInstanceManager(newInstanceSettings(httpProvider, &setting.Cfg{}, &featuremgmt.FeatureManager{}, backend.NewLoggerWith("logger", "test"))), + im: datasource.NewInstanceManager(newInstanceSettings(httpProvider, &setting.Cfg{}, backend.NewLoggerWith("logger", "test"))), } req := HeuristicsRequest{ diff --git a/pkg/tsdb/prometheus/prometheus.go b/pkg/tsdb/prometheus/prometheus.go index 9c1a0db794a..ab91aaf7394 100644 --- a/pkg/tsdb/prometheus/prometheus.go +++ b/pkg/tsdb/prometheus/prometheus.go @@ -15,7 +15,7 @@ import ( apiv1 "github.com/prometheus/client_golang/api/prometheus/v1" "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient" - "github.com/grafana/grafana/pkg/services/featuremgmt" + "github.com/grafana/grafana/pkg/setting" "github.com/grafana/grafana/pkg/tsdb/prometheus/client" "github.com/grafana/grafana/pkg/tsdb/prometheus/instrumentation" @@ -24,9 +24,8 @@ import ( ) type Service struct { - im instancemgmt.InstanceManager - features featuremgmt.FeatureToggles - logger log.Logger + im instancemgmt.InstanceManager + logger log.Logger } type instance struct { @@ -35,17 +34,16 @@ type instance struct { versionCache *cache.Cache } -func ProvideService(httpClientProvider *httpclient.Provider, cfg *setting.Cfg, features featuremgmt.FeatureToggles) *Service { +func ProvideService(httpClientProvider *httpclient.Provider, cfg *setting.Cfg) *Service { plog := backend.NewLoggerWith("logger", "tsdb.prometheus") plog.Debug("Initializing") return &Service{ - im: datasource.NewInstanceManager(newInstanceSettings(httpClientProvider, cfg, features, plog)), - features: features, - logger: plog, + im: datasource.NewInstanceManager(newInstanceSettings(httpClientProvider, cfg, plog)), + logger: plog, } } -func newInstanceSettings(httpClientProvider *httpclient.Provider, cfg *setting.Cfg, features featuremgmt.FeatureToggles, log log.Logger) datasource.InstanceFactoryFunc { +func newInstanceSettings(httpClientProvider *httpclient.Provider, cfg *setting.Cfg, log log.Logger) datasource.InstanceFactoryFunc { return func(ctx context.Context, settings backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) { // Creates a http roundTripper. opts, err := client.CreateTransportOptions(ctx, settings, cfg, log) @@ -58,7 +56,7 @@ func newInstanceSettings(httpClientProvider *httpclient.Provider, cfg *setting.C } // New version using custom client and better response parsing - qd, err := querydata.New(httpClient, features, settings, log) + qd, err := querydata.New(httpClient, settings, log) if err != nil { return nil, err } diff --git a/pkg/tsdb/prometheus/prometheus_test.go b/pkg/tsdb/prometheus/prometheus_test.go index 735ed25e38c..02307493664 100644 --- a/pkg/tsdb/prometheus/prometheus_test.go +++ b/pkg/tsdb/prometheus/prometheus_test.go @@ -10,9 +10,9 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana-plugin-sdk-go/backend/datasource" "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient" - "github.com/grafana/grafana/pkg/services/featuremgmt" - "github.com/grafana/grafana/pkg/setting" "github.com/stretchr/testify/require" + + "github.com/grafana/grafana/pkg/setting" ) type fakeSender struct{} @@ -69,7 +69,7 @@ func TestService(t *testing.T) { f := &fakeHTTPClientProvider{} httpProvider := getMockPromTestSDKProvider(f) service := &Service{ - im: datasource.NewInstanceManager(newInstanceSettings(httpProvider, &setting.Cfg{}, &featuremgmt.FeatureManager{}, backend.NewLoggerWith("logger", "test"))), + im: datasource.NewInstanceManager(newInstanceSettings(httpProvider, &setting.Cfg{}, backend.NewLoggerWith("logger", "test"))), } req := &backend.CallResourceRequest{ diff --git a/pkg/tsdb/prometheus/querydata/request.go b/pkg/tsdb/prometheus/querydata/request.go index ceb5e3877d9..1282354207e 100644 --- a/pkg/tsdb/prometheus/querydata/request.go +++ b/pkg/tsdb/prometheus/querydata/request.go @@ -15,7 +15,6 @@ import ( "github.com/grafana/grafana-plugin-sdk-go/backend/log" "github.com/grafana/grafana-plugin-sdk-go/backend/tracing" - "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/tsdb/intervalv2" "github.com/grafana/grafana/pkg/tsdb/prometheus/client" "github.com/grafana/grafana/pkg/tsdb/prometheus/models" @@ -44,14 +43,11 @@ type QueryData struct { ID int64 URL string TimeInterval string - enableDataplane bool - enableScope bool exemplarSampler func() exemplar.Sampler } func New( httpClient *http.Client, - features featuremgmt.FeatureToggles, settings backend.DataSourceInstanceSettings, plog log.Logger, ) (*QueryData, error) { @@ -84,8 +80,6 @@ func New( ID: settings.ID, URL: settings.URL, exemplarSampler: exemplarSampler, - enableDataplane: features.IsEnabledGlobally(featuremgmt.FlagPrometheusDataplane), - enableScope: features.IsEnabledGlobally(featuremgmt.FlagPromQLScope), }, nil } @@ -95,13 +89,17 @@ func (s *QueryData) Execute(ctx context.Context, req *backend.QueryDataRequest) Responses: backend.Responses{}, } + cfg := backend.GrafanaConfigFromContext(ctx) + hasPromQLScopeFeatureFlag := cfg.FeatureToggles().IsEnabled("promQLScope") + hasPrometheusDataplaneFeatureFlag := cfg.FeatureToggles().IsEnabled("prometheusDataplane") + for _, q := range req.Queries { - query, err := models.Parse(q, s.TimeInterval, s.intervalCalculator, fromAlert, s.enableScope) + query, err := models.Parse(q, s.TimeInterval, s.intervalCalculator, fromAlert, hasPromQLScopeFeatureFlag) if err != nil { return &result, err } - r := s.fetch(ctx, s.client, query) + r := s.fetch(ctx, s.client, query, hasPrometheusDataplaneFeatureFlag) if r == nil { s.log.FromContext(ctx).Debug("Received nil response from runQuery", "query", query.Expr) continue @@ -112,7 +110,7 @@ func (s *QueryData) Execute(ctx context.Context, req *backend.QueryDataRequest) return &result, nil } -func (s *QueryData) fetch(ctx context.Context, client *client.Client, q *models.Query) *backend.DataResponse { +func (s *QueryData) fetch(ctx context.Context, client *client.Client, q *models.Query, enablePrometheusDataplane bool) *backend.DataResponse { traceCtx, end := s.trace(ctx, q) defer end() @@ -125,14 +123,14 @@ func (s *QueryData) fetch(ctx context.Context, client *client.Client, q *models. } if q.InstantQuery { - res := s.instantQuery(traceCtx, client, q) + res := s.instantQuery(traceCtx, client, q, enablePrometheusDataplane) dr.Error = res.Error dr.Frames = res.Frames dr.Status = res.Status } if q.RangeQuery { - res := s.rangeQuery(traceCtx, client, q) + res := s.rangeQuery(traceCtx, client, q, enablePrometheusDataplane) if res.Error != nil { if dr.Error == nil { dr.Error = res.Error @@ -147,7 +145,7 @@ func (s *QueryData) fetch(ctx context.Context, client *client.Client, q *models. } if q.ExemplarQuery { - res := s.exemplarQuery(traceCtx, client, q) + res := s.exemplarQuery(traceCtx, client, q, enablePrometheusDataplane) if res.Error != nil { // If exemplar query returns error, we want to only log it and // continue with other results processing @@ -159,7 +157,7 @@ func (s *QueryData) fetch(ctx context.Context, client *client.Client, q *models. return dr } -func (s *QueryData) rangeQuery(ctx context.Context, c *client.Client, q *models.Query) backend.DataResponse { +func (s *QueryData) rangeQuery(ctx context.Context, c *client.Client, q *models.Query, enablePrometheusDataplaneFlag bool) backend.DataResponse { res, err := c.QueryRange(ctx, q) if err != nil { return backend.DataResponse{ @@ -175,10 +173,10 @@ func (s *QueryData) rangeQuery(ctx context.Context, c *client.Client, q *models. } }() - return s.parseResponse(ctx, q, res) + return s.parseResponse(ctx, q, res, enablePrometheusDataplaneFlag) } -func (s *QueryData) instantQuery(ctx context.Context, c *client.Client, q *models.Query) backend.DataResponse { +func (s *QueryData) instantQuery(ctx context.Context, c *client.Client, q *models.Query, enablePrometheusDataplaneFlag bool) backend.DataResponse { res, err := c.QueryInstant(ctx, q) if err != nil { return backend.DataResponse{ @@ -201,10 +199,10 @@ func (s *QueryData) instantQuery(ctx context.Context, c *client.Client, q *model } }() - return s.parseResponse(ctx, q, res) + return s.parseResponse(ctx, q, res, enablePrometheusDataplaneFlag) } -func (s *QueryData) exemplarQuery(ctx context.Context, c *client.Client, q *models.Query) backend.DataResponse { +func (s *QueryData) exemplarQuery(ctx context.Context, c *client.Client, q *models.Query, enablePrometheusDataplaneFlag bool) backend.DataResponse { res, err := c.QueryExemplars(ctx, q) if err != nil { return backend.DataResponse{ @@ -218,7 +216,7 @@ func (s *QueryData) exemplarQuery(ctx context.Context, c *client.Client, q *mode s.log.Warn("Failed to close response body", "error", err) } }() - return s.parseResponse(ctx, q, res) + return s.parseResponse(ctx, q, res, enablePrometheusDataplaneFlag) } func (s *QueryData) trace(ctx context.Context, q *models.Query) (context.Context, func()) { diff --git a/pkg/tsdb/prometheus/querydata/request_test.go b/pkg/tsdb/prometheus/querydata/request_test.go index 40d3d783b76..488d676f25e 100644 --- a/pkg/tsdb/prometheus/querydata/request_test.go +++ b/pkg/tsdb/prometheus/querydata/request_test.go @@ -15,7 +15,6 @@ import ( p "github.com/prometheus/common/model" "github.com/stretchr/testify/require" - "github.com/grafana/grafana/pkg/services/featuremgmt" "github.com/grafana/grafana/pkg/tsdb/prometheus/kinds/dataquery" "github.com/grafana/kindsys" @@ -442,7 +441,6 @@ func setup() (*testContext, error) { JSONData: json.RawMessage(`{"timeInterval": "15s"}`), } - features := featuremgmt.WithFeatures() opts, err := client.CreateTransportOptions(context.Background(), settings, &setting.Cfg{}, log.New()) if err != nil { return nil, err @@ -453,7 +451,7 @@ func setup() (*testContext, error) { return nil, err } - queryData, _ := querydata.New(httpClient, features, settings, log.New()) + queryData, _ := querydata.New(httpClient, settings, log.New()) return &testContext{ httpProvider: httpProvider, diff --git a/pkg/tsdb/prometheus/querydata/response.go b/pkg/tsdb/prometheus/querydata/response.go index be09ff3e575..dd0e5f3f31b 100644 --- a/pkg/tsdb/prometheus/querydata/response.go +++ b/pkg/tsdb/prometheus/querydata/response.go @@ -18,7 +18,7 @@ import ( "github.com/grafana/grafana/pkg/util/converter" ) -func (s *QueryData) parseResponse(ctx context.Context, q *models.Query, res *http.Response) backend.DataResponse { +func (s *QueryData) parseResponse(ctx context.Context, q *models.Query, res *http.Response, enablePrometheusDataplaneFlag bool) backend.DataResponse { defer func() { if err := res.Body.Close(); err != nil { s.log.FromContext(ctx).Error("Failed to close response body", "err", err) @@ -30,7 +30,7 @@ func (s *QueryData) parseResponse(ctx context.Context, q *models.Query, res *htt iter := jsoniter.Parse(jsoniter.ConfigDefault, res.Body, 1024) r := converter.ReadPrometheusStyleResult(iter, converter.Options{ - Dataplane: s.enableDataplane, + Dataplane: enablePrometheusDataplaneFlag, }) r.Status = backend.Status(res.StatusCode) @@ -41,7 +41,7 @@ func (s *QueryData) parseResponse(ctx context.Context, q *models.Query, res *htt // The ExecutedQueryString can be viewed in QueryInspector in UI for i, frame := range r.Frames { - addMetadataToMultiFrame(q, frame, s.enableDataplane) + addMetadataToMultiFrame(q, frame, enablePrometheusDataplaneFlag) if i == 0 { frame.Meta.ExecutedQueryString = executedQueryString(q) } diff --git a/pkg/tsdb/prometheus/querydata/response_test.go b/pkg/tsdb/prometheus/querydata/response_test.go index e449f3610d8..62d27222d8e 100644 --- a/pkg/tsdb/prometheus/querydata/response_test.go +++ b/pkg/tsdb/prometheus/querydata/response_test.go @@ -19,7 +19,7 @@ func TestQueryData_parseResponse(t *testing.T) { t.Run("resultType is before result the field must parsed normally", func(t *testing.T) { resBody := `{"data":{"resultType":"vector", "result":[{"metric":{"__name__":"some_name","environment":"some_env","id":"some_id","instance":"some_instance:1234","job":"some_job","name":"another_name","region":"some_region"},"value":[1.1,"2"]}]},"status":"success"}` res := &http.Response{Body: io.NopCloser(bytes.NewBufferString(resBody))} - result := qd.parseResponse(context.Background(), &models.Query{}, res) + result := qd.parseResponse(context.Background(), &models.Query{}, res, false) assert.Nil(t, result.Error) assert.Len(t, result.Frames, 1) }) @@ -27,7 +27,7 @@ func TestQueryData_parseResponse(t *testing.T) { t.Run("resultType is after the result field must parsed normally", func(t *testing.T) { resBody := `{"data":{"result":[{"metric":{"__name__":"some_name","environment":"some_env","id":"some_id","instance":"some_instance:1234","job":"some_job","name":"another_name","region":"some_region"},"value":[1.1,"2"]}],"resultType":"vector"},"status":"success"}` res := &http.Response{Body: io.NopCloser(bytes.NewBufferString(resBody))} - result := qd.parseResponse(context.Background(), &models.Query{}, res) + result := qd.parseResponse(context.Background(), &models.Query{}, res, false) assert.Nil(t, result.Error) assert.Len(t, result.Frames, 1) }) @@ -35,7 +35,7 @@ func TestQueryData_parseResponse(t *testing.T) { t.Run("no resultType is existed in the data", func(t *testing.T) { resBody := `{"data":{"result":[{"metric":{"__name__":"some_name","environment":"some_env","id":"some_id","instance":"some_instance:1234","job":"some_job","name":"another_name","region":"some_region"},"value":[1.1,"2"]}]},"status":"success"}` res := &http.Response{Body: io.NopCloser(bytes.NewBufferString(resBody))} - result := qd.parseResponse(context.Background(), &models.Query{}, res) + result := qd.parseResponse(context.Background(), &models.Query{}, res, false) assert.Error(t, result.Error) assert.Equal(t, result.Error.Error(), "no resultType found") }) @@ -43,7 +43,7 @@ func TestQueryData_parseResponse(t *testing.T) { t.Run("resultType is set as empty string before result", func(t *testing.T) { resBody := `{"data":{"resultType":"", "result":[{"metric":{"__name__":"some_name","environment":"some_env","id":"some_id","instance":"some_instance:1234","job":"some_job","name":"another_name","region":"some_region"},"value":[1.1,"2"]}]},"status":"success"}` res := &http.Response{Body: io.NopCloser(bytes.NewBufferString(resBody))} - result := qd.parseResponse(context.Background(), &models.Query{}, res) + result := qd.parseResponse(context.Background(), &models.Query{}, res, false) assert.Error(t, result.Error) assert.Equal(t, result.Error.Error(), "unknown result type: ") }) @@ -51,7 +51,7 @@ func TestQueryData_parseResponse(t *testing.T) { t.Run("resultType is set as empty string after result", func(t *testing.T) { resBody := `{"data":{"result":[{"metric":{"__name__":"some_name","environment":"some_env","id":"some_id","instance":"some_instance:1234","job":"some_job","name":"another_name","region":"some_region"},"value":[1.1,"2"]}],"resultType":""},"status":"success"}` res := &http.Response{Body: io.NopCloser(bytes.NewBufferString(resBody))} - result := qd.parseResponse(context.Background(), &models.Query{}, res) + result := qd.parseResponse(context.Background(), &models.Query{}, res, false) assert.Error(t, result.Error) assert.Equal(t, result.Error.Error(), "unknown result type: ") })