diff --git a/docs/sources/developers/kinds/core/dashboard/schema-reference.md b/docs/sources/developers/kinds/core/dashboard/schema-reference.md
index 561580fd2fd..0bbf32a8c27 100644
--- a/docs/sources/developers/kinds/core/dashboard/schema-reference.md
+++ b/docs/sources/developers/kinds/core/dashboard/schema-reference.md
@@ -436,6 +436,7 @@ Dashboard panels are the basic visualization building blocks.
| Property | Type | Required | Default | Description |
|--------------------|---------------------------------------------------|----------|---------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `type` | string | **Yes** | | The panel plugin type id. This is used to find the plugin to display the panel.
Constraint: `length >=1`. |
+| `cacheTimeout` | string | No | | Sets panel queries cache timeout. |
| `datasource` | [DataSourceRef](#datasourceref) | No | | Ref to a DataSource instance |
| `description` | string | No | | Panel description. |
| `fieldConfig` | [FieldConfigSource](#fieldconfigsource) | No | | The data model used in Grafana, namely the data frame, is a columnar-oriented table structure that unifies both time series and table query results.
Each column within this structure is called a field. A field can represent a single time series or table column.
Field options allow you to change how the data is displayed in your visualizations. |
@@ -449,6 +450,7 @@ Dashboard panels are the basic visualization building blocks.
| `maxPerRow` | number | No | | Option for repeated panels that controls max items per row
Only relevant for horizontally repeated panels |
| `options` | [object](#options) | No | | It depends on the panel plugin. They are specified by the Options field in panel plugin schemas. |
| `pluginVersion` | string | No | | The version of the plugin that is used for this panel. This is used to find the plugin to display the panel and to migrate old panel configs. |
+| `queryCachingTTL` | number | No | | Overrides the data source configured time-to-live for a query cache item in milliseconds |
| `repeatDirection` | string | No | `h` | Direction to repeat in if 'repeat' is set.
`h` for horizontal, `v` for vertical.
Possible values are: `h`, `v`. |
| `repeat` | string | No | | Name of template variable to repeat for. |
| `targets` | [Target](#target)[] | No | | Depends on the panel plugin. See the plugin documentation for details. |
@@ -500,6 +502,7 @@ Dashboard panels are the basic visualization building blocks.
| Property | Type | Required | Default | Description |
|--------------------|---------------------------------------------------|----------|---------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `type` | string | **Yes** | | The panel plugin type id. This is used to find the plugin to display the panel.
Constraint: `length >=1`. |
+| `cacheTimeout` | string | No | | Sets panel queries cache timeout. |
| `datasource` | [DataSourceRef](#datasourceref) | No | | Ref to a DataSource instance |
| `description` | string | No | | Panel description. |
| `fieldConfig` | [FieldConfigSource](#fieldconfigsource) | No | | The data model used in Grafana, namely the data frame, is a columnar-oriented table structure that unifies both time series and table query results.
Each column within this structure is called a field. A field can represent a single time series or table column.
Field options allow you to change how the data is displayed in your visualizations. |
@@ -513,6 +516,7 @@ Dashboard panels are the basic visualization building blocks.
| `maxPerRow` | number | No | | Option for repeated panels that controls max items per row
Only relevant for horizontally repeated panels |
| `options` | [options](#options) | No | | It depends on the panel plugin. They are specified by the Options field in panel plugin schemas. |
| `pluginVersion` | string | No | | The version of the plugin that is used for this panel. This is used to find the plugin to display the panel and to migrate old panel configs. |
+| `queryCachingTTL` | number | No | | Overrides the data source configured time-to-live for a query cache item in milliseconds |
| `repeatDirection` | string | No | `h` | Direction to repeat in if 'repeat' is set.
`h` for horizontal, `v` for vertical.
Possible values are: `h`, `v`. |
| `repeat` | string | No | | Name of template variable to repeat for. |
| `targets` | [Target](#target)[] | No | | Depends on the panel plugin. See the plugin documentation for details. |
diff --git a/kinds/dashboard/dashboard_kind.cue b/kinds/dashboard/dashboard_kind.cue
index fe963ef5bab..b366e2c96ff 100644
--- a/kinds/dashboard/dashboard_kind.cue
+++ b/kinds/dashboard/dashboard_kind.cue
@@ -591,6 +591,12 @@ lineage: schemas: [{
// Dynamically load the panel
libraryPanel?: #LibraryPanelRef
+ // Sets panel queries cache timeout.
+ cacheTimeout?: string
+
+ // Overrides the data source configured time-to-live for a query cache item in milliseconds
+ queryCachingTTL?: number
+
// It depends on the panel plugin. They are specified by the Options field in panel plugin schemas.
options?: {...} @grafanamaturity(NeedsExpertReview)
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 3e7d114de76..886dd0e3466 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
@@ -692,6 +692,10 @@ export const defaultDashboardCursorSync: DashboardCursorSync = DashboardCursorSy
* Dashboard panels are the basic visualization building blocks.
*/
export interface Panel {
+ /**
+ * Sets panel queries cache timeout.
+ */
+ cacheTimeout?: string;
/**
* The datasource used in all targets.
*/
@@ -748,6 +752,10 @@ export interface Panel {
* The version of the plugin that is used for this panel. This is used to find the plugin to display the panel and to migrate old panel configs.
*/
pluginVersion?: string;
+ /**
+ * Overrides the data source configured time-to-live for a query cache item in milliseconds
+ */
+ queryCachingTTL?: number;
/**
* Name of template variable to repeat for.
*/
diff --git a/pkg/kinds/dashboard/dashboard_spec_gen.go b/pkg/kinds/dashboard/dashboard_spec_gen.go
index 3014bba97ef..ab33a177135 100644
--- a/pkg/kinds/dashboard/dashboard_spec_gen.go
+++ b/pkg/kinds/dashboard/dashboard_spec_gen.go
@@ -505,6 +505,9 @@ type MatcherConfig struct {
// Dashboard panels are the basic visualization building blocks.
type Panel struct {
+ // Sets panel queries cache timeout.
+ CacheTimeout *string `json:"cacheTimeout,omitempty"`
+
// Ref to a DataSource instance
Datasource *DataSourceRef `json:"datasource,omitempty"`
@@ -552,6 +555,9 @@ type Panel struct {
// The version of the plugin that is used for this panel. This is used to find the plugin to display the panel and to migrate old panel configs.
PluginVersion *string `json:"pluginVersion,omitempty"`
+ // Overrides the data source configured time-to-live for a query cache item in milliseconds
+ QueryCachingTTL *float32 `json:"queryCachingTTL,omitempty"`
+
// Name of template variable to repeat for.
Repeat *string `json:"repeat,omitempty"`
diff --git a/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataQueriesTab.tsx b/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataQueriesTab.tsx
index 164237f0ae2..1f47fdabe5a 100644
--- a/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataQueriesTab.tsx
+++ b/public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataQueriesTab.tsx
@@ -72,9 +72,12 @@ export class PanelDataQueriesTab extends SceneObjectBase {
expect(dataObj.state.minInterval).toBe('1s');
});
});
+
+ describe('query caching', () => {
+ it('updates cacheTimeout and queryCachingTTL', async () => {
+ const { vizPanelManager } = setupTest('panel-1');
+ vizPanelManager.activate();
+ await Promise.resolve();
+
+ const dataObj = vizPanelManager.queryRunner;
+
+ vizPanelManager.changeQueryOptions({
+ cacheTimeout: '60',
+ queryCachingTTL: 200000,
+ dataSource: {
+ name: 'grafana-testdata',
+ type: 'grafana-testdata-datasource',
+ default: true,
+ },
+ queries: [],
+ });
+
+ expect(dataObj.state.cacheTimeout).toBe('60');
+ expect(dataObj.state.queryCachingTTL).toBe(200000);
+ });
+ });
});
describe('query inspection', () => {
diff --git a/public/app/features/dashboard-scene/panel-edit/VizPanelManager.tsx b/public/app/features/dashboard-scene/panel-edit/VizPanelManager.tsx
index 3c40e06957c..6a87c2c64c5 100644
--- a/public/app/features/dashboard-scene/panel-edit/VizPanelManager.tsx
+++ b/public/app/features/dashboard-scene/panel-edit/VizPanelManager.tsx
@@ -229,6 +229,14 @@ export class VizPanelManager extends SceneObjectBase {
panelObj.setState({ $timeRange: new PanelTimeRange(timeRangeObjStateUpdate) });
}
+ if (options.cacheTimeout !== dataObj?.state.cacheTimeout) {
+ dataObjStateUpdate.cacheTimeout = options.cacheTimeout;
+ }
+
+ if (options.queryCachingTTL !== dataObj?.state.queryCachingTTL) {
+ dataObjStateUpdate.queryCachingTTL = options.queryCachingTTL;
+ }
+
dataObj.setState(dataObjStateUpdate);
dataObj.runQueries();
}
diff --git a/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.test.ts b/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.test.ts
index 52f8757b376..490732bf0ee 100644
--- a/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.test.ts
+++ b/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.test.ts
@@ -443,6 +443,22 @@ describe('transformSaveModelToScene', () => {
expect(repeater.state.repeatDirection).toBe('v');
expect(repeater.state.maxPerRow).toBe(8);
});
+
+ it('should apply query caching options to SceneQueryRunner', () => {
+ const panel = {
+ title: '',
+ type: 'test-plugin',
+ gridPos: { x: 0, y: 0, w: 12, h: 8 },
+ transparent: true,
+ cacheTimeout: '10',
+ queryCachingTTL: 200000,
+ };
+
+ const { vizPanel } = buildGridItemForTest(panel);
+ const runner = getQueryRunnerFor(vizPanel)!;
+ expect(runner.state.cacheTimeout).toBe('10');
+ expect(runner.state.queryCachingTTL).toBe(200000);
+ });
});
describe('when creating variables objects', () => {
diff --git a/public/app/features/dashboard-scene/serialization/transformSceneToSaveModel.test.ts b/public/app/features/dashboard-scene/serialization/transformSceneToSaveModel.test.ts
index 86b675a6f81..2901b087238 100644
--- a/public/app/features/dashboard-scene/serialization/transformSceneToSaveModel.test.ts
+++ b/public/app/features/dashboard-scene/serialization/transformSceneToSaveModel.test.ts
@@ -564,6 +564,37 @@ describe('transformSceneToSaveModel', () => {
uid: SHARED_DASHBOARD_QUERY,
});
});
+
+ it('Given panel with query caching options', () => {
+ const panel = buildGridItemFromPanelSchema({
+ datasource: {
+ type: 'grafana-testdata',
+ uid: 'abc',
+ },
+ cacheTimeout: '10',
+ queryCachingTTL: 200000,
+ maxDataPoints: 100,
+ targets: [
+ {
+ refId: 'A',
+ expr: 'A',
+ datasource: {
+ type: 'grafana-testdata',
+ uid: 'abc',
+ },
+ },
+ {
+ refId: 'B',
+ expr: 'B',
+ },
+ ],
+ });
+
+ const result = gridItemToPanel(panel);
+
+ expect(result.cacheTimeout).toBe('10');
+ expect(result.queryCachingTTL).toBe(200000);
+ });
});
describe('Snapshots', () => {
diff --git a/public/app/features/dashboard-scene/serialization/transformSceneToSaveModel.ts b/public/app/features/dashboard-scene/serialization/transformSceneToSaveModel.ts
index 84442df1153..e6301ac4ef7 100644
--- a/public/app/features/dashboard-scene/serialization/transformSceneToSaveModel.ts
+++ b/public/app/features/dashboard-scene/serialization/transformSceneToSaveModel.ts
@@ -251,13 +251,24 @@ function vizPanelDataToPanel(
): Pick {
const dataProvider = vizPanel.state.$data;
- const panel: Pick = {};
+ const panel: Pick<
+ Panel,
+ 'datasource' | 'targets' | 'maxDataPoints' | 'transformations' | 'cacheTimeout' | 'queryCachingTTL'
+ > = {};
const queryRunner = getQueryRunnerFor(vizPanel);
if (queryRunner) {
panel.targets = queryRunner.state.queries;
panel.maxDataPoints = queryRunner.state.maxDataPoints;
panel.datasource = queryRunner.state.datasource;
+
+ if (queryRunner.state.cacheTimeout) {
+ panel.cacheTimeout = queryRunner.state.cacheTimeout;
+ }
+
+ if (queryRunner.state.queryCachingTTL) {
+ panel.queryCachingTTL = queryRunner.state.queryCachingTTL;
+ }
}
if (dataProvider instanceof SceneDataTransformer) {
diff --git a/public/app/features/dashboard-scene/utils/createPanelDataProvider.ts b/public/app/features/dashboard-scene/utils/createPanelDataProvider.ts
index 6e58e8fa398..774ff4c31c3 100644
--- a/public/app/features/dashboard-scene/utils/createPanelDataProvider.ts
+++ b/public/app/features/dashboard-scene/utils/createPanelDataProvider.ts
@@ -20,6 +20,8 @@ export function createPanelDataProvider(panel: PanelModel): SceneDataProvider |
queries: panel.targets,
maxDataPoints: panel.maxDataPoints ?? undefined,
maxDataPointsFromWidth: true,
+ cacheTimeout: panel.cacheTimeout,
+ queryCachingTTL: panel.queryCachingTTL,
dataLayerFilter: {
panelId: panel.id,
},