diff --git a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md index 87784df9f2b..dadf12020cc 100644 --- a/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md +++ b/docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md @@ -174,6 +174,7 @@ Experimental features might be changed or removed without prior notice. | `kubernetesAggregator` | Enable grafana aggregator | | `expressionParser` | Enable new expression parser | | `accessActionSets` | Introduces action sets for resource permissions | +| `disableNumericMetricsSortingInExpressions` | In server-side expressions, disable the sorting of numeric-kind metrics by their metric name or labels. | ## Development feature toggles diff --git a/go.mod b/go.mod index 099b49df2db..6eadc3a20a1 100644 --- a/go.mod +++ b/go.mod @@ -243,7 +243,7 @@ require ( github.com/dave/dst v0.27.2 // @grafana/grafana-as-code github.com/go-jose/go-jose/v3 v3.0.3 // @grafana/identity-access-team github.com/grafana/dataplane/examples v0.0.1 // @grafana/observability-metrics - github.com/grafana/dataplane/sdata v0.0.7 // @grafana/observability-metrics + github.com/grafana/dataplane/sdata v0.0.8 // @grafana/observability-metrics github.com/grafana/tempo v1.5.1-0.20230524121406-1dc1bfe7085b // @grafana/observability-traces-and-profiling github.com/microsoft/go-mssqldb v1.6.1-0.20240214161942-b65008136246 // @grafana/grafana-bi-squad github.com/redis/go-redis/v9 v9.1.0 // @grafana/alerting-squad-backend diff --git a/go.sum b/go.sum index 92fd1692e31..4a7064373ac 100644 --- a/go.sum +++ b/go.sum @@ -2171,8 +2171,8 @@ github.com/grafana/cuetsy v0.1.11 h1:I3IwBhF+UaQxRM79HnImtrAn8REGdb5M3+C4QrYHoWk github.com/grafana/cuetsy v0.1.11/go.mod h1:Ix97+CPD8ws9oSSxR3/Lf4ahU1I4Np83kjJmDVnLZvc= github.com/grafana/dataplane/examples v0.0.1 h1:K9M5glueWyLoL4//H+EtTQq16lXuHLmOhb6DjSCahzA= github.com/grafana/dataplane/examples v0.0.1/go.mod h1:h5YwY8s407/17XF5/dS8XrUtsTVV2RnuW8+m1Mp46mg= -github.com/grafana/dataplane/sdata v0.0.7 h1:CImITypIyS1jxijCR6xqKx71JnYAxcwpH9ChK0gH164= -github.com/grafana/dataplane/sdata v0.0.7/go.mod h1:Jvs5ddpGmn6vcxT7tCTWAZ1mgi4sbcdFt9utQx5uMAU= +github.com/grafana/dataplane/sdata v0.0.8 h1:M6PPldZKO/gbCj9Ul0dpwa/51mXNkM+9bjWJWw2XVao= +github.com/grafana/dataplane/sdata v0.0.8/go.mod h1:Jvs5ddpGmn6vcxT7tCTWAZ1mgi4sbcdFt9utQx5uMAU= github.com/grafana/dskit v0.0.0-20240104111617-ea101a3b86eb h1:AWE6+kvtE18HP+lRWNUCyvymyrFSXs6TcS2vXIXGIuw= github.com/grafana/dskit v0.0.0-20240104111617-ea101a3b86eb/go.mod h1:kkWM4WUV230bNG3urVRWPBnSJHs64y/0RmWjftnnn0c= github.com/grafana/gofpdf v0.0.0-20231002120153-857cc45be447 h1:jxJJ5z0GxqhWFbQUsys3BHG8jnmniJ2Q74tXAG1NaDo= diff --git a/go.work.sum b/go.work.sum index 70201be8575..e7909486338 100644 --- a/go.work.sum +++ b/go.work.sum @@ -406,6 +406,10 @@ github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/grafana/authlib v0.0.0-20240319083410-9d4a6e3861e5/go.mod h1:86rRD5P6u2JPWtNWTMOlqlU+YMv2fUvVz/DomA6L7w4= +github.com/grafana/dataplane/sdata v0.0.7 h1:CImITypIyS1jxijCR6xqKx71JnYAxcwpH9ChK0gH164= +github.com/grafana/dataplane/sdata v0.0.7/go.mod h1:Jvs5ddpGmn6vcxT7tCTWAZ1mgi4sbcdFt9utQx5uMAU= +github.com/grafana/dataplane/sdata v0.0.8 h1:M6PPldZKO/gbCj9Ul0dpwa/51mXNkM+9bjWJWw2XVao= +github.com/grafana/dataplane/sdata v0.0.8/go.mod h1:Jvs5ddpGmn6vcxT7tCTWAZ1mgi4sbcdFt9utQx5uMAU= github.com/grafana/e2e v0.1.1-0.20221018202458-cffd2bb71c7b h1:Ha+kSIoTutf4ytlVw/SaEclDUloYx0+FXDKJWKhNbE4= github.com/grafana/e2e v0.1.1-0.20221018202458-cffd2bb71c7b/go.mod h1:3UsooRp7yW5/NJQBlXcTsAHOoykEhNUYXkQ3r6ehEEY= github.com/grafana/gomemcache v0.0.0-20231023152154-6947259a0586 h1:/of8Z8taCPftShATouOrBVy6GaTTjgQd/VfNiZp/VXQ= @@ -414,8 +418,6 @@ github.com/grafana/grafana-plugin-sdk-go v0.212.0/go.mod h1:qsI4ktDf0lig74u8SLPJ github.com/grafana/grafana-plugin-sdk-go v0.215.0/go.mod h1:nBsh3jRItKQUXDF2BQkiQCPxqrsSQeb+7hiFyJTO1RE= github.com/grafana/grafana-plugin-sdk-go v0.216.0/go.mod h1:FdvSvOliqpVLnytM7e89zCFyYPDE6VOn9SIjVQRvVxM= github.com/grafana/grafana/pkg/promlib v0.0.3/go.mod h1:3El4NlsfALz8QQCbEGHGFvJUG+538QLMuALRhZ3pcoo= -github.com/grafana/prometheus-alertmanager v0.25.1-0.20240321101410-40158de684b2 h1:wqqaqZw+J8sLXzOjXMMde219jc6dfJPI8599UpaILZw= -github.com/grafana/prometheus-alertmanager v0.25.1-0.20240321101410-40158de684b2/go.mod h1:8Ia/R3urPmbzJ8OsdvmZvIprDwvwmYCmUbwBL+jlPOE= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1/go.mod h1:YvJ2f6MplWDhfxiUC3KpyTy76kYUZA4W3pTv/wdKQ9Y= github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 h1:MJG/KsmcqMwFAkh8mTnAwhyKoB+sTAnY4CACC110tbU= @@ -835,7 +837,6 @@ k8s.io/client-go v0.29.0/go.mod h1:yLkXH4HKMAywcrD82KMSmfYg2DlE8mepPR4JGSo5n38= k8s.io/component-base v0.29.0/go.mod h1:sADonFTQ9Zc9yFLghpDpmNXEdHyQmFIGbiuZbqAXQ1M= k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 h1:pWEwq4Asjm4vjW7vcsmijwBhOr1/shsbSYiWXmNGlks= k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/kms v0.29.0/go.mod h1:mB0f9HLxRXeXUfHfn1A7rpwOlzXI1gIWu86z6buNoYA= k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= k8s.io/kube-openapi v0.0.0-20231214164306-ab13479f8bf8/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= diff --git a/packages/grafana-data/src/types/featureToggles.gen.ts b/packages/grafana-data/src/types/featureToggles.gen.ts index a070155a704..a670448deb8 100644 --- a/packages/grafana-data/src/types/featureToggles.gen.ts +++ b/packages/grafana-data/src/types/featureToggles.gen.ts @@ -178,4 +178,5 @@ export interface FeatureToggles { newDashboardWithFiltersAndGroupBy?: boolean; cloudWatchNewLabelParsing?: boolean; accessActionSets?: boolean; + disableNumericMetricsSortingInExpressions?: boolean; } diff --git a/pkg/expr/converter.go b/pkg/expr/converter.go index 3b080f42e59..445330130ff 100644 --- a/pkg/expr/converter.go +++ b/pkg/expr/converter.go @@ -31,7 +31,7 @@ func (c *ResultConverter) Convert(ctx context.Context, dt, useDataplane, _ := shouldUseDataplane(frames, logger, c.Features.IsEnabled(ctx, featuremgmt.FlagDisableSSEDataplane)) if useDataplane { logger.Debug("Handling SSE data source query through dataplane", "datatype", dt) - result, err := handleDataplaneFrames(ctx, c.Tracer, dt, frames) + result, err := handleDataplaneFrames(ctx, c.Tracer, c.Features, dt, frames) return fmt.Sprintf("dataplane-%s", dt), result, err } diff --git a/pkg/expr/dataplane.go b/pkg/expr/dataplane.go index ae028ea5da9..3f79b11c428 100644 --- a/pkg/expr/dataplane.go +++ b/pkg/expr/dataplane.go @@ -13,6 +13,7 @@ import ( "github.com/grafana/grafana/pkg/expr/mathexp" "github.com/grafana/grafana/pkg/infra/log" "github.com/grafana/grafana/pkg/infra/tracing" + "github.com/grafana/grafana/pkg/services/featuremgmt" "go.opentelemetry.io/otel/attribute" ) @@ -58,7 +59,7 @@ func shouldUseDataplane(frames data.Frames, logger log.Logger, disable bool) (dt return dt, true, nil } -func handleDataplaneFrames(ctx context.Context, tracer tracing.Tracer, t data.FrameType, frames data.Frames) (mathexp.Results, error) { +func handleDataplaneFrames(ctx context.Context, tracer tracing.Tracer, features featuremgmt.FeatureToggles, t data.FrameType, frames data.Frames) (mathexp.Results, error) { _, span := tracer.Start(ctx, "SSE.HandleDataPlaneData") defer span.End() span.SetAttributes(attribute.String("dataplane.type", string(t))) @@ -69,7 +70,8 @@ func handleDataplaneFrames(ctx context.Context, tracer tracing.Tracer, t data.Fr case data.KindTimeSeries: return handleDataplaneTimeseries(frames) case data.KindNumeric: - return handleDataplaneNumeric(frames) + sortMetrics := !features.IsEnabled(ctx, featuremgmt.FlagDisableNumericMetricsSortingInExpressions) + return handleDataplaneNumeric(frames, sortMetrics) default: return mathexp.Results{}, fmt.Errorf("kind %s (type %s) not supported by server side expressions", t.Kind(), t) } @@ -105,7 +107,7 @@ func handleDataplaneTimeseries(frames data.Frames) (mathexp.Results, error) { return res, nil } -func handleDataplaneNumeric(frames data.Frames) (mathexp.Results, error) { +func handleDataplaneNumeric(frames data.Frames, sortMetrics bool) (mathexp.Results, error) { dn, err := numeric.CollectionReaderFromFrames(frames) if err != nil { return mathexp.Results{}, err @@ -122,6 +124,9 @@ func handleDataplaneNumeric(frames data.Frames) (mathexp.Results, error) { } return mathexp.Results{Values: mathexp.Values{noData}}, nil } + if sortMetrics { + numeric.SortNumericMetricRef(nc.Refs) + } res := mathexp.Results{} res.Values = make([]mathexp.Value, 0, len(nc.Refs)) for _, n := range nc.Refs { diff --git a/pkg/expr/dataplane_test.go b/pkg/expr/dataplane_test.go index 674d4432f0a..53094212f75 100644 --- a/pkg/expr/dataplane_test.go +++ b/pkg/expr/dataplane_test.go @@ -192,7 +192,7 @@ func TestHandleDataplaneNumeric(t *testing.T) { for _, example := range validNoDataNumericExamples.AsSlice() { t.Run(example.Info().ID, func(t *testing.T) { - res, err := handleDataplaneNumeric(example.Frames("A")) + res, err := handleDataplaneNumeric(example.Frames("A"), false) require.NoError(t, err) require.Len(t, res.Values, 1) }) @@ -213,7 +213,7 @@ func TestHandleDataplaneNumeric(t *testing.T) { for _, example := range numericExamples.AsSlice() { t.Run(example.Info().ID, func(t *testing.T) { - res, err := handleDataplaneNumeric(example.Frames("A")) + res, err := handleDataplaneNumeric(example.Frames("A"), false) require.NoError(t, err) require.Len(t, res.Values, example.Info().ItemCount) }) diff --git a/pkg/services/featuremgmt/registry.go b/pkg/services/featuremgmt/registry.go index cbbb227c811..d4834ab39ce 100644 --- a/pkg/services/featuremgmt/registry.go +++ b/pkg/services/featuremgmt/registry.go @@ -1197,6 +1197,14 @@ var ( Stage: FeatureStageExperimental, Owner: identityAccessTeam, }, + { + Name: "disableNumericMetricsSortingInExpressions", + Description: "In server-side expressions, disable the sorting of numeric-kind metrics by their metric name or labels.", + Stage: FeatureStageExperimental, + FrontendOnly: false, + Owner: grafanaObservabilityMetricsSquad, + RequiresRestart: true, + }, } ) diff --git a/pkg/services/featuremgmt/toggles_gen.csv b/pkg/services/featuremgmt/toggles_gen.csv index b9d7b81f2af..79355f63171 100644 --- a/pkg/services/featuremgmt/toggles_gen.csv +++ b/pkg/services/featuremgmt/toggles_gen.csv @@ -159,3 +159,4 @@ oauthRequireSubClaim,experimental,@grafana/identity-access-team,false,false,fals newDashboardWithFiltersAndGroupBy,experimental,@grafana/dashboards-squad,false,false,false cloudWatchNewLabelParsing,GA,@grafana/aws-datasources,false,false,false accessActionSets,experimental,@grafana/identity-access-team,false,false,false +disableNumericMetricsSortingInExpressions,experimental,@grafana/observability-metrics,false,true,false diff --git a/pkg/services/featuremgmt/toggles_gen.go b/pkg/services/featuremgmt/toggles_gen.go index 80c0dc9dc0c..389557e105a 100644 --- a/pkg/services/featuremgmt/toggles_gen.go +++ b/pkg/services/featuremgmt/toggles_gen.go @@ -646,4 +646,8 @@ const ( // FlagAccessActionSets // Introduces action sets for resource permissions FlagAccessActionSets = "accessActionSets" + + // FlagDisableNumericMetricsSortingInExpressions + // In server-side expressions, disable the sorting of numeric-kind metrics by their metric name or labels. + FlagDisableNumericMetricsSortingInExpressions = "disableNumericMetricsSortingInExpressions" ) diff --git a/pkg/services/featuremgmt/toggles_gen.json b/pkg/services/featuremgmt/toggles_gen.json index 92827f8d698..387c6e40226 100644 --- a/pkg/services/featuremgmt/toggles_gen.json +++ b/pkg/services/featuremgmt/toggles_gen.json @@ -2120,6 +2120,19 @@ "stage": "experimental", "codeowner": "@grafana/identity-access-team" } + }, + { + "metadata": { + "name": "disableNumericMetricsSortingInExpressions", + "resourceVersion": "1713208725143", + "creationTimestamp": "2024-04-15T19:18:45Z" + }, + "spec": { + "description": "In server-side expressions, disable the sorting of numeric-kind metrics by their metric name or labels.", + "stage": "experimental", + "codeowner": "@grafana/observability-metrics", + "requiresRestart": true + } } ] } \ No newline at end of file