From a1a665e26b8200021bdfd12bd1917439cb5456bd Mon Sep 17 00:00:00 2001 From: Victor Marin Date: Wed, 17 Dec 2025 14:52:59 +0200 Subject: [PATCH] Dashboards: Add values recommendations support for AdHocFilters and GroupBy variables (#114849) * drilldown recommendations * cleanup + tests * refactor * canary scenes * update type * canary scenes * refactor types * refactor * do not pass userId * canary scenes * canary scenes * bump scenes * export recomendation type --- package.json | 4 +- packages/grafana-data/src/index.ts | 2 + packages/grafana-data/src/types/datasource.ts | 53 +++++++++++++------ .../src/types/featureToggles.gen.ts | 4 ++ pkg/services/featuremgmt/registry.go | 7 +++ pkg/services/featuremgmt/toggles_gen.csv | 1 + pkg/services/featuremgmt/toggles_gen.json | 13 +++++ .../transformSaveModelSchemaV2ToScene.ts | 2 + .../dashboard-scene/utils/variables.ts | 2 + yarn.lock | 22 ++++---- 10 files changed, 80 insertions(+), 30 deletions(-) diff --git a/package.json b/package.json index 1151e8ee235..e148217cac3 100644 --- a/package.json +++ b/package.json @@ -295,8 +295,8 @@ "@grafana/plugin-ui": "^0.11.1", "@grafana/prometheus": "workspace:*", "@grafana/runtime": "workspace:*", - "@grafana/scenes": "6.49.0", - "@grafana/scenes-react": "6.49.0", + "@grafana/scenes": "6.50.0", + "@grafana/scenes-react": "6.50.0", "@grafana/schema": "workspace:*", "@grafana/sql": "workspace:*", "@grafana/ui": "workspace:*", diff --git a/packages/grafana-data/src/index.ts b/packages/grafana-data/src/index.ts index 63c36639e25..6027b566764 100644 --- a/packages/grafana-data/src/index.ts +++ b/packages/grafana-data/src/index.ts @@ -664,6 +664,7 @@ export { type DataSourceGetTagKeysOptions, type DataSourceGetTagValuesOptions, type DataSourceGetDrilldownsApplicabilityOptions, + type DataSourceGetRecommendedDrilldownsOptions, type MetadataInspectorProps, type LegacyMetricFindQueryOptions, type QueryEditorProps, @@ -681,6 +682,7 @@ export { type QueryHint, type MetricFindValue, type DrilldownsApplicability, + type DrilldownRecommendation, type DataSourceJsonData, type DataSourceSettings, type DataSourceInstanceSettings, diff --git a/packages/grafana-data/src/types/datasource.ts b/packages/grafana-data/src/types/datasource.ts index 538e7a051e8..f50e126a5c7 100644 --- a/packages/grafana-data/src/types/datasource.ts +++ b/packages/grafana-data/src/types/datasource.ts @@ -313,6 +313,13 @@ abstract class DataSourceApi< options?: DataSourceGetDrilldownsApplicabilityOptions ): Promise; + /** + * Get recommended drilldowns for a dashboard + */ + getRecommendedDrilldowns?( + options?: DataSourceGetRecommendedDrilldownsOptions + ): Promise; + /** * Get tag keys for adhoc filters */ @@ -398,13 +405,9 @@ abstract class DataSourceApi< } /** - * Options argument to DataSourceAPI.getTagKeys + * Base options shared across datasource filtering operations. */ -export interface DataSourceGetTagKeysOptions { - /** - * The other existing filters or base filters. New in v10.3 - */ - filters: AdHocVariableFilter[]; +export interface DataSourceFilteringRequestOptions { /** * Context time range. New in v10.3 */ @@ -413,21 +416,27 @@ export interface DataSourceGetTagKeysOptions + extends DataSourceFilteringRequestOptions { + /** + * The other existing filters or base filters. New in v10.3 + */ + filters: AdHocVariableFilter[]; +} + /** * Options argument to DataSourceAPI.getTagValues */ -export interface DataSourceGetTagValuesOptions { +export interface DataSourceGetTagValuesOptions + extends DataSourceFilteringRequestOptions { key: string; /** * The other existing filters or base filters. New in v10.3 */ filters: AdHocVariableFilter[]; - /** - * Context time range. New in v10.3 - */ - timeRange?: TimeRange; - queries?: TQuery[]; - scopes?: Scope[] | undefined; } export interface MetadataInspectorProps< @@ -646,12 +655,22 @@ export interface MetricFindValue { properties?: Record; } -export interface DataSourceGetDrilldownsApplicabilityOptions { +export interface DataSourceGetDrilldownsApplicabilityOptions + extends DataSourceFilteringRequestOptions { + filters?: AdHocVariableFilter[]; + groupByKeys?: string[]; +} + +export interface DataSourceGetRecommendedDrilldownsOptions + extends DataSourceFilteringRequestOptions { + dashboardUid?: string; + filters?: AdHocVariableFilter[]; + groupByKeys?: string[]; +} + +export interface DrilldownRecommendation { filters?: AdHocVariableFilter[]; groupByKeys?: string[]; - timeRange?: TimeRange; - queries?: TQuery[]; - scopes?: Scope[] | undefined; } export interface DrilldownsApplicability { diff --git a/packages/grafana-data/src/types/featureToggles.gen.ts b/packages/grafana-data/src/types/featureToggles.gen.ts index 04e4862f2ad..51eada8c120 100644 --- a/packages/grafana-data/src/types/featureToggles.gen.ts +++ b/packages/grafana-data/src/types/featureToggles.gen.ts @@ -373,6 +373,10 @@ export interface FeatureToggles { */ unlimitedLayoutsNesting?: boolean; /** + * Enables showing recently used drilldowns or recommendations given by the datasource in the AdHocFilters and GroupBy variables + */ + drilldownRecommendations?: boolean; + /** * Enables viewing non-applicable drilldowns on a panel level */ perPanelNonApplicableDrilldowns?: boolean; diff --git a/pkg/services/featuremgmt/registry.go b/pkg/services/featuremgmt/registry.go index 2044c9c40f2..b0beaa05482 100644 --- a/pkg/services/featuremgmt/registry.go +++ b/pkg/services/featuremgmt/registry.go @@ -600,6 +600,13 @@ var ( FrontendOnly: true, Owner: grafanaDashboardsSquad, }, + { + Name: "drilldownRecommendations", + Description: "Enables showing recently used drilldowns or recommendations given by the datasource in the AdHocFilters and GroupBy variables", + Stage: FeatureStageExperimental, + FrontendOnly: true, + Owner: grafanaDashboardsSquad, + }, { Name: "perPanelNonApplicableDrilldowns", Description: "Enables viewing non-applicable drilldowns on a panel level", diff --git a/pkg/services/featuremgmt/toggles_gen.csv b/pkg/services/featuremgmt/toggles_gen.csv index 0f681344984..46581205ae4 100644 --- a/pkg/services/featuremgmt/toggles_gen.csv +++ b/pkg/services/featuremgmt/toggles_gen.csv @@ -83,6 +83,7 @@ dashboardNewLayouts,experimental,@grafana/dashboards-squad,false,false,false kubernetesDashboardsV2,experimental,@grafana/dashboards-squad,false,false,false dashboardUndoRedo,experimental,@grafana/dashboards-squad,false,false,true unlimitedLayoutsNesting,experimental,@grafana/dashboards-squad,false,false,true +drilldownRecommendations,experimental,@grafana/dashboards-squad,false,false,true perPanelNonApplicableDrilldowns,experimental,@grafana/dashboards-squad,false,false,true panelGroupBy,experimental,@grafana/dashboards-squad,false,false,true perPanelFiltering,experimental,@grafana/dashboards-squad,false,false,true diff --git a/pkg/services/featuremgmt/toggles_gen.json b/pkg/services/featuremgmt/toggles_gen.json index 31b501a8feb..4cc98de091b 100644 --- a/pkg/services/featuremgmt/toggles_gen.json +++ b/pkg/services/featuremgmt/toggles_gen.json @@ -1181,6 +1181,19 @@ "codeowner": "@grafana/grafana-datasources-core-services" } }, + { + "metadata": { + "name": "drilldownRecommendations", + "resourceVersion": "1764855550769", + "creationTimestamp": "2025-12-04T13:39:10Z" + }, + "spec": { + "description": "Enables showing recently used drilldowns or recommendations given by the datasource in the AdHocFilters and GroupBy variables", + "stage": "experimental", + "codeowner": "@grafana/dashboards-squad", + "frontend": true + } + }, { "metadata": { "name": "elasticsearchCrossClusterSearch", diff --git a/public/app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene.ts b/public/app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene.ts index 96781fe9fc2..09cae3ef7da 100644 --- a/public/app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene.ts +++ b/public/app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene.ts @@ -331,6 +331,7 @@ function createSceneVariableFromVariableModel(variable: TypedVariableModelV2): S baseFilters: variable.spec.baseFilters ?? [], defaultKeys: variable.spec.defaultKeys, useQueriesAsFilterForOptions: true, + drilldownRecommendationsEnabled: config.featureToggles.drilldownRecommendations, layout: config.featureToggles.newFiltersUI ? 'combobox' : undefined, supportsMultiValueOperators: Boolean( getDataSourceSrv().getInstanceSettings({ type: ds?.type })?.meta.multiValueFilterOperators @@ -459,6 +460,7 @@ function createSceneVariableFromVariableModel(variable: TypedVariableModelV2): S skipUrlSync: variable.spec.skipUrlSync, isMulti: variable.spec.multi, hide: transformVariableHideToEnumV1(variable.spec.hide), + drilldownRecommendationsEnabled: config.featureToggles.drilldownRecommendations, // @ts-expect-error defaultOptions: variable.options, }); diff --git a/public/app/features/dashboard-scene/utils/variables.ts b/public/app/features/dashboard-scene/utils/variables.ts index d62f9563ffc..2f262781b00 100644 --- a/public/app/features/dashboard-scene/utils/variables.ts +++ b/public/app/features/dashboard-scene/utils/variables.ts @@ -162,6 +162,7 @@ export function createSceneVariableFromVariableModel(variable: TypedVariableMode defaultKeys: variable.defaultKeys, allowCustomValue: variable.allowCustomValue, useQueriesAsFilterForOptions: true, + drilldownRecommendationsEnabled: config.featureToggles.drilldownRecommendations, layout: config.featureToggles.newFiltersUI ? 'combobox' : undefined, supportsMultiValueOperators: Boolean( getDataSourceSrv().getInstanceSettings({ type: variable.datasource?.type })?.meta.multiValueFilterOperators @@ -291,6 +292,7 @@ export function createSceneVariableFromVariableModel(variable: TypedVariableMode defaultOptions: variable.options, defaultValue: variable.defaultValue, allowCustomValue: variable.allowCustomValue, + drilldownRecommendationsEnabled: config.featureToggles.drilldownRecommendations, }); // Switch variable // In the old variable model we are storing the enabled and disabled values in the options: diff --git a/yarn.lock b/yarn.lock index eaffc580fcc..1c4d07dbb6e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3604,11 +3604,11 @@ __metadata: languageName: unknown linkType: soft -"@grafana/scenes-react@npm:6.49.0": - version: 6.49.0 - resolution: "@grafana/scenes-react@npm:6.49.0" +"@grafana/scenes-react@npm:6.50.0": + version: 6.50.0 + resolution: "@grafana/scenes-react@npm:6.50.0" dependencies: - "@grafana/scenes": "npm:6.49.0" + "@grafana/scenes": "npm:6.50.0" lru-cache: "npm:^10.2.2" react-use: "npm:^17.4.0" peerDependencies: @@ -3620,7 +3620,7 @@ __metadata: react: ^18.0.0 react-dom: ^18.0.0 react-router-dom: ^6.28.0 - checksum: 10/0f9ba2ccaf2c8a703f3c4867320852c07f640aea85491e6c1a35d7fd25b48e69740f7782b52280ab4d423a6e87659de41cf66904acc865c9ea1f934ded6c7e64 + checksum: 10/9ac9f8a32699f447c7b67dd2aef4e3ca5bc9fc98e94e0dc139e7824274ffa005b7fb3fc42ca5e55bdf89b91e3af0d3807b03e1a261db91c65717ee1763e5e807 languageName: node linkType: hard @@ -3650,9 +3650,9 @@ __metadata: languageName: node linkType: hard -"@grafana/scenes@npm:6.49.0": - version: 6.49.0 - resolution: "@grafana/scenes@npm:6.49.0" +"@grafana/scenes@npm:6.50.0": + version: 6.50.0 + resolution: "@grafana/scenes@npm:6.50.0" dependencies: "@floating-ui/react": "npm:^0.26.16" "@leeoniya/ufuzzy": "npm:^1.0.16" @@ -3672,7 +3672,7 @@ __metadata: react: ^18.0.0 react-dom: ^18.0.0 react-router-dom: ^6.28.0 - checksum: 10/0e873ceac0834879ade41df56ced5a3e8f6a10e5aba15a6f271327aa804729402bcf44845e54614dd0fb1541a28efbb9a5499acceae04cb8be3b11bcdc230347 + checksum: 10/7bc6280ff065bbba37f010e2a1f0a7dc998fe43721ddc0121e27a754c41e824b82a44222100282a69143a52061cf0dce39e6bc8b95292ca444a59c114d4b5a41 languageName: node linkType: hard @@ -19484,8 +19484,8 @@ __metadata: "@grafana/plugin-ui": "npm:^0.11.1" "@grafana/prometheus": "workspace:*" "@grafana/runtime": "workspace:*" - "@grafana/scenes": "npm:6.49.0" - "@grafana/scenes-react": "npm:6.49.0" + "@grafana/scenes": "npm:6.50.0" + "@grafana/scenes-react": "npm:6.50.0" "@grafana/schema": "workspace:*" "@grafana/sql": "workspace:*" "@grafana/test-utils": "workspace:*"