diff --git a/docs/sources/developers/kinds/core/dashboard/schema-reference.md b/docs/sources/developers/kinds/core/dashboard/schema-reference.md
index b1e7fb7ea9d..eb287875f5c 100644
--- a/docs/sources/developers/kinds/core/dashboard/schema-reference.md
+++ b/docs/sources/developers/kinds/core/dashboard/schema-reference.md
@@ -600,24 +600,24 @@ Configured template variables
A variable is a placeholder for a value. You can use variables in metric queries and in panel titles.
-| Property | Type | Required | Default | Description |
-|---------------|-------------------------------------|----------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `name` | string | **Yes** | | Name of variable |
-| `type` | string | **Yes** | | Dashboard variable type
`query`: Query-generated list of values such as metric names, server names, sensor IDs, data centers, and so on.
`adhoc`: Key/value filters that are automatically added to all metric queries for a data source (Prometheus, Loki, InfluxDB, and Elasticsearch only).
`constant`: Define a hidden constant.
`datasource`: Quickly change the data source for an entire dashboard.
`interval`: Interval variables represent time spans.
`textbox`: Display a free text input field with an optional default value.
`custom`: Define the variable options manually using a comma-separated list.
`system`: Variables defined by Grafana. See: https://grafana.com/docs/grafana/latest/dashboards/variables/add-template-variables/#global-variables
Possible values are: `query`, `adhoc`, `constant`, `datasource`, `interval`, `textbox`, `custom`, `system`. |
-| `allValue` | string | No | | Custom all value |
-| `current` | [VariableOption](#variableoption) | No | | Option to be selected in a variable. |
-| `datasource` | [DataSourceRef](#datasourceref) | No | | Ref to a DataSource instance |
-| `description` | string | No | | Description of variable. It can be defined but `null`. |
-| `hide` | integer | No | | Determine if the variable shows on dashboard
Accepted values are 0 (show label and value), 1 (show value only), 2 (show nothing).
Possible values are: `0`, `1`, `2`. |
-| `includeAll` | boolean | No | `false` | Whether all value option is available or not |
-| `label` | string | No | | Optional display name |
-| `multi` | boolean | No | `false` | Whether multiple values can be selected or not from variable value list |
-| `options` | [VariableOption](#variableoption)[] | No | | Options that can be selected for a variable. |
-| `query` | | No | | Query used to fetch values for a variable |
-| `refresh` | integer | No | | Options to config when to refresh a variable
`0`: Never refresh the variable
`1`: Queries the data source every time the dashboard loads.
`2`: Queries the data source when the dashboard time range changes.
Possible values are: `0`, `1`, `2`. |
-| `regex` | string | No | | Optional field, if you want to extract part of a series name or metric node segment.
Named capture groups can be used to separate the display text and value. |
-| `skipUrlSync` | boolean | No | `false` | Whether the variable value should be managed by URL query params or not |
-| `sort` | integer | No | | Sort variable options
Accepted values are:
`0`: No sorting
`1`: Alphabetical ASC
`2`: Alphabetical DESC
`3`: Numerical ASC
`4`: Numerical DESC
`5`: Alphabetical Case Insensitive ASC
`6`: Alphabetical Case Insensitive DESC
`7`: Natural ASC
`8`: Natural DESC
Possible values are: `0`, `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`. |
+| Property | Type | Required | Default | Description |
+|---------------|-------------------------------------|----------|---------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `name` | string | **Yes** | | Name of variable |
+| `type` | string | **Yes** | | Dashboard variable type
`query`: Query-generated list of values such as metric names, server names, sensor IDs, data centers, and so on.
`adhoc`: Key/value filters that are automatically added to all metric queries for a data source (Prometheus, Loki, InfluxDB, and Elasticsearch only).
`constant`: Define a hidden constant.
`datasource`: Quickly change the data source for an entire dashboard.
`interval`: Interval variables represent time spans.
`textbox`: Display a free text input field with an optional default value.
`custom`: Define the variable options manually using a comma-separated list.
`system`: Variables defined by Grafana. See: https://grafana.com/docs/grafana/latest/dashboards/variables/add-template-variables/#global-variables
Possible values are: `query`, `adhoc`, `groupby`, `constant`, `datasource`, `interval`, `textbox`, `custom`, `system`. |
+| `allValue` | string | No | | Custom all value |
+| `current` | [VariableOption](#variableoption) | No | | Option to be selected in a variable. |
+| `datasource` | [DataSourceRef](#datasourceref) | No | | Ref to a DataSource instance |
+| `description` | string | No | | Description of variable. It can be defined but `null`. |
+| `hide` | integer | No | | Determine if the variable shows on dashboard
Accepted values are 0 (show label and value), 1 (show value only), 2 (show nothing).
Possible values are: `0`, `1`, `2`. |
+| `includeAll` | boolean | No | `false` | Whether all value option is available or not |
+| `label` | string | No | | Optional display name |
+| `multi` | boolean | No | `false` | Whether multiple values can be selected or not from variable value list |
+| `options` | [VariableOption](#variableoption)[] | No | | Options that can be selected for a variable. |
+| `query` | | No | | Query used to fetch values for a variable |
+| `refresh` | integer | No | | Options to config when to refresh a variable
`0`: Never refresh the variable
`1`: Queries the data source every time the dashboard loads.
`2`: Queries the data source when the dashboard time range changes.
Possible values are: `0`, `1`, `2`. |
+| `regex` | string | No | | Optional field, if you want to extract part of a series name or metric node segment.
Named capture groups can be used to separate the display text and value. |
+| `skipUrlSync` | boolean | No | `false` | Whether the variable value should be managed by URL query params or not |
+| `sort` | integer | No | | Sort variable options
Accepted values are:
`0`: No sorting
`1`: Alphabetical ASC
`2`: Alphabetical DESC
`3`: Numerical ASC
`4`: Numerical DESC
`5`: Alphabetical Case Insensitive ASC
`6`: Alphabetical Case Insensitive DESC
`7`: Natural ASC
`8`: Natural DESC
Possible values are: `0`, `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`. |
### VariableOption
diff --git a/kinds/dashboard/dashboard_kind.cue b/kinds/dashboard/dashboard_kind.cue
index ac0fddf3212..6cace8d26ff 100644
--- a/kinds/dashboard/dashboard_kind.cue
+++ b/kinds/dashboard/dashboard_kind.cue
@@ -291,7 +291,7 @@ lineage: schemas: [{
// `textbox`: Display a free text input field with an optional default value.
// `custom`: Define the variable options manually using a comma-separated list.
// `system`: Variables defined by Grafana. See: https://grafana.com/docs/grafana/latest/dashboards/variables/add-template-variables/#global-variables
- #VariableType: "query" | "adhoc" | "constant" | "datasource" | "interval" | "textbox" | "custom" | "system" @cuetsy(kind="type") @grafanamaturity(NeedsExpertReview)
+ #VariableType: "query" | "adhoc" | "groupby" | "constant" | "datasource" | "interval" | "textbox" | "custom" | "system" @cuetsy(kind="type") @grafanamaturity(NeedsExpertReview)
// Color mode for a field. You can specify a single color, or select a continuous (gradient) color schemes, based on a value.
// Continuous color interpolates a color using the percentage of a value relative to min and max.
diff --git a/package.json b/package.json
index 964c78a49db..d6fa8af44b4 100644
--- a/package.json
+++ b/package.json
@@ -246,7 +246,7 @@
"@grafana/o11y-ds-frontend": "workspace:*",
"@grafana/prometheus": "workspace:*",
"@grafana/runtime": "workspace:*",
- "@grafana/scenes": "^2.4.0",
+ "@grafana/scenes": "2.6.3",
"@grafana/schema": "workspace:*",
"@grafana/sql": "workspace:*",
"@grafana/ui": "workspace:*",
diff --git a/packages/grafana-data/src/types/datasource.ts b/packages/grafana-data/src/types/datasource.ts
index 782462d146e..82232b4991d 100644
--- a/packages/grafana-data/src/types/datasource.ts
+++ b/packages/grafana-data/src/types/datasource.ts
@@ -560,6 +560,7 @@ export interface DataQueryRequest {
/** Filters to dynamically apply to all queries */
filters?: AdHocVariableFilter[];
+ groupByKeys?: string[];
// Request Timing
startTime: number;
diff --git a/packages/grafana-data/src/types/templateVars.ts b/packages/grafana-data/src/types/templateVars.ts
index 8594bbb20e7..49dfe218bc9 100644
--- a/packages/grafana-data/src/types/templateVars.ts
+++ b/packages/grafana-data/src/types/templateVars.ts
@@ -1,4 +1,5 @@
import { LoadingState } from './data';
+import { MetricFindValue } from './datasource';
import { DataSourceRef } from './query';
export type VariableType = TypedVariableModel['type'];
@@ -13,6 +14,7 @@ export interface VariableModel {
export type TypedVariableModel =
| QueryVariableModel
| AdHocVariableModel
+ | GroupByVariableModel
| ConstantVariableModel
| DataSourceVariableModel
| IntervalVariableModel
@@ -64,6 +66,14 @@ export interface AdHocVariableModel extends BaseVariableModel {
baseFilters?: AdHocVariableFilter[];
}
+export interface GroupByVariableModel extends BaseVariableModel {
+ type: 'groupby';
+ datasource: DataSourceRef | null;
+ groupByKeys: string[];
+ defaultOptions?: MetricFindValue[];
+ multi: true;
+}
+
export interface VariableOption {
selected: boolean;
text: string | string[];
diff --git a/packages/grafana-schema/src/raw/dashboard/x/dashboard_types.gen.ts b/packages/grafana-schema/src/raw/dashboard/x/dashboard_types.gen.ts
index 6e42cab8111..c34707a521c 100644
--- a/packages/grafana-schema/src/raw/dashboard/x/dashboard_types.gen.ts
+++ b/packages/grafana-schema/src/raw/dashboard/x/dashboard_types.gen.ts
@@ -349,7 +349,7 @@ export type DashboardLinkType = ('link' | 'dashboards');
* `custom`: Define the variable options manually using a comma-separated list.
* `system`: Variables defined by Grafana. See: https://grafana.com/docs/grafana/latest/dashboards/variables/add-template-variables/#global-variables
*/
-export type VariableType = ('query' | 'adhoc' | 'constant' | 'datasource' | 'interval' | 'textbox' | 'custom' | 'system');
+export type VariableType = ('query' | 'adhoc' | 'groupby' | 'constant' | 'datasource' | 'interval' | 'textbox' | 'custom' | 'system');
/**
* Color mode for a field. You can specify a single color, or select a continuous (gradient) color schemes, based on a value.
diff --git a/pkg/kinds/dashboard/dashboard_spec_gen.go b/pkg/kinds/dashboard/dashboard_spec_gen.go
index eb45c900be2..dfd9bf19629 100644
--- a/pkg/kinds/dashboard/dashboard_spec_gen.go
+++ b/pkg/kinds/dashboard/dashboard_spec_gen.go
@@ -159,6 +159,7 @@ const (
VariableTypeConstant VariableType = "constant"
VariableTypeCustom VariableType = "custom"
VariableTypeDatasource VariableType = "datasource"
+ VariableTypeGroupby VariableType = "groupby"
VariableTypeInterval VariableType = "interval"
VariableTypeQuery VariableType = "query"
VariableTypeSystem VariableType = "system"
diff --git a/public/app/features/dashboard-scene/settings/variables/editors/GroupByVariableEditor.tsx b/public/app/features/dashboard-scene/settings/variables/editors/GroupByVariableEditor.tsx
new file mode 100644
index 00000000000..8637fb23e5c
--- /dev/null
+++ b/public/app/features/dashboard-scene/settings/variables/editors/GroupByVariableEditor.tsx
@@ -0,0 +1,12 @@
+import React from 'react';
+
+import { GroupByVariable } from '@grafana/scenes';
+
+interface GroupByVariableEditorProps {
+ variable: GroupByVariable;
+ onChange: (variable: GroupByVariable) => void;
+}
+
+export function GroupByVariableEditor(props: GroupByVariableEditorProps) {
+ return GroupByVariableEditor
;
+}
diff --git a/public/app/features/dashboard-scene/settings/variables/utils.test.ts b/public/app/features/dashboard-scene/settings/variables/utils.test.ts
index 9725ee5fe5c..f34dcdc3ec1 100644
--- a/public/app/features/dashboard-scene/settings/variables/utils.test.ts
+++ b/public/app/features/dashboard-scene/settings/variables/utils.test.ts
@@ -7,6 +7,7 @@ import {
QueryVariable,
DataSourceVariable,
AdHocFiltersVariable,
+ GroupByVariable,
TextBoxVariable,
SceneVariableSet,
} from '@grafana/scenes';
@@ -18,6 +19,7 @@ import { AdHocFiltersVariableEditor } from './editors/AdHocFiltersVariableEditor
import { ConstantVariableEditor } from './editors/ConstantVariableEditor';
import { CustomVariableEditor } from './editors/CustomVariableEditor';
import { DataSourceVariableEditor } from './editors/DataSourceVariableEditor';
+import { GroupByVariableEditor } from './editors/GroupByVariableEditor';
import { IntervalVariableEditor } from './editors/IntervalVariableEditor';
import { QueryVariableEditor } from './editors/QueryVariableEditor';
import { TextBoxVariableEditor } from './editors/TextBoxVariableEditor';
@@ -73,7 +75,16 @@ jest.mock('@grafana/runtime', () => ({
describe('isEditableVariableType', () => {
it('should return true for editable variable types', () => {
- const editableTypes: VariableType[] = ['custom', 'query', 'constant', 'interval', 'datasource', 'adhoc', 'textbox'];
+ const editableTypes: VariableType[] = [
+ 'custom',
+ 'query',
+ 'constant',
+ 'interval',
+ 'datasource',
+ 'adhoc',
+ 'groupby',
+ 'textbox',
+ ];
editableTypes.forEach((type) => {
expect(isEditableVariableType(type)).toBe(true);
});
@@ -99,7 +110,7 @@ describe('getVariableTypeSelectOptions', () => {
it('should return an array of selectable values for editable variable types', () => {
const options = getVariableTypeSelectOptions();
- expect(options).toHaveLength(7);
+ expect(options).toHaveLength(8);
options.forEach((option, index) => {
const editableType = EDITABLE_VARIABLES_SELECT_ORDER[index];
@@ -132,6 +143,7 @@ describe('getVariableEditor', () => {
['interval', IntervalVariableEditor],
['datasource', DataSourceVariableEditor],
['adhoc', AdHocFiltersVariableEditor],
+ ['groupby', GroupByVariableEditor],
['textbox', TextBoxVariableEditor],
])('should return the correct editor for variable type "%s"', (type, ExpectedVariableEditor) => {
expect(getVariableEditor(type as EditableVariableType)).toBe(ExpectedVariableEditor);
@@ -158,6 +170,7 @@ describe('getVariableScene', () => {
['interval', IntervalVariable],
['datasource', DataSourceVariable],
['adhoc', AdHocFiltersVariable],
+ ['groupby', GroupByVariable],
['textbox', TextBoxVariable],
])('should return the scene variable instance for the given editable variable type', () => {
const initialState = { name: 'MyVariable' };
diff --git a/public/app/features/dashboard-scene/settings/variables/utils.ts b/public/app/features/dashboard-scene/settings/variables/utils.ts
index 8b6480b6c9e..f1ed0380100 100644
--- a/public/app/features/dashboard-scene/settings/variables/utils.ts
+++ b/public/app/features/dashboard-scene/settings/variables/utils.ts
@@ -10,6 +10,7 @@ import {
TextBoxVariable,
QueryVariable,
AdHocFilterSet,
+ GroupByVariable,
SceneVariable,
MultiValueVariable,
SceneVariableState,
@@ -22,6 +23,7 @@ import { AdHocFiltersVariableEditor } from './editors/AdHocFiltersVariableEditor
import { ConstantVariableEditor } from './editors/ConstantVariableEditor';
import { CustomVariableEditor } from './editors/CustomVariableEditor';
import { DataSourceVariableEditor } from './editors/DataSourceVariableEditor';
+import { GroupByVariableEditor } from './editors/GroupByVariableEditor';
import { IntervalVariableEditor } from './editors/IntervalVariableEditor';
import { QueryVariableEditor } from './editors/QueryVariableEditor';
import { TextBoxVariableEditor } from './editors/TextBoxVariableEditor';
@@ -69,6 +71,11 @@ export const EDITABLE_VARIABLES: Record> {
@@ -118,6 +126,8 @@ export function getVariableScene(type: EditableVariableType, initialState: Commo
case 'adhoc':
// TODO: Initialize properly AdHocFilterSet with initialState
return new AdHocFilterSet({ name: initialState.name });
+ case 'groupby':
+ return new GroupByVariable(initialState);
case 'textbox':
return new TextBoxVariable(initialState);
}
diff --git a/public/app/features/variables/guard.test.ts b/public/app/features/variables/guard.test.ts
index 1afcf66bbef..17e22c9ccce 100644
--- a/public/app/features/variables/guard.test.ts
+++ b/public/app/features/variables/guard.test.ts
@@ -19,6 +19,7 @@ import {
createCustomVariable,
createDashboardVariable,
createDatasourceVariable,
+ createGroupByVariable,
createIntervalVariable,
createOrgVariable,
createQueryVariable,
@@ -164,6 +165,7 @@ describe('type guards', () => {
const variableFactsObj: Record = {
query: { variable: createQueryVariable(), isMulti: true, hasOptions: true, hasCurrent: true },
adhoc: { variable: createAdhocVariable(), isMulti: false, hasOptions: false, hasCurrent: false },
+ groupby: { variable: createGroupByVariable(), isMulti: true, hasOptions: false, hasCurrent: false },
constant: { variable: createConstantVariable(), isMulti: false, hasOptions: true, hasCurrent: true },
datasource: { variable: createDatasourceVariable(), isMulti: true, hasOptions: true, hasCurrent: true },
interval: { variable: createIntervalVariable(), isMulti: false, hasOptions: true, hasCurrent: true },
diff --git a/public/app/features/variables/state/__tests__/fixtures.ts b/public/app/features/variables/state/__tests__/fixtures.ts
index 8f7ae7cc9f2..6014a6a33ce 100644
--- a/public/app/features/variables/state/__tests__/fixtures.ts
+++ b/public/app/features/variables/state/__tests__/fixtures.ts
@@ -5,6 +5,7 @@ import {
CustomVariableModel,
DashboardVariableModel,
DataSourceVariableModel,
+ GroupByVariableModel,
IntervalVariableModel,
LoadingState,
OrgVariableModel,
@@ -78,6 +79,19 @@ export function createAdhocVariable(input?: Partial): AdHocV
};
}
+export function createGroupByVariable(input?: Partial): GroupByVariableModel {
+ return {
+ ...createBaseVariableModel('groupby'),
+ datasource: {
+ uid: 'abc-123',
+ type: 'prometheus',
+ },
+ groupByKeys: [],
+ multi: true,
+ ...input,
+ };
+}
+
export function createConstantVariable(input: Partial = {}): ConstantVariableModel {
return {
...createBaseVariableModel('constant'),
diff --git a/yarn.lock b/yarn.lock
index de827c749d4..14c16499f6b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3850,7 +3850,7 @@ __metadata:
languageName: unknown
linkType: soft
-"@grafana/scenes@npm:^2.4.0":
+"@grafana/scenes@npm:2.6.3":
version: 2.6.3
resolution: "@grafana/scenes@npm:2.6.3"
dependencies:
@@ -16834,12 +16834,12 @@ __metadata:
linkType: hard
"follow-redirects@npm:^1.0.0, follow-redirects@npm:^1.15.0":
- version: 1.15.5
- resolution: "follow-redirects@npm:1.15.5"
+ version: 1.15.3
+ resolution: "follow-redirects@npm:1.15.3"
peerDependenciesMeta:
debug:
optional: true
- checksum: 10/d467f13c1c6aa734599b8b369cd7a625b20081af358f6204ff515f6f4116eb440de9c4e0c49f10798eeb0df26c95dd05d5e0d9ddc5786ab1a8a8abefe92929b4
+ checksum: 10/60d98693f4976892f8c654b16ef6d1803887a951898857ab0cdc009570b1c06314ad499505b7a040ac5b98144939f8597766e5e6a6859c0945d157b473aa6f5f
languageName: node
linkType: hard
@@ -17772,7 +17772,7 @@ __metadata:
"@grafana/o11y-ds-frontend": "workspace:*"
"@grafana/prometheus": "workspace:*"
"@grafana/runtime": "workspace:*"
- "@grafana/scenes": "npm:^2.4.0"
+ "@grafana/scenes": "npm:2.6.3"
"@grafana/schema": "workspace:*"
"@grafana/sql": "workspace:*"
"@grafana/tsconfig": "npm:^1.3.0-rc1"
@@ -25579,11 +25579,11 @@ __metadata:
linkType: hard
"react-hook-form@npm:^7.49.2":
- version: 7.50.1
- resolution: "react-hook-form@npm:7.50.1"
+ version: 7.50.0
+ resolution: "react-hook-form@npm:7.50.0"
peerDependencies:
react: ^16.8.0 || ^17 || ^18
- checksum: 10/54a9daa2143c601a9867e96a2159a0bbe98707b5bbeb5953bfdf3342d2f04bfcaa6169907ed167c5c1f3a044630860d4f43685f4ac4e15b9cd892d1b00d54dde
+ checksum: 10/3b85cc179053af72a2734f2e77767de8f9b3ecbefeee282b73e81141c4b7bb97308ec00da61fdc25a28299a2defb74bff66417bb85a66357f5ceddba7b697ae7
languageName: node
linkType: hard
@@ -26243,12 +26243,12 @@ __metadata:
linkType: hard
"react-zoom-pan-pinch@npm:^3.3.0":
- version: 3.4.2
- resolution: "react-zoom-pan-pinch@npm:3.4.2"
+ version: 3.4.1
+ resolution: "react-zoom-pan-pinch@npm:3.4.1"
peerDependencies:
react: "*"
react-dom: "*"
- checksum: 10/3014c26523d69eb6a10fb1862374e4fcfb8bcf14614b0a872ca178473634427753d5c7ed6f80233f973236fcd232dd5eec70365c6eb68703e435a9a74b75bf3f
+ checksum: 10/6d46d88c869d49e511ed6899d736c8952a56ec38f7cdfa47fdd6c819c265ae4c503d4bdf6cb85557efb2e259489db6baaac9a3f3e0fa8703a534605afca6f8c2
languageName: node
linkType: hard