mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Plugins: Remove pluginsInstrumentationStatusSource feature toggle (#83067)
* Plugins: Remove pluginsInstrumentationStatusSource feature toggle * update tests * Inline pluginRequestDurationWithLabels, pluginRequestCounterWithLabels, pluginRequestDurationSecondsWithLabels
This commit is contained in:
parent
b6b5935992
commit
68fe045ec7
@ -157,7 +157,6 @@ Experimental features might be changed or removed without prior notice.
|
|||||||
| `kubernetesSnapshots` | Routes snapshot requests from /api to the /apis endpoint |
|
| `kubernetesSnapshots` | Routes snapshot requests from /api to the /apis endpoint |
|
||||||
| `teamHttpHeaders` | Enables datasources to apply team headers to the client requests |
|
| `teamHttpHeaders` | Enables datasources to apply team headers to the client requests |
|
||||||
| `cachingOptimizeSerializationMemoryUsage` | If enabled, the caching backend gradually serializes query responses for the cache, comparing against the configured `[caching]max_value_mb` value as it goes. This can can help prevent Grafana from running out of memory while attempting to cache very large query responses. |
|
| `cachingOptimizeSerializationMemoryUsage` | If enabled, the caching backend gradually serializes query responses for the cache, comparing against the configured `[caching]max_value_mb` value as it goes. This can can help prevent Grafana from running out of memory while attempting to cache very large query responses. |
|
||||||
| `pluginsInstrumentationStatusSource` | Include a status source label for plugin request metrics and logs |
|
|
||||||
| `prometheusPromQAIL` | Prometheus and AI/ML to assist users in creating a query |
|
| `prometheusPromQAIL` | Prometheus and AI/ML to assist users in creating a query |
|
||||||
| `alertmanagerRemoteSecondary` | Enable Grafana to sync configuration and state with a remote Alertmanager. |
|
| `alertmanagerRemoteSecondary` | Enable Grafana to sync configuration and state with a remote Alertmanager. |
|
||||||
| `alertmanagerRemotePrimary` | Enable Grafana to have a remote Alertmanager instance as the primary Alertmanager. |
|
| `alertmanagerRemotePrimary` | Enable Grafana to have a remote Alertmanager instance as the primary Alertmanager. |
|
||||||
|
@ -139,7 +139,6 @@ export interface FeatureToggles {
|
|||||||
awsDatasourcesNewFormStyling?: boolean;
|
awsDatasourcesNewFormStyling?: boolean;
|
||||||
cachingOptimizeSerializationMemoryUsage?: boolean;
|
cachingOptimizeSerializationMemoryUsage?: boolean;
|
||||||
panelTitleSearchInV1?: boolean;
|
panelTitleSearchInV1?: boolean;
|
||||||
pluginsInstrumentationStatusSource?: boolean;
|
|
||||||
managedPluginsInstall?: boolean;
|
managedPluginsInstall?: boolean;
|
||||||
prometheusPromQAIL?: boolean;
|
prometheusPromQAIL?: boolean;
|
||||||
addFieldFromCalculationStatFunctions?: boolean;
|
addFieldFromCalculationStatFunctions?: boolean;
|
||||||
|
@ -905,13 +905,6 @@ var (
|
|||||||
Stage: FeatureStageExperimental,
|
Stage: FeatureStageExperimental,
|
||||||
Owner: grafanaBackendPlatformSquad,
|
Owner: grafanaBackendPlatformSquad,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Name: "pluginsInstrumentationStatusSource",
|
|
||||||
Description: "Include a status source label for plugin request metrics and logs",
|
|
||||||
FrontendOnly: false,
|
|
||||||
Stage: FeatureStageExperimental,
|
|
||||||
Owner: grafanaPluginsPlatformSquad,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
Name: "managedPluginsInstall",
|
Name: "managedPluginsInstall",
|
||||||
Description: "Install managed plugins directly from plugins catalog",
|
Description: "Install managed plugins directly from plugins catalog",
|
||||||
|
@ -120,7 +120,6 @@ teamHttpHeaders,experimental,@grafana/identity-access-team,false,false,false
|
|||||||
awsDatasourcesNewFormStyling,preview,@grafana/aws-datasources,false,false,true
|
awsDatasourcesNewFormStyling,preview,@grafana/aws-datasources,false,false,true
|
||||||
cachingOptimizeSerializationMemoryUsage,experimental,@grafana/grafana-operator-experience-squad,false,false,false
|
cachingOptimizeSerializationMemoryUsage,experimental,@grafana/grafana-operator-experience-squad,false,false,false
|
||||||
panelTitleSearchInV1,experimental,@grafana/backend-platform,true,false,false
|
panelTitleSearchInV1,experimental,@grafana/backend-platform,true,false,false
|
||||||
pluginsInstrumentationStatusSource,experimental,@grafana/plugins-platform-backend,false,false,false
|
|
||||||
managedPluginsInstall,preview,@grafana/plugins-platform-backend,false,false,false
|
managedPluginsInstall,preview,@grafana/plugins-platform-backend,false,false,false
|
||||||
prometheusPromQAIL,experimental,@grafana/observability-metrics,false,false,true
|
prometheusPromQAIL,experimental,@grafana/observability-metrics,false,false,true
|
||||||
addFieldFromCalculationStatFunctions,preview,@grafana/dataviz-squad,false,false,true
|
addFieldFromCalculationStatFunctions,preview,@grafana/dataviz-squad,false,false,true
|
||||||
|
|
@ -491,10 +491,6 @@ const (
|
|||||||
// Enable searching for dashboards using panel title in search v1
|
// Enable searching for dashboards using panel title in search v1
|
||||||
FlagPanelTitleSearchInV1 = "panelTitleSearchInV1"
|
FlagPanelTitleSearchInV1 = "panelTitleSearchInV1"
|
||||||
|
|
||||||
// FlagPluginsInstrumentationStatusSource
|
|
||||||
// Include a status source label for plugin request metrics and logs
|
|
||||||
FlagPluginsInstrumentationStatusSource = "pluginsInstrumentationStatusSource"
|
|
||||||
|
|
||||||
// FlagManagedPluginsInstall
|
// FlagManagedPluginsInstall
|
||||||
// Install managed plugins directly from plugins catalog
|
// Install managed plugins directly from plugins catalog
|
||||||
FlagManagedPluginsInstall = "managedPluginsInstall"
|
FlagManagedPluginsInstall = "managedPluginsInstall"
|
||||||
|
@ -82,7 +82,8 @@
|
|||||||
"metadata": {
|
"metadata": {
|
||||||
"name": "pluginsInstrumentationStatusSource",
|
"name": "pluginsInstrumentationStatusSource",
|
||||||
"resourceVersion": "1708108588074",
|
"resourceVersion": "1708108588074",
|
||||||
"creationTimestamp": "2024-02-16T18:36:28Z"
|
"creationTimestamp": "2024-02-16T18:36:28Z",
|
||||||
|
"deletionTimestamp": "2024-02-19T14:18:02Z"
|
||||||
},
|
},
|
||||||
"spec": {
|
"spec": {
|
||||||
"description": "Include a status source label for plugin request metrics and logs",
|
"description": "Include a status source label for plugin request metrics and logs",
|
||||||
|
@ -50,9 +50,7 @@ func (m *LoggerMiddleware) logRequest(ctx context.Context, fn func(ctx context.C
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
logParams = append(logParams, "error", err)
|
logParams = append(logParams, "error", err)
|
||||||
}
|
}
|
||||||
if m.features.IsEnabled(ctx, featuremgmt.FlagPluginsInstrumentationStatusSource) {
|
logParams = append(logParams, "statusSource", pluginrequestmeta.StatusSourceFromContext(ctx))
|
||||||
logParams = append(logParams, "statusSource", pluginrequestmeta.StatusSourceFromContext(ctx))
|
|
||||||
}
|
|
||||||
|
|
||||||
ctxLogger := m.logger.FromContext(ctx)
|
ctxLogger := m.logger.FromContext(ctx)
|
||||||
logFunc := ctxLogger.Info
|
logFunc := ctxLogger.Info
|
||||||
@ -81,9 +79,11 @@ func (m *LoggerMiddleware) QueryData(ctx context.Context, req *backend.QueryData
|
|||||||
ctxLogger := m.logger.FromContext(ctx)
|
ctxLogger := m.logger.FromContext(ctx)
|
||||||
for refID, dr := range resp.Responses {
|
for refID, dr := range resp.Responses {
|
||||||
if dr.Error != nil {
|
if dr.Error != nil {
|
||||||
logParams := []any{"refID", refID, "status", int(dr.Status), "error", dr.Error}
|
logParams := []any{
|
||||||
if m.features.IsEnabled(ctx, featuremgmt.FlagPluginsInstrumentationStatusSource) {
|
"refID", refID,
|
||||||
logParams = append(logParams, "statusSource", pluginrequestmeta.StatusSourceFromPluginErrorSource(dr.ErrorSource))
|
"status", int(dr.Status),
|
||||||
|
"error", dr.Error,
|
||||||
|
"statusSource", pluginrequestmeta.StatusSourceFromPluginErrorSource(dr.ErrorSource),
|
||||||
}
|
}
|
||||||
ctxLogger.Error("Partial data response error", logParams...)
|
ctxLogger.Error("Partial data response error", logParams...)
|
||||||
}
|
}
|
||||||
|
@ -32,10 +32,7 @@ type MetricsMiddleware struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newMetricsMiddleware(promRegisterer prometheus.Registerer, pluginRegistry registry.Service, features featuremgmt.FeatureToggles) *MetricsMiddleware {
|
func newMetricsMiddleware(promRegisterer prometheus.Registerer, pluginRegistry registry.Service, features featuremgmt.FeatureToggles) *MetricsMiddleware {
|
||||||
var additionalLabels []string
|
additionalLabels := []string{"status_source"}
|
||||||
if features.IsEnabledGlobally(featuremgmt.FlagPluginsInstrumentationStatusSource) {
|
|
||||||
additionalLabels = []string{"status_source"}
|
|
||||||
}
|
|
||||||
pluginRequestCounter := prometheus.NewCounterVec(prometheus.CounterOpts{
|
pluginRequestCounter := prometheus.NewCounterVec(prometheus.CounterOpts{
|
||||||
Namespace: "grafana",
|
Namespace: "grafana",
|
||||||
Name: "plugin_request_total",
|
Name: "plugin_request_total",
|
||||||
@ -119,19 +116,11 @@ func (m *MetricsMiddleware) instrumentPluginRequest(ctx context.Context, pluginC
|
|||||||
status, err := fn(ctx)
|
status, err := fn(ctx)
|
||||||
elapsed := time.Since(start)
|
elapsed := time.Since(start)
|
||||||
|
|
||||||
pluginRequestDurationLabels := []string{pluginCtx.PluginID, endpoint, target}
|
statusSource := pluginrequestmeta.StatusSourceFromContext(ctx)
|
||||||
pluginRequestCounterLabels := []string{pluginCtx.PluginID, endpoint, status.String(), target}
|
|
||||||
pluginRequestDurationSecondsLabels := []string{"grafana-backend", pluginCtx.PluginID, endpoint, status.String(), target}
|
|
||||||
if m.features.IsEnabled(ctx, featuremgmt.FlagPluginsInstrumentationStatusSource) {
|
|
||||||
statusSource := pluginrequestmeta.StatusSourceFromContext(ctx)
|
|
||||||
pluginRequestDurationLabels = append(pluginRequestDurationLabels, string(statusSource))
|
|
||||||
pluginRequestCounterLabels = append(pluginRequestCounterLabels, string(statusSource))
|
|
||||||
pluginRequestDurationSecondsLabels = append(pluginRequestDurationSecondsLabels, string(statusSource))
|
|
||||||
}
|
|
||||||
|
|
||||||
pluginRequestDurationWithLabels := m.pluginRequestDuration.WithLabelValues(pluginRequestDurationLabels...)
|
pluginRequestDurationWithLabels := m.pluginRequestDuration.WithLabelValues(pluginCtx.PluginID, endpoint, target, string(statusSource))
|
||||||
pluginRequestCounterWithLabels := m.pluginRequestCounter.WithLabelValues(pluginRequestCounterLabels...)
|
pluginRequestCounterWithLabels := m.pluginRequestCounter.WithLabelValues(pluginCtx.PluginID, endpoint, status.String(), target, string(statusSource))
|
||||||
pluginRequestDurationSecondsWithLabels := m.pluginRequestDurationSeconds.WithLabelValues(pluginRequestDurationSecondsLabels...)
|
pluginRequestDurationSecondsWithLabels := m.pluginRequestDurationSeconds.WithLabelValues("grafana-backend", pluginCtx.PluginID, endpoint, status.String(), target, string(statusSource))
|
||||||
|
|
||||||
if traceID := tracing.TraceIDFromContext(ctx, true); traceID != "" {
|
if traceID := tracing.TraceIDFromContext(ctx, true); traceID != "" {
|
||||||
pluginRequestDurationWithLabels.(prometheus.ExemplarObserver).ObserveWithExemplar(
|
pluginRequestDurationWithLabels.(prometheus.ExemplarObserver).ObserveWithExemplar(
|
||||||
|
@ -90,7 +90,7 @@ func TestInstrumentationMiddleware(t *testing.T) {
|
|||||||
require.Equal(t, 1, testutil.CollectAndCount(promRegistry, metricRequestDurationMs))
|
require.Equal(t, 1, testutil.CollectAndCount(promRegistry, metricRequestDurationMs))
|
||||||
require.Equal(t, 1, testutil.CollectAndCount(promRegistry, metricRequestDurationS))
|
require.Equal(t, 1, testutil.CollectAndCount(promRegistry, metricRequestDurationS))
|
||||||
|
|
||||||
counter := mw.pluginMetrics.pluginRequestCounter.WithLabelValues(pluginID, tc.expEndpoint, requestStatusOK.String(), string(backendplugin.TargetUnknown))
|
counter := mw.pluginMetrics.pluginRequestCounter.WithLabelValues(pluginID, tc.expEndpoint, requestStatusOK.String(), string(backendplugin.TargetUnknown), string(pluginrequestmeta.DefaultStatusSource))
|
||||||
require.Equal(t, 1.0, testutil.ToFloat64(counter))
|
require.Equal(t, 1.0, testutil.ToFloat64(counter))
|
||||||
for _, m := range []string{metricRequestDurationMs, metricRequestDurationS} {
|
for _, m := range []string{metricRequestDurationMs, metricRequestDurationS} {
|
||||||
require.NoError(t, checkHistogram(promRegistry, m, map[string]string{
|
require.NoError(t, checkHistogram(promRegistry, m, map[string]string{
|
||||||
@ -115,12 +115,6 @@ func TestInstrumentationMiddleware(t *testing.T) {
|
|||||||
|
|
||||||
func TestInstrumentationMiddlewareStatusSource(t *testing.T) {
|
func TestInstrumentationMiddlewareStatusSource(t *testing.T) {
|
||||||
const labelStatusSource = "status_source"
|
const labelStatusSource = "status_source"
|
||||||
queryDataOKCounterLabels := prometheus.Labels{
|
|
||||||
"plugin_id": pluginID,
|
|
||||||
"endpoint": endpointQueryData,
|
|
||||||
"status": requestStatusOK.String(),
|
|
||||||
"target": string(backendplugin.TargetUnknown),
|
|
||||||
}
|
|
||||||
queryDataErrorCounterLabels := prometheus.Labels{
|
queryDataErrorCounterLabels := prometheus.Labels{
|
||||||
"plugin_id": pluginID,
|
"plugin_id": pluginID,
|
||||||
"endpoint": endpointQueryData,
|
"endpoint": endpointQueryData,
|
||||||
@ -159,8 +153,7 @@ func TestInstrumentationMiddlewareStatusSource(t *testing.T) {
|
|||||||
require.NoError(t, pluginsRegistry.Add(context.Background(), &plugins.Plugin{
|
require.NoError(t, pluginsRegistry.Add(context.Background(), &plugins.Plugin{
|
||||||
JSONData: plugins.JSONData{ID: pluginID, Backend: true},
|
JSONData: plugins.JSONData{ID: pluginID, Backend: true},
|
||||||
}))
|
}))
|
||||||
features := featuremgmt.WithFeatures(featuremgmt.FlagPluginsInstrumentationStatusSource)
|
metricsMw := newMetricsMiddleware(promRegistry, pluginsRegistry, featuremgmt.WithFeatures())
|
||||||
metricsMw := newMetricsMiddleware(promRegistry, pluginsRegistry, features)
|
|
||||||
cdt := clienttest.NewClientDecoratorTest(t, clienttest.WithMiddlewares(
|
cdt := clienttest.NewClientDecoratorTest(t, clienttest.WithMiddlewares(
|
||||||
NewPluginRequestMetaMiddleware(),
|
NewPluginRequestMetaMiddleware(),
|
||||||
plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
|
plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
|
||||||
@ -171,53 +164,21 @@ func TestInstrumentationMiddlewareStatusSource(t *testing.T) {
|
|||||||
))
|
))
|
||||||
|
|
||||||
t.Run("Metrics", func(t *testing.T) {
|
t.Run("Metrics", func(t *testing.T) {
|
||||||
t.Run("Should ignore ErrorSource if feature flag is disabled", func(t *testing.T) {
|
metricsMw.pluginMetrics.pluginRequestCounter.Reset()
|
||||||
// Use different middleware without feature flag
|
|
||||||
metricsMw := newMetricsMiddleware(prometheus.NewRegistry(), pluginsRegistry, featuremgmt.WithFeatures())
|
|
||||||
cdt := clienttest.NewClientDecoratorTest(t, clienttest.WithMiddlewares(
|
|
||||||
plugins.ClientMiddlewareFunc(func(next plugins.Client) plugins.Client {
|
|
||||||
metricsMw.next = next
|
|
||||||
return metricsMw
|
|
||||||
}),
|
|
||||||
))
|
|
||||||
|
|
||||||
cdt.TestClient.QueryDataFunc = func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
cdt.TestClient.QueryDataFunc = func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
||||||
return &backend.QueryDataResponse{Responses: map[string]backend.DataResponse{"A": downstreamErrorResponse}}, nil
|
return &backend.QueryDataResponse{Responses: map[string]backend.DataResponse{"A": downstreamErrorResponse}}, nil
|
||||||
}
|
}
|
||||||
_, err := cdt.Decorator.QueryData(context.Background(), &backend.QueryDataRequest{PluginContext: pCtx})
|
_, err := cdt.Decorator.QueryData(context.Background(), &backend.QueryDataRequest{PluginContext: pCtx})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
counter, err := metricsMw.pluginMetrics.pluginRequestCounter.GetMetricWith(newLabels(queryDataErrorCounterLabels, nil))
|
counter, err := metricsMw.pluginMetrics.pluginRequestCounter.GetMetricWith(newLabels(
|
||||||
require.NoError(t, err)
|
queryDataErrorCounterLabels,
|
||||||
require.Equal(t, 1.0, testutil.ToFloat64(counter))
|
prometheus.Labels{
|
||||||
|
labelStatusSource: string(backend.ErrorSourceDownstream),
|
||||||
// error_source should not be defined at all
|
}),
|
||||||
_, err = metricsMw.pluginMetrics.pluginRequestCounter.GetMetricWith(newLabels(
|
)
|
||||||
queryDataOKCounterLabels,
|
require.NoError(t, err)
|
||||||
prometheus.Labels{
|
require.Equal(t, 1.0, testutil.ToFloat64(counter))
|
||||||
labelStatusSource: string(backend.ErrorSourceDownstream),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
require.Error(t, err)
|
|
||||||
require.ErrorContains(t, err, "inconsistent label cardinality")
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("Should add error_source label if feature flag is enabled", func(t *testing.T) {
|
|
||||||
metricsMw.pluginMetrics.pluginRequestCounter.Reset()
|
|
||||||
|
|
||||||
cdt.TestClient.QueryDataFunc = func(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
|
|
||||||
return &backend.QueryDataResponse{Responses: map[string]backend.DataResponse{"A": downstreamErrorResponse}}, nil
|
|
||||||
}
|
|
||||||
_, err := cdt.Decorator.QueryData(context.Background(), &backend.QueryDataRequest{PluginContext: pCtx})
|
|
||||||
require.NoError(t, err)
|
|
||||||
counter, err := metricsMw.pluginMetrics.pluginRequestCounter.GetMetricWith(newLabels(
|
|
||||||
queryDataErrorCounterLabels,
|
|
||||||
prometheus.Labels{
|
|
||||||
labelStatusSource: string(backend.ErrorSourceDownstream),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
require.NoError(t, err)
|
|
||||||
require.Equal(t, 1.0, testutil.ToFloat64(counter))
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Priority", func(t *testing.T) {
|
t.Run("Priority", func(t *testing.T) {
|
||||||
|
@ -153,12 +153,8 @@ func NewClientDecorator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
func CreateMiddlewares(cfg *setting.Cfg, oAuthTokenService oauthtoken.OAuthTokenService, tracer tracing.Tracer, cachingService caching.CachingService, features *featuremgmt.FeatureManager, promRegisterer prometheus.Registerer, registry registry.Service) []plugins.ClientMiddleware {
|
func CreateMiddlewares(cfg *setting.Cfg, oAuthTokenService oauthtoken.OAuthTokenService, tracer tracing.Tracer, cachingService caching.CachingService, features *featuremgmt.FeatureManager, promRegisterer prometheus.Registerer, registry registry.Service) []plugins.ClientMiddleware {
|
||||||
var middlewares []plugins.ClientMiddleware
|
middlewares := []plugins.ClientMiddleware{
|
||||||
|
clientmiddleware.NewPluginRequestMetaMiddleware(),
|
||||||
if features.IsEnabledGlobally(featuremgmt.FlagPluginsInstrumentationStatusSource) {
|
|
||||||
middlewares = []plugins.ClientMiddleware{
|
|
||||||
clientmiddleware.NewPluginRequestMetaMiddleware(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
skipCookiesNames := []string{cfg.LoginCookieName}
|
skipCookiesNames := []string{cfg.LoginCookieName}
|
||||||
@ -189,11 +185,9 @@ func CreateMiddlewares(cfg *setting.Cfg, oAuthTokenService oauthtoken.OAuthToken
|
|||||||
|
|
||||||
middlewares = append(middlewares, clientmiddleware.NewHTTPClientMiddleware())
|
middlewares = append(middlewares, clientmiddleware.NewHTTPClientMiddleware())
|
||||||
|
|
||||||
if features.IsEnabledGlobally(featuremgmt.FlagPluginsInstrumentationStatusSource) {
|
// StatusSourceMiddleware should be at the very bottom, or any middlewares below it won't see the
|
||||||
// StatusSourceMiddleware should be at the very bottom, or any middlewares below it won't see the
|
// correct status source in their context.Context
|
||||||
// correct status source in their context.Context
|
middlewares = append(middlewares, clientmiddleware.NewStatusSourceMiddleware())
|
||||||
middlewares = append(middlewares, clientmiddleware.NewStatusSourceMiddleware())
|
|
||||||
}
|
|
||||||
|
|
||||||
return middlewares
|
return middlewares
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user