diff --git a/.betterer.eslint.config.js b/.betterer.eslint.config.js
index 1be44601a3c..349ee612837 100644
--- a/.betterer.eslint.config.js
+++ b/.betterer.eslint.config.js
@@ -113,6 +113,7 @@ module.exports = [
ignores: ['public/app/plugins/**', '**/*.story.tsx', '**/*.{test,spec}.{ts,tsx}', '**/__mocks__/', 'public/test'],
rules: {
'@grafana/no-untranslated-strings': 'error',
+ '@grafana/no-translation-top-level': 'error',
},
},
];
diff --git a/.betterer.results b/.betterer.results
index fc5e3c214fe..b03dac144aa 100644
--- a/.betterer.results
+++ b/.betterer.results
@@ -5,6 +5,12 @@
//
exports[`better eslint`] = {
value: `{
+ "apps/dashboard/tshack/v0alpha1_spec_gen.ts:5381": [
+ [0, 0, 0, "Unexpected any. Specify a different type.", "0"]
+ ],
+ "apps/dashboard/tshack/v1alpha1_spec_gen.ts:5381": [
+ [0, 0, 0, "Unexpected any. Specify a different type.", "0"]
+ ],
"e2e/old-arch/utils/support/types.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
@@ -142,6 +148,14 @@ exports[`better eslint`] = {
"packages/grafana-data/src/transformations/standardTransformersRegistry.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
+ "packages/grafana-data/src/transformations/transformDataFrame.ts:5381": [
+ [0, 0, 0, "Unexpected any. Specify a different type.", "0"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "1"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "2"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "3"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "4"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "5"]
+ ],
"packages/grafana-data/src/transformations/transformers/nulls/nullInsertThreshold.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
@@ -285,6 +299,9 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
+ "packages/grafana-data/src/types/scopes.ts:5381": [
+ [0, 0, 0, "Do not use any type assertions.", "0"]
+ ],
"packages/grafana-data/src/types/select.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
@@ -491,6 +508,9 @@ exports[`better eslint`] = {
"packages/grafana-runtime/src/services/pluginExtensions/usePluginExtensions.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
+ "packages/grafana-runtime/src/services/pluginExtensions/usePluginFunctions.ts:5381": [
+ [0, 0, 0, "Do not use any type assertions.", "0"]
+ ],
"packages/grafana-runtime/src/utils/DataSourceWithBackend.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
@@ -515,46 +535,15 @@ exports[`better eslint`] = {
"packages/grafana-sql/src/components/visual-query-builder/AwesomeQueryBuilder.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
- "packages/grafana-ui/src/components/Alert/Alert.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"]
- ],
- "packages/grafana-ui/src/components/Card/Card.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
- ],
- "packages/grafana-ui/src/components/Cascader/Cascader.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
- ],
"packages/grafana-ui/src/components/ColorPicker/ColorPicker.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
- "packages/grafana-ui/src/components/ColorPicker/NamedColorsPalette.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"]
- ],
- "packages/grafana-ui/src/components/ColorPicker/SeriesColorPickerPopover.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"]
- ],
- "packages/grafana-ui/src/components/Combobox/Combobox.tsx:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"],
- [0, 0, 0, "Do not use any type assertions.", "1"]
- ],
"packages/grafana-ui/src/components/Combobox/MultiCombobox.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
- "packages/grafana-ui/src/components/Combobox/ValuePill.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
- ],
- "packages/grafana-ui/src/components/ConfirmModal/ConfirmContent.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
- ],
- "packages/grafana-ui/src/components/DataLinks/DataLinkEditor.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "3"]
+ "packages/grafana-ui/src/components/Combobox/useOptions.ts:5381": [
+ [0, 0, 0, "Do not use any type assertions.", "0"]
],
"packages/grafana-ui/src/components/DataLinks/DataLinkInput.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
@@ -562,81 +551,19 @@ exports[`better eslint`] = {
"packages/grafana-ui/src/components/DataLinks/DataLinkSuggestions.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
],
- "packages/grafana-ui/src/components/DataLinks/DataLinksInlineEditor/DataLinksInlineEditor.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
- ],
- "packages/grafana-ui/src/components/DataLinks/DataLinksInlineEditor/DataLinksListItem.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"]
- ],
- "packages/grafana-ui/src/components/DataSourceSettings/AlertingSettings.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"]
- ],
- "packages/grafana-ui/src/components/DataSourceSettings/BasicAuthSettings.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"]
- ],
"packages/grafana-ui/src/components/DataSourceSettings/CustomHeadersSettings.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "3"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "4"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "5"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "6"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "7"]
+ [0, 0, 0, "Unexpected any. Specify a different type.", "0"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
"packages/grafana-ui/src/components/DataSourceSettings/DataSourceHttpSettings.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "3"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "4"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "5"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "6"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "7"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "8"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "9"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "10"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "11"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "12"]
- ],
- "packages/grafana-ui/src/components/DataSourceSettings/HttpProxySettings.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "3"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "4"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "5"]
- ],
- "packages/grafana-ui/src/components/DataSourceSettings/SecureSocksProxySettings.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"]
- ],
- "packages/grafana-ui/src/components/DataSourceSettings/TLSAuthSettings.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "3"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "4"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "5"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "6"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "7"]
+ [0, 0, 0, "Do not use the t() function outside of a component or function", "0"],
+ [0, 0, 0, "Do not use the t() function outside of a component or function", "1"],
+ [0, 0, 0, "Do not use the t() function outside of a component or function", "2"]
],
"packages/grafana-ui/src/components/DataSourceSettings/types.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
- "packages/grafana-ui/src/components/DateTimePickers/DateTimePicker/DateTimePicker.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"]
- ],
- "packages/grafana-ui/src/components/DateTimePickers/RelativeTimeRangePicker/RelativeTimeRangePicker.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"]
- ],
"packages/grafana-ui/src/components/FileDropzone/FileDropzone.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
],
@@ -694,16 +621,6 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"]
],
- "packages/grafana-ui/src/components/PageLayout/PageToolbar.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "3"]
- ],
- "packages/grafana-ui/src/components/Pagination/Pagination.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"]
- ],
"packages/grafana-ui/src/components/PanelChrome/PanelContext.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"]
@@ -1003,9 +920,8 @@ exports[`better eslint`] = {
"public/app/core/components/AppChrome/MegaMenu/MegaMenuItem.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
],
- "public/app/core/components/AppChrome/News/NewsContainer.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"]
+ "public/app/core/components/AppChrome/News/NewsDrawer.tsx:5381": [
+ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
],
"public/app/core/components/AppChrome/News/NewsWrapper.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
@@ -1016,10 +932,12 @@ exports[`better eslint`] = {
"public/app/core/components/AppChrome/QuickAdd/QuickAdd.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
],
+ "public/app/core/components/AppChrome/TopBar/ProfileButton.tsx:5381": [
+ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
+ ],
"public/app/core/components/AppChrome/TopBar/SingleTopBar.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"]
+ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"]
],
"public/app/core/components/AppChrome/TopBar/TopSearchBarCommandPaletteTrigger.tsx:5381": [
[0, 0, 0, "\'@grafana/ui/src/themes/mixins\' import is restricted from being used by a pattern. Import from the public export instead.", "0"]
@@ -1194,9 +1112,6 @@ exports[`better eslint`] = {
"public/app/core/components/TagFilter/TagOption.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
],
- "public/app/core/components/TimePicker/TimePickerWithHistory.tsx:5381": [
- [0, 0, 0, "\'@grafana/ui/src/utils/i18n\' import is restricted from being used by a pattern. Import from the public export instead.", "0"]
- ],
"public/app/core/components/TimeSeries/TimeSeries.tsx:5381": [
[0, 0, 0, "\'@grafana/ui/src/components/uPlot/PlotLegend\' import is restricted from being used by a pattern. Import from the public export instead.", "0"],
[0, 0, 0, "\'@grafana/ui/src/components/uPlot/config/UPlotConfigBuilder\' import is restricted from being used by a pattern. Import from the public export instead.", "1"],
@@ -1325,8 +1240,10 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"],
[0, 0, 0, "Do not use any type assertions.", "2"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "3"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "4"]
+ [0, 0, 0, "Do not use any type assertions.", "3"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "4"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "5"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "6"]
],
"public/app/core/utils/richHistory.test.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
@@ -1348,32 +1265,15 @@ exports[`better eslint`] = {
[0, 0, 0, "\'@grafana/ui/src/components/Forms/RadioButtonGroup/RadioButtonGroup\' import is restricted from being used by a pattern. Import from the public export instead.", "3"],
[0, 0, 0, "\'@grafana/ui/src/components/JSONFormatter/JSONFormatter\' import is restricted from being used by a pattern. Import from the public export instead.", "4"],
[0, 0, 0, "\'@grafana/ui/src/themes\' import is restricted from being used by a pattern. Import from the public export instead.", "5"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "6"],
+ [0, 0, 0, "\'@grafana/ui/src/utils/i18n\' import is restricted from being used by a pattern. Import from the public export instead.", "6"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "7"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "8"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "9"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "10"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "11"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "12"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "13"]
+ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "9"]
],
"public/app/features/actions/ActionEditorModalContent.tsx:5381": [
[0, 0, 0, "\'@grafana/ui/src/components/Button\' import is restricted from being used by a pattern. Import from the public export instead.", "0"],
[0, 0, 0, "\'@grafana/ui/src/components/Modal/Modal\' import is restricted from being used by a pattern. Import from the public export instead.", "1"]
],
- "public/app/features/actions/ActionsInlineEditor.tsx:5381": [
- [0, 0, 0, "\'@grafana/ui/src/components/Button\' import is restricted from being used by a pattern. Import from the public export instead.", "0"],
- [0, 0, 0, "\'@grafana/ui/src/components/Modal/Modal\' import is restricted from being used by a pattern. Import from the public export instead.", "1"],
- [0, 0, 0, "\'@grafana/ui/src/themes\' import is restricted from being used by a pattern. Import from the public export instead.", "2"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "3"]
- ],
- "public/app/features/actions/ActionsListItem.tsx:5381": [
- [0, 0, 0, "\'@grafana/ui/src/components/Icon/Icon\' import is restricted from being used by a pattern. Import from the public export instead.", "0"],
- [0, 0, 0, "\'@grafana/ui/src/components/IconButton/IconButton\' import is restricted from being used by a pattern. Import from the public export instead.", "1"],
- [0, 0, 0, "\'@grafana/ui/src/themes\' import is restricted from being used by a pattern. Import from the public export instead.", "2"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "3"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "4"]
- ],
"public/app/features/actions/ParamsEditor.tsx:5381": [
[0, 0, 0, "\'@grafana/ui/src/components/IconButton/IconButton\' import is restricted from being used by a pattern. Import from the public export instead.", "0"],
[0, 0, 0, "\'@grafana/ui/src/components/Input/Input\' import is restricted from being used by a pattern. Import from the public export instead.", "1"],
@@ -1558,23 +1458,10 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "3"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "4"]
],
- "public/app/features/alerting/unified/CloneRuleEditor.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"]
- ],
- "public/app/features/alerting/unified/ExistingRuleEditor.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "3"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "4"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "5"]
- ],
"public/app/features/alerting/unified/GrafanaRuleQueryViewer.tsx:5381": [
[0, 0, 0, "\'@grafana/data/src/datetime/rangeutil\' import is restricted from being used by a pattern. Import from the public export instead.", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "2"],
+ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "3"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "4"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "5"],
@@ -1587,7 +1474,8 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings. Wrap text with ", "12"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "13"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "14"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "15"]
+ [0, 0, 0, "No untranslated strings. Wrap text with ", "15"],
+ [0, 0, 0, "No untranslated strings. Wrap text with ", "16"]
],
"public/app/features/alerting/unified/NotificationPoliciesPage.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
@@ -1597,9 +1485,7 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "3"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "4"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "5"]
+ [0, 0, 0, "No untranslated strings. Wrap text with ", "3"]
],
"public/app/features/alerting/unified/RedirectToRuleViewer.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
@@ -1611,24 +1497,12 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings. Wrap text with ", "6"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "7"]
],
- "public/app/features/alerting/unified/RuleEditor.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "2"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "3"]
- ],
- "public/app/features/alerting/unified/RuleViewer.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
- ],
"public/app/features/alerting/unified/Settings.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "1"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "2"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "3"]
],
- "public/app/features/alerting/unified/Templates.test.tsx:5381": [
- [0, 0, 0, "\'@grafana/ui/src/components/Monaco/types\' import is restricted from being used by a pattern. Import from the public export instead.", "0"]
- ],
"public/app/features/alerting/unified/components/AlertLabel.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
],
@@ -1658,10 +1532,6 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings. Wrap text with ", "4"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "5"]
],
- "public/app/features/alerting/unified/components/InfoPausedRule.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "1"]
- ],
"public/app/features/alerting/unified/components/InvalidIntervalWarning.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "1"],
@@ -1867,9 +1737,6 @@ exports[`better eslint`] = {
"public/app/features/alerting/unified/components/extensions/AlertInstanceExtensionPoint.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
],
- "public/app/features/alerting/unified/components/extensions/AlertInstanceExtensionPointMenu.tsx:5381": [
- [0, 0, 0, "Do not re-export imported variable (\`app/features/explore/extensions/ToolbarExtensionPointMenu\`)", "0"]
- ],
"public/app/features/alerting/unified/components/mute-timings/MuteTimingActionsButtons.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"]
@@ -2040,9 +1907,6 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings. Wrap text with ", "11"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "12"]
],
- "public/app/features/alerting/unified/components/receivers/TemplateEditor.tsx:5381": [
- [0, 0, 0, "\'@grafana/ui/src/components/Monaco/types\' import is restricted from being used by a pattern. Import from the public export instead.", "0"]
- ],
"public/app/features/alerting/unified/components/receivers/TemplateForm.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
@@ -2127,10 +1991,8 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings. Wrap text with ", "6"]
],
"public/app/features/alerting/unified/components/receivers/form/fields/KeyValueMapInput.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "1"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "2"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "3"]
+ [0, 0, 0, "No untranslated strings. Wrap text with ", "0"],
+ [0, 0, 0, "No untranslated strings. Wrap text with ", "1"]
],
"public/app/features/alerting/unified/components/receivers/form/fields/OptionField.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
@@ -2161,9 +2023,6 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"]
],
- "public/app/features/alerting/unified/components/receivers/form/fields/TemplateSelector.test.tsx:5381": [
- [0, 0, 0, "\'@grafana/ui/src/components/Monaco/types\' import is restricted from being used by a pattern. Import from the public export instead.", "0"]
- ],
"public/app/features/alerting/unified/components/receivers/form/fields/TemplateSelector.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
@@ -2258,10 +2117,7 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "7"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "8"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "9"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "10"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "11"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "12"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "13"]
+ [0, 0, 0, "No untranslated strings. Wrap text with ", "10"]
],
"public/app/features/alerting/unified/components/rule-editor/GrafanaFolderAndLabelsStep.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
@@ -2383,6 +2239,9 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings. Wrap text with ", "10"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "11"]
],
+ "public/app/features/alerting/unified/components/rule-editor/dag.test.ts:5381": [
+ [0, 0, 0, "\'@grafana/runtime/src/utils/DataSourceWithBackend\' import is restricted from being used by a pattern. Import from the public export instead.", "0"]
+ ],
"public/app/features/alerting/unified/components/rule-editor/labels/LabelsButtons.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "1"]
@@ -2437,14 +2296,13 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings. Wrap text with ", "8"]
],
"public/app/features/alerting/unified/components/rule-editor/query-and-alert-condition/QueryAndExpressionsStep.tsx:5381": [
- [0, 0, 0, "\'@grafana/ui/src/components/Text/Text\' import is restricted from being used by a pattern. Import from the public export instead.", "0"],
+ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"],
+ [0, 0, 0, "No untranslated strings. Wrap text with ", "2"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "3"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "4"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "5"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "6"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "7"]
+ [0, 0, 0, "No untranslated strings. Wrap text with ", "6"]
],
"public/app/features/alerting/unified/components/rule-editor/query-and-alert-condition/SimpleCondition.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
@@ -2501,39 +2359,15 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings. Wrap text with ", "0"]
],
"public/app/features/alerting/unified/components/rule-viewer/RuleViewer.tsx:5381": [
- [0, 0, 0, "\'@grafana/ui/src/utils/i18n\' import is restricted from being used by a pattern. Import from the public export instead.", "0"],
+ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "3"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "4"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "5"]
- ],
- "public/app/features/alerting/unified/components/rule-viewer/tabs/Details.tsx:5381": [
- [0, 0, 0, "No untranslated strings. Wrap text with ", "0"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "1"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "2"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "3"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "4"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "5"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "6"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "7"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "8"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "9"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "10"]
- ],
- "public/app/features/alerting/unified/components/rule-viewer/tabs/Query.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "1"]
+ [0, 0, 0, "No untranslated strings. Wrap text with ", "4"]
],
"public/app/features/alerting/unified/components/rule-viewer/tabs/Routing.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with ", "0"]
],
- "public/app/features/alerting/unified/components/rules/ActionButton.tsx:5381": [
- [0, 0, 0, "\'@grafana/ui/src/components/Button\' import is restricted from being used by a pattern. Import from the public export instead.", "0"]
- ],
- "public/app/features/alerting/unified/components/rules/ActionIcon.tsx:5381": [
- [0, 0, 0, "\'@grafana/ui/src/components/Tooltip\' import is restricted from being used by a pattern. Import from the public export instead.", "0"]
- ],
"public/app/features/alerting/unified/components/rules/AlertInstanceDetails.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
],
@@ -2923,14 +2757,30 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "2"],
[0, 0, 0, "Do not use any type assertions.", "3"],
[0, 0, 0, "Do not use any type assertions.", "4"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "5"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "6"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "7"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "8"]
+ [0, 0, 0, "Unexpected any. Specify a different type.", "5"]
],
"public/app/features/alerting/unified/plugins/PluginOriginBadge.tsx:5381": [
[0, 0, 0, "\'@grafana/ui/src/components/Icon/utils\' import is restricted from being used by a pattern. Import from the public export instead.", "0"]
],
+ "public/app/features/alerting/unified/rule-editor/CloneRuleEditor.tsx:5381": [
+ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
+ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
+ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"]
+ ],
+ "public/app/features/alerting/unified/rule-editor/ExistingRuleEditor.tsx:5381": [
+ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
+ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
+ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"],
+ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "3"],
+ [0, 0, 0, "No untranslated strings. Wrap text with ", "4"],
+ [0, 0, 0, "No untranslated strings. Wrap text with ", "5"]
+ ],
+ "public/app/features/alerting/unified/rule-editor/RuleEditor.tsx:5381": [
+ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
+ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
+ [0, 0, 0, "No untranslated strings. Wrap text with ", "2"],
+ [0, 0, 0, "No untranslated strings. Wrap text with ", "3"]
+ ],
"public/app/features/alerting/unified/rule-list/FilterView.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
],
@@ -2955,11 +2805,8 @@ exports[`better eslint`] = {
"public/app/features/alerting/unified/rule-list/components/RuleGroup.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
],
- "public/app/features/alerting/unified/rule-list/components/RuleListIcon.tsx:5381": [
- [0, 0, 0, "\'@grafana/ui/src/components/Text/Text\' import is restricted from being used by a pattern. Import from the public export instead.", "0"]
- ],
- "public/app/features/alerting/unified/state/actions.ts:5381": [
- [0, 0, 0, "\'@grafana/runtime/src/utils/logging\' import is restricted from being used by a pattern. Import from the public export instead.", "0"]
+ "public/app/features/alerting/unified/state/AlertingQueryRunner.test.ts:5381": [
+ [0, 0, 0, "\'@grafana/runtime/src/utils/DataSourceWithBackend\' import is restricted from being used by a pattern. Import from the public export instead.", "0"]
],
"public/app/features/alerting/unified/types/receiver-form.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
@@ -3183,8 +3030,7 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "0"]
],
"public/app/features/connections/tabs/ConnectData/ConnectData.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "1"]
+ [0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/connections/tabs/ConnectData/NoAccessModal/NoAccessModal.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
@@ -3199,7 +3045,8 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "0"]
],
"public/app/features/connections/tabs/ConnectData/Search/Search.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
+ [0, 0, 0, "Do not use the t() function outside of a component or function", "0"],
+ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"]
],
"public/app/features/connections/tabs/ConnectData/Search/index.tsx:5381": [
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "0"]
@@ -3234,13 +3081,6 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings. Wrap text with ", "6"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "7"]
],
- "public/app/features/dashboard-scene/edit-pane/DashboardEditPane.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"]
- ],
- "public/app/features/dashboard-scene/embedding/EmbeddedDashboard.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
- ],
"public/app/features/dashboard-scene/embedding/EmbeddedDashboardTestPage.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with ", "0"]
],
@@ -3283,8 +3123,7 @@ exports[`better eslint`] = {
"public/app/features/dashboard-scene/pages/DashboardScenePage.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "3"]
+ [0, 0, 0, "Unexpected any. Specify a different type.", "2"]
],
"public/app/features/dashboard-scene/panel-edit/LibraryVizPanelInfo.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with ", "0"]
@@ -3301,7 +3140,7 @@ exports[`better eslint`] = {
"public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataAlertingTab.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "2"],
+ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "3"]
],
"public/app/features/dashboard-scene/panel-edit/PanelDataPane/PanelDataPane.tsx:5381": [
@@ -3415,40 +3254,6 @@ exports[`better eslint`] = {
"public/app/features/dashboard-scene/scene/DashboardLinksControls.tsx:5381": [
[0, 0, 0, "\'@grafana/data/src/text/sanitize\' import is restricted from being used by a pattern. Import from the public export instead.", "0"]
],
- "public/app/features/dashboard-scene/scene/NavToolbarActions.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "3"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "4"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "5"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "6"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "7"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "8"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "9"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "10"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "11"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "12"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "13"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "14"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "15"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "16"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "17"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "18"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "19"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "20"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "21"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "22"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "23"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "24"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "25"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "26"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "27"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "28"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "29"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "30"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "31"]
- ],
"public/app/features/dashboard-scene/scene/PanelLinks.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
],
@@ -3461,28 +3266,6 @@ exports[`better eslint`] = {
"public/app/features/dashboard-scene/scene/UnlinkModal.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
],
- "public/app/features/dashboard-scene/scene/row-actions/RowActions.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "1"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "2"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "3"]
- ],
- "public/app/features/dashboard-scene/scene/row-actions/RowOptionsButton.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
- ],
- "public/app/features/dashboard-scene/scene/row-actions/RowOptionsForm.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "2"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "3"]
- ],
- "public/app/features/dashboard-scene/scene/row-actions/RowOptionsModal.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
- ],
- "public/app/features/dashboard-scene/scene/types.ts:5381": [
- [0, 0, 0, "Unexpected any. Specify a different type.", "0"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "1"]
- ],
"public/app/features/dashboard-scene/serialization/angularMigration.test.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
@@ -3503,14 +3286,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "7"],
[0, 0, 0, "Unexpected any. Specify a different type.", "8"]
],
- "public/app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"],
- [0, 0, 0, "Do not use any type assertions.", "1"],
- [0, 0, 0, "Do not use any type assertions.", "2"],
- [0, 0, 0, "Do not use any type assertions.", "3"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "4"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "5"]
- ],
"public/app/features/dashboard-scene/serialization/transformToV1TypesUtils.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
@@ -3742,8 +3517,7 @@ exports[`better eslint`] = {
],
"public/app/features/dashboard-scene/sharing/ShareButton/share-snapshot/UpsertSnapshot.tsx:5381": [
[0, 0, 0, "\'@grafana/ui/src/components/Input/Input\' import is restricted from being used by a pattern. Import from the public export instead.", "0"],
- [0, 0, 0, "\'@grafana/ui/src/utils/i18n\' import is restricted from being used by a pattern. Import from the public export instead.", "1"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"]
+ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"]
],
"public/app/features/dashboard-scene/sharing/ShareDrawer/ShareDrawerConfirmAction.tsx:5381": [
[0, 0, 0, "\'@grafana/ui/src/components/ConfirmModal/ConfirmContent\' import is restricted from being used by a pattern. Import from the public export instead.", "0"]
@@ -3775,9 +3549,10 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "2"],
[0, 0, 0, "Do not use any type assertions.", "3"],
[0, 0, 0, "Unexpected any. Specify a different type.", "4"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "5"]
+ [0, 0, 0, "Unexpected any. Specify a different type.", "5"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "6"]
],
- "public/app/features/dashboard/api/v0.ts:5381": [
+ "public/app/features/dashboard/api/v1.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/dashboard/components/AddLibraryPanelWidget/AddLibraryPanelWidget.tsx:5381": [
@@ -4222,6 +3997,9 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings. Wrap text with ", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "1"]
],
+ "public/app/features/dashboard/containers/PublicDashboardPage.tsx:5381": [
+ [0, 0, 0, "Do not use any type assertions.", "0"]
+ ],
"public/app/features/dashboard/containers/SoloPanelPage.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "1"]
@@ -4240,9 +4018,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
[0, 0, 0, "Unexpected any. Specify a different type.", "2"]
],
- "public/app/features/dashboard/services/TimeSrv.ts:5381": [
- [0, 0, 0, "\'@grafana/ui/src/utils/i18n\' import is restricted from being used by a pattern. Import from the public export instead.", "0"]
- ],
"public/app/features/dashboard/state/DashboardMigrator.test.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
[0, 0, 0, "Unexpected any. Specify a different type.", "1"],
@@ -4660,13 +4435,9 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "8"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "9"]
],
- "public/app/features/explore/ExplorePage.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
- ],
"public/app/features/explore/ExploreRunQueryButton.tsx:5381": [
- [0, 0, 0, "\'@grafana/ui/src/utils/i18n\' import is restricted from being used by a pattern. Import from the public export instead.", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"]
+ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
+ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"]
],
"public/app/features/explore/ExploreToolbar.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
@@ -4724,10 +4495,6 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings. Wrap text with ", "3"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "4"]
],
- "public/app/features/explore/Logs/LogsNavigation.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "1"]
- ],
"public/app/features/explore/Logs/LogsSamplePanel.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "1"],
@@ -4803,30 +4570,18 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings. Wrap text with ", "2"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "3"]
],
- "public/app/features/explore/QueryLibrary/QueryLibraryExpmInfo.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "3"]
- ],
- "public/app/features/explore/QueryLibrary/QueryTemplateForm.tsx:5381": [
- [0, 0, 0, "\'@grafana/ui/src/components/Input/Input\' import is restricted from being used by a pattern. Import from the public export instead.", "0"]
- ],
- "public/app/features/explore/QueryLibrary/QueryTemplatesList.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "3"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "4"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "5"]
- ],
- "public/app/features/explore/QueryLibrary/QueryTemplatesTable/QueryDescriptionCell.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "1"]
+ "public/app/features/explore/RichHistory/RichHistorySettingsTab.tsx:5381": [
+ [0, 0, 0, "Do not use the t() function outside of a component or function", "0"],
+ [0, 0, 0, "Do not use the t() function outside of a component or function", "1"],
+ [0, 0, 0, "Do not use the t() function outside of a component or function", "2"],
+ [0, 0, 0, "Do not use the t() function outside of a component or function", "3"]
],
"public/app/features/explore/RichHistory/RichHistoryStarredTab.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with ", "0"]
],
+ "public/app/features/explore/ShortLinkButtonMenu.tsx:5381": [
+ [0, 0, 0, "Do not use the t() function outside of a component or function", "0"]
+ ],
"public/app/features/explore/SupplementaryResultError.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with ", "0"]
],
@@ -5042,9 +4797,7 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use any type assertions.", "1"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "3"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "4"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "5"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "6"]
+ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "4"]
],
"public/app/features/explore/extensions/ConfirmNavigationModal.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with ", "0"],
@@ -5073,9 +4826,6 @@ exports[`better eslint`] = {
"public/app/features/explore/state/time.test.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
- "public/app/features/explore/state/time.ts:5381": [
- [0, 0, 0, "\'@grafana/ui/src/utils/i18n\' import is restricted from being used by a pattern. Import from the public export instead.", "0"]
- ],
"public/app/features/explore/state/utils.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"],
@@ -5136,12 +4886,7 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "4"]
],
"public/app/features/expressions/components/Threshold.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "3"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "4"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "5"]
+ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
],
"public/app/features/expressions/guards.ts:5381": [
[0, 0, 0, "\'@grafana/runtime/src/utils/DataSourceWithBackend\' import is restricted from being used by a pattern. Import from the public export instead.", "0"],
@@ -5195,8 +4940,14 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings. Wrap text with ", "4"]
],
"public/app/features/inspector/InspectJSONTab.tsx:5381": [
- [0, 0, 0, "No untranslated strings. Wrap text with ", "0"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "1"]
+ [0, 0, 0, "Do not use the t() function outside of a component or function", "0"],
+ [0, 0, 0, "Do not use the t() function outside of a component or function", "1"],
+ [0, 0, 0, "Do not use the t() function outside of a component or function", "2"],
+ [0, 0, 0, "Do not use the t() function outside of a component or function", "3"],
+ [0, 0, 0, "Do not use the t() function outside of a component or function", "4"],
+ [0, 0, 0, "Do not use the t() function outside of a component or function", "5"],
+ [0, 0, 0, "No untranslated strings. Wrap text with ", "6"],
+ [0, 0, 0, "No untranslated strings. Wrap text with ", "7"]
],
"public/app/features/inspector/InspectStatsTab.tsx:5381": [
[0, 0, 0, "Use data-testid for E2E selectors instead of aria-label", "0"]
@@ -5387,9 +5138,6 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings. Wrap text with ", "2"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "3"]
],
- "public/app/features/manage-dashboards/components/PublicDashboardListTable/PublicDashboardListTable.tsx:5381": [
- [0, 0, 0, "\'HorizontalGroup\' import from \'@grafana/ui\' is restricted from being used by a pattern. Use Stack component instead.", "0"]
- ],
"public/app/features/manage-dashboards/components/SnapshotListTable.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
],
@@ -5581,12 +5329,6 @@ exports[`better eslint`] = {
"public/app/features/plugins/admin/components/GetStartedWithPlugin/index.ts:5381": [
[0, 0, 0, "Do not re-export imported variable (\`./GetStartedWithPlugin\`)", "0"]
],
- "public/app/features/plugins/admin/components/InstallControls/ExternallyManagedButton.tsx:5381": [
- [0, 0, 0, "No untranslated strings. Wrap text with ", "0"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "1"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "2"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "3"]
- ],
"public/app/features/plugins/admin/components/InstallControls/InstallControlsButton.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
],
@@ -5650,7 +5392,8 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings. Wrap text with ", "5"]
],
"public/app/features/plugins/admin/components/PluginDetailsPanel.tsx:5381": [
- [0, 0, 0, "\'@grafana/runtime/src/components/PluginPage\' import is restricted from being used by a pattern. Import from the public export instead.", "0"]
+ [0, 0, 0, "\'@grafana/runtime/src/components/PluginPage\' import is restricted from being used by a pattern. Import from the public export instead.", "0"],
+ [0, 0, 0, "No untranslated strings. Wrap text with ", "1"]
],
"public/app/features/plugins/admin/components/PluginDetailsSignature.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
@@ -5751,11 +5494,10 @@ exports[`better eslint`] = {
[0, 0, 0, "\'@grafana/data/src/types/pluginExtensions\' import is restricted from being used by a pattern. Import from the public export instead.", "0"]
],
"public/app/features/plugins/extensions/usePluginComponents.tsx:5381": [
- [0, 0, 0, "\'@grafana/runtime/src/services/pluginExtensions/getPluginExtensions\' import is restricted from being used by a pattern. Import from the public export instead.", "0"],
- [0, 0, 0, "Do not use any type assertions.", "1"]
+ [0, 0, 0, "Do not use any type assertions.", "0"]
],
- "public/app/features/plugins/extensions/usePluginLinks.tsx:5381": [
- [0, 0, 0, "\'@grafana/runtime/src/services/pluginExtensions/getPluginExtensions\' import is restricted from being used by a pattern. Import from the public export instead.", "0"]
+ "public/app/features/plugins/extensions/usePluginFunctions.tsx:5381": [
+ [0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/features/plugins/extensions/validators.ts:5381": [
[0, 0, 0, "\'@grafana/data/src/types/pluginExtensions\' import is restricted from being used by a pattern. Import from the public export instead.", "0"]
@@ -5806,9 +5548,6 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings. Wrap text with ", "4"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "5"]
],
- "public/app/features/query-library/api/query.ts:5381": [
- [0, 0, 0, "\'@grafana/runtime/src/services/backendSrv\' import is restricted from being used by a pattern. Import from the public export instead.", "0"]
- ],
"public/app/features/query/components/QueryEditorRow.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"],
[0, 0, 0, "Do not use any type assertions.", "1"],
@@ -5943,10 +5682,6 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings. Wrap text with ", "2"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "3"]
],
- "public/app/features/scopes/index.ts:5381": [
- [0, 0, 0, "Do not re-export imported variable (\`./ScopesDashboards\`)", "0"],
- [0, 0, 0, "Do not re-export imported variable (\`./instance\`)", "1"]
- ],
"public/app/features/search/page/components/ActionRow.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with ", "0"]
],
@@ -5983,9 +5718,6 @@ exports[`better eslint`] = {
"public/app/features/search/utils.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"]
],
- "public/app/features/serviceaccounts/ServiceAccountCreatePage.tsx:5381": [
- [0, 0, 0, "\'@grafana/ui/src/utils/i18n\' import is restricted from being used by a pattern. Import from the public export instead.", "0"]
- ],
"public/app/features/serviceaccounts/ServiceAccountPage.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
@@ -6186,8 +5918,7 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings. Wrap text with ", "1"]
],
"public/app/features/trails/DataTrailSettings.tsx:5381": [
- [0, 0, 0, "\'@grafana/ui/src/utils/i18n\' import is restricted from being used by a pattern. Import from the public export instead.", "0"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "1"]
+ [0, 0, 0, "No untranslated strings. Wrap text with ", "0"]
],
"public/app/features/trails/DataTrailsHistory.tsx:5381": [
[0, 0, 0, "\'@grafana/data/src/datetime/rangeutil\' import is restricted from being used by a pattern. Import from the public export instead.", "0"],
@@ -6214,9 +5945,6 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings. Wrap text with ", "7"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "8"]
],
- "public/app/features/trails/MetricSelect/NativeHistogramBadge.tsx:5381": [
- [0, 0, 0, "\'@grafana/ui/src/utils/i18n\' import is restricted from being used by a pattern. Import from the public export instead.", "0"]
- ],
"public/app/features/trails/MetricsHeader.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with ", "0"],
[0, 0, 0, "No untranslated strings. Wrap text with ", "1"]
@@ -6230,8 +5958,7 @@ exports[`better eslint`] = {
[0, 0, 0, "No untranslated strings. Wrap text with ", "2"]
],
"public/app/features/trails/banners/NativeHistogramBanner.tsx:5381": [
- [0, 0, 0, "\'@grafana/ui/src/utils/i18n\' import is restricted from being used by a pattern. Import from the public export instead.", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"]
+ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
],
"public/app/features/transformers/FilterByValueTransformer/FilterByValueFilterEditor.tsx:5381": [
[0, 0, 0, "\'@grafana/data/src/transformations/transformers/filterByValue\' import is restricted from being used by a pattern. Import from the public export instead.", "0"],
@@ -6252,8 +5979,7 @@ exports[`better eslint`] = {
],
"public/app/features/transformers/FilterByValueTransformer/ValueMatchers/BasicMatcherEditor.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "2"]
+ [0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
"public/app/features/transformers/FilterByValueTransformer/ValueMatchers/NoopMatcherEditor.tsx:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
@@ -6261,15 +5987,11 @@ exports[`better eslint`] = {
"public/app/features/transformers/FilterByValueTransformer/ValueMatchers/RangeMatcherEditor.tsx:5381": [
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "3"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "4"],
- [0, 0, 0, "No untranslated strings. Wrap text with ", "5"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "6"]
+ [0, 0, 0, "No untranslated strings. Wrap text with ", "2"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "3"]
],
"public/app/features/transformers/FilterByValueTransformer/ValueMatchers/RegexMatcherEditor.tsx:5381": [
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"]
+ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "0"]
],
"public/app/features/transformers/FilterByValueTransformer/ValueMatchers/types.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"],
@@ -6452,10 +6174,7 @@ exports[`better eslint`] = {
[0, 0, 0, "\'@grafana/data/src/transformations/transformers/histogram\' import is restricted from being used by a pattern. Import from the public export instead.", "0"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
[0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "3"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "4"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "5"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "6"]
+ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "3"]
],
"public/app/features/transformers/editors/JoinByFieldTransformerEditor.tsx:5381": [
[0, 0, 0, "\'@grafana/data/src/transformations/transformers/joinByField\' import is restricted from being used by a pattern. Import from the public export instead.", "0"],
@@ -6474,9 +6193,7 @@ exports[`better eslint`] = {
],
"public/app/features/transformers/editors/LimitTransformerEditor.tsx:5381": [
[0, 0, 0, "\'@grafana/data/src/transformations/transformers/limit\' import is restricted from being used by a pattern. Import from the public export instead.", "0"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "2"],
- [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "3"]
+ [0, 0, 0, "No untranslated strings in text props. Wrap text with or use t()", "1"]
],
"public/app/features/transformers/editors/MergeTransformerEditor.tsx:5381": [
[0, 0, 0, "\'@grafana/data/src/transformations/transformers/merge\' import is restricted from being used by a pattern. Import from the public export instead.", "0"],
@@ -6968,9 +6685,6 @@ exports[`better eslint`] = {
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "0"],
[0, 0, 0, "Do not use export all (\`export * from ...\`)", "1"]
],
- "public/app/plugins/datasource/azuremonitor/azure_monitor/azure_monitor_datasource.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"]
- ],
"public/app/plugins/datasource/azuremonitor/components/ArgQueryEditor/index.tsx:5381": [
[0, 0, 0, "Do not re-export imported variable (\`./ArgQueryEditor\`)", "0"]
],
@@ -7020,6 +6734,9 @@ exports[`better eslint`] = {
"public/app/plugins/datasource/azuremonitor/types/templateVariables.ts:5381": [
[0, 0, 0, "Do not re-export imported variable (\`../dataquery.gen\`)", "0"]
],
+ "public/app/plugins/datasource/azuremonitor/utils/common.ts:5381": [
+ [0, 0, 0, "Do not use any type assertions.", "0"]
+ ],
"public/app/plugins/datasource/azuremonitor/utils/messageFromError.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
@@ -7582,8 +7299,7 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "2"]
],
"public/app/plugins/datasource/zipkin/datasource.ts:5381": [
- [0, 0, 0, "Do not use any type assertions.", "0"],
- [0, 0, 0, "Unexpected any. Specify a different type.", "1"]
+ [0, 0, 0, "Do not use any type assertions.", "0"]
],
"public/app/plugins/datasource/zipkin/utils/transforms.ts:5381": [
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
diff --git a/.bingo/Variables.mk b/.bingo/Variables.mk
index 56a916a0d25..80b5946b497 100644
--- a/.bingo/Variables.mk
+++ b/.bingo/Variables.mk
@@ -5,6 +5,10 @@ GOPATH ?= $(shell go env GOPATH)
GOBIN ?= $(firstword $(subst :, ,${GOPATH}))/bin
GO ?= $(shell which go)
+# Add this near the top of the file, after the initial variable definitions
+ifndef VARIABLES_MK
+VARIABLES_MK := 1
+
# Below generated variables ensure that every time a tool under each variable is invoked, the correct version
# will be used; reinstalling only if needed.
# For example for bra variable:
@@ -65,3 +69,4 @@ $(SWAGGER): $(BINGO_DIR)/swagger.mod
@echo "(re)installing $(GOBIN)/swagger-v0.30.6-0.20240310114303-db51e79a0e37"
@cd $(BINGO_DIR) && GOWORK=off $(GO) build -mod=mod -modfile=swagger.mod -o=$(GOBIN)/swagger-v0.30.6-0.20240310114303-db51e79a0e37 "github.com/go-swagger/go-swagger/cmd/swagger"
+endif
diff --git a/.drone.yml b/.drone.yml
index f81d8bbbc69..dbcc1662f84 100644
--- a/.drone.yml
+++ b/.drone.yml
@@ -18,14 +18,14 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
- image: alpine:3.20.3
+ image: alpine:3.21.3
name: identify-runner
- commands:
- go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd
depends_on: []
environment:
CGO_ENABLED: 0
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: compile-build-cmd
- commands:
- ./bin/build verify-drone
@@ -69,13 +69,13 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
- image: alpine:3.20.3
+ image: alpine:3.21.3
name: identify-runner
- commands:
- go install github.com/bazelbuild/buildtools/buildifier@latest
- buildifier --lint=warn -mode=check -r .
depends_on: []
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: lint-starlark
trigger:
event:
@@ -112,7 +112,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
- image: alpine:3.20.3
+ image: alpine:3.21.3
name: identify-runner
- commands:
- yarn install --immutable || yarn install --immutable
@@ -170,7 +170,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
- image: alpine:3.20.3
+ image: alpine:3.21.3
name: identify-runner
- commands:
- yarn install --immutable || yarn install --immutable
@@ -179,7 +179,7 @@ steps:
name: yarn-install
- commands:
- apk add --update git bash
- - yarn betterer ci
+ - yarn betterer:ci
depends_on:
- yarn-install
image: node:22.11.0-alpine
@@ -309,7 +309,7 @@ steps:
path: /github-app
- commands:
- echo $DRONE_RUNNER_NAME
- image: alpine:3.20.3
+ image: alpine:3.21.3
name: identify-runner
- commands:
- yarn install --immutable || yarn install --immutable
@@ -339,6 +339,16 @@ steps:
- yarn-install
image: node:22-bookworm
name: verify-i18n
+- commands:
+ - yarn generate-apis
+ - "\n file_diff=$(git diff ':!conf')\n if [ -n \"$file_diff\"
+ ]; then\n echo $file_diff\n echo \"\nAPI client
+ generation has not been committed. Please run 'yarn generate-apis', commit the
+ changes and push again.\"\n exit 1\n fi\n "
+ depends_on:
+ - yarn-install
+ image: node:22-bookworm
+ name: verify-api-clients
trigger:
event:
- pull_request
@@ -417,7 +427,7 @@ steps:
path: /github-app
- commands:
- echo $DRONE_RUNNER_NAME
- image: alpine:3.20.3
+ image: alpine:3.21.3
name: identify-runner
- commands:
- '# It is required that code generated from Thema/CUE be committed and in sync
@@ -427,7 +437,7 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-cue
depends_on: []
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: verify-gen-cue
- commands:
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
@@ -436,21 +446,21 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-jsonnet
depends_on: []
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: verify-gen-jsonnet
- commands:
- apk add --update make
- make gen-go
depends_on:
- verify-gen-cue
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: wire-install
- commands:
- apk add --update build-base shared-mime-info shared-mime-info-lang
- go list -f '{{.Dir}}/...' -m | xargs go test -short -covermode=atomic -timeout=5m
depends_on:
- wire-install
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: test-backend
- commands:
- apk add --update build-base
@@ -459,7 +469,7 @@ steps:
| grep -o '\(.*\)/' | sort -u)
depends_on:
- wire-install
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: test-backend-integration
trigger:
event:
@@ -479,6 +489,7 @@ trigger:
- public/app/plugins/**/plugin.json
- docs/sources/setup-grafana/configure-grafana/feature-toggles/**
- devenv/**
+ - apps/**
type: docker
volumes:
- host:
@@ -506,14 +517,14 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
- image: alpine:3.20.3
+ image: alpine:3.21.3
name: identify-runner
- commands:
- go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd
depends_on: []
environment:
CGO_ENABLED: 0
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: compile-build-cmd
- commands:
- echo $(/usr/bin/github-app-external-token) > /github-app/token
@@ -558,16 +569,16 @@ steps:
- apk add --update make
- make gen-go
depends_on: []
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: wire-install
- commands:
- go run scripts/modowners/modowners.go check go.mod
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: validate-modfile
- commands:
- apk add --update make
- make swagger-validate
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: validate-openapi-spec
trigger:
event:
@@ -588,6 +599,7 @@ trigger:
- public/app/plugins/**/plugin.json
- devenv/**
- .bingo/**
+ - apps/**
type: docker
volumes:
- host:
@@ -630,11 +642,11 @@ steps:
path: /github-app
- commands:
- echo $DRONE_RUNNER_NAME
- image: alpine:3.20.3
+ image: alpine:3.21.3
name: identify-runner
- commands:
- mkdir -p bin
- - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.1/grabpl
+ - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.2/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -643,7 +655,7 @@ steps:
depends_on: []
environment:
CGO_ENABLED: 0
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: compile-build-cmd
- commands:
- '# It is required that code generated from Thema/CUE be committed and in sync
@@ -653,7 +665,7 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-cue
depends_on: []
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: verify-gen-cue
- commands:
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
@@ -662,7 +674,7 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-jsonnet
depends_on: []
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: verify-gen-jsonnet
- commands:
- yarn install --immutable || yarn install --immutable
@@ -694,12 +706,14 @@ steps:
token:
from_secret: drone_token
- commands:
- - docker run --privileged --rm tonistiigi/binfmt --install all
+ - docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --version
+ - docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*'
+ - docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all
- /src/grafana-build artifacts -a targz:grafana:linux/amd64 -a targz:grafana:linux/arm64
-a targz:grafana:linux/arm/v7 -a docker:grafana:linux/amd64 -a docker:grafana:linux/amd64:ubuntu
-a docker:grafana:linux/arm64 -a docker:grafana:linux/arm64:ubuntu -a docker:grafana:linux/arm/v7
- -a docker:grafana:linux/arm/v7:ubuntu --go-version=1.23.5 --yarn-cache=$$YARN_CACHE_FOLDER
- --build-id=$$DRONE_BUILD_NUMBER --ubuntu-base=ubuntu:22.04 --alpine-base=alpine:3.20.3
+ -a docker:grafana:linux/arm/v7:ubuntu --go-version=1.23.7 --yarn-cache=$$YARN_CACHE_FOLDER
+ --build-id=$$DRONE_BUILD_NUMBER --ubuntu-base=ubuntu:22.04 --alpine-base=alpine:3.21.3
--tag-format='{{ .version_base }}-{{ .buildID }}-{{ .arch }}' --ubuntu-tag-format='{{
.version_base }}-{{ .buildID }}-ubuntu-{{ .arch }}' --verify='false' --grafana-dir=$$PWD
> packages.txt
@@ -756,7 +770,7 @@ steps:
GF_APP_MODE: development
GF_SERVER_HTTP_PORT: "3001"
GF_SERVER_ROUTER_LOGGING: "1"
- image: alpine:3.20.3
+ image: alpine:3.21.3
name: grafana-server
- commands:
- ./bin/build e2e-tests --port 3001 --suite dashboards-suite
@@ -1087,7 +1101,7 @@ steps:
path: /github-app
- commands:
- mkdir -p bin
- - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.1/grabpl
+ - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.2/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -1096,11 +1110,11 @@ steps:
depends_on: []
environment:
CGO_ENABLED: 0
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: compile-build-cmd
- commands:
- echo $DRONE_RUNNER_NAME
- image: alpine:3.20.3
+ image: alpine:3.21.3
name: identify-runner
- commands:
- '# It is required that code generated from Thema/CUE be committed and in sync
@@ -1110,7 +1124,7 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-cue
depends_on: []
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: verify-gen-cue
- commands:
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
@@ -1119,14 +1133,14 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-jsonnet
depends_on: []
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: verify-gen-jsonnet
- commands:
- apk add --update make
- make gen-go
depends_on:
- verify-gen-cue
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: wire-install
- commands:
- dockerize -wait tcp://postgres:5432 -timeout 120s
@@ -1147,7 +1161,7 @@ steps:
GRAFANA_TEST_DB: postgres
PGPASSWORD: grafanatest
POSTGRES_HOST: postgres
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: postgres-integration-tests
- commands:
- dockerize -wait tcp://mysql80:3306 -timeout 120s
@@ -1168,7 +1182,7 @@ steps:
environment:
GRAFANA_TEST_DB: mysql
MYSQL_HOST: mysql80
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: mysql-8.0-integration-tests
- commands:
- dockerize -wait tcp://redis:6379 -timeout 120s
@@ -1184,7 +1198,7 @@ steps:
- wait-for-redis
environment:
REDIS_URL: redis://redis:6379/0
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: redis-integration-tests
- commands:
- dockerize -wait tcp://memcached:11211 -timeout 120s
@@ -1200,7 +1214,7 @@ steps:
- wait-for-memcached
environment:
MEMCACHED_HOSTS: memcached:11211
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: memcached-integration-tests
- commands:
- dockerize -wait tcp://mimir_backend:8080 -timeout 120s
@@ -1216,7 +1230,7 @@ steps:
environment:
AM_TENANT_ID: test
AM_URL: http://mimir_backend:8080
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: remote-alertmanager-integration-tests
trigger:
event:
@@ -1266,7 +1280,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
- image: alpine:3.20.3
+ image: alpine:3.21.3
name: identify-runner
- commands:
- yarn install --immutable || yarn install --immutable
@@ -1298,7 +1312,7 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-cue
depends_on: []
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: verify-gen-cue
trigger:
event:
@@ -1419,7 +1433,7 @@ steps:
&& return 1; fi
depends_on:
- clone-enterprise
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: swagger-gen
trigger:
event:
@@ -1524,7 +1538,7 @@ steps:
depends_on: []
environment:
CGO_ENABLED: 0
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: compile-build-cmd
- commands:
- '# It is required that code generated from Thema/CUE be committed and in sync
@@ -1535,7 +1549,7 @@ steps:
- CODEGEN_VERIFY=1 make gen-cue
depends_on:
- clone-enterprise
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: verify-gen-cue
- commands:
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
@@ -1545,14 +1559,14 @@ steps:
- CODEGEN_VERIFY=1 make gen-jsonnet
depends_on:
- clone-enterprise
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: verify-gen-jsonnet
- commands:
- apk add --update make
- make gen-go
depends_on:
- verify-gen-cue
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: wire-install
- commands:
- apk add --update build-base
@@ -1560,7 +1574,7 @@ steps:
- go test -v -run=^$ -benchmem -timeout=1h -count=8 -bench=. ${GO_PACKAGES}
depends_on:
- wire-install
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: sqlite-benchmark-integration-tests
- commands:
- apk add --update build-base
@@ -1572,7 +1586,7 @@ steps:
GRAFANA_TEST_DB: postgres
PGPASSWORD: grafanatest
POSTGRES_HOST: postgres
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: postgres-benchmark-integration-tests
- commands:
- apk add --update build-base
@@ -1583,7 +1597,7 @@ steps:
environment:
GRAFANA_TEST_DB: mysql
MYSQL_HOST: mysql80
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: mysql-8.0-benchmark-integration-tests
trigger:
event:
@@ -1623,7 +1637,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
- image: alpine:3.20.3
+ image: alpine:3.21.3
name: identify-runner
- commands:
- yarn install --immutable || yarn install --immutable
@@ -1655,7 +1669,7 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-cue
depends_on: []
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: verify-gen-cue
trigger:
branch: main
@@ -1694,7 +1708,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
- image: alpine:3.20.3
+ image: alpine:3.21.3
name: identify-runner
- commands:
- yarn install --immutable || yarn install --immutable
@@ -1703,7 +1717,7 @@ steps:
name: yarn-install
- commands:
- apk add --update git bash
- - yarn betterer ci
+ - yarn betterer:ci
depends_on:
- yarn-install
image: node:22.11.0-alpine
@@ -1752,7 +1766,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
- image: alpine:3.20.3
+ image: alpine:3.21.3
name: identify-runner
- commands:
- yarn install --immutable || yarn install --immutable
@@ -1782,6 +1796,16 @@ steps:
- yarn-install
image: node:22-bookworm
name: verify-i18n
+- commands:
+ - yarn generate-apis
+ - "\n file_diff=$(git diff ':!conf')\n if [ -n \"$file_diff\"
+ ]; then\n echo $file_diff\n echo \"\nAPI client
+ generation has not been committed. Please run 'yarn generate-apis', commit the
+ changes and push again.\"\n exit 1\n fi\n "
+ depends_on:
+ - yarn-install
+ image: node:22-bookworm
+ name: verify-api-clients
trigger:
branch: main
event:
@@ -1818,7 +1842,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
- image: alpine:3.20.3
+ image: alpine:3.21.3
name: identify-runner
- commands:
- '# It is required that code generated from Thema/CUE be committed and in sync
@@ -1828,7 +1852,7 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-cue
depends_on: []
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: verify-gen-cue
- commands:
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
@@ -1837,21 +1861,21 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-jsonnet
depends_on: []
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: verify-gen-jsonnet
- commands:
- apk add --update make
- make gen-go
depends_on:
- verify-gen-cue
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: wire-install
- commands:
- apk add --update build-base shared-mime-info shared-mime-info-lang
- go list -f '{{.Dir}}/...' -m | xargs go test -short -covermode=atomic -timeout=5m
depends_on:
- wire-install
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: test-backend
- commands:
- apk add --update build-base
@@ -1860,7 +1884,7 @@ steps:
| grep -o '\(.*\)/' | sort -u)
depends_on:
- wire-install
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: test-backend-integration
trigger:
branch: main
@@ -1898,29 +1922,29 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
- image: alpine:3.20.3
+ image: alpine:3.21.3
name: identify-runner
- commands:
- go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd
depends_on: []
environment:
CGO_ENABLED: 0
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: compile-build-cmd
- commands:
- apk add --update make
- make gen-go
depends_on: []
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: wire-install
- commands:
- go run scripts/modowners/modowners.go check go.mod
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: validate-modfile
- commands:
- apk add --update make
- make swagger-validate
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: validate-openapi-spec
- commands:
- ./bin/build verify-drone
@@ -1964,7 +1988,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
- image: alpine:3.20.3
+ image: alpine:3.21.3
name: identify-runner
- commands:
- yarn install --immutable || yarn install --immutable
@@ -2039,11 +2063,11 @@ steps:
path: /github-app
- commands:
- echo $DRONE_RUNNER_NAME
- image: alpine:3.20.3
+ image: alpine:3.21.3
name: identify-runner
- commands:
- mkdir -p bin
- - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.1/grabpl
+ - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.2/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -2052,7 +2076,7 @@ steps:
depends_on: []
environment:
CGO_ENABLED: 0
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: compile-build-cmd
- commands:
- '# It is required that code generated from Thema/CUE be committed and in sync
@@ -2062,7 +2086,7 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-cue
depends_on: []
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: verify-gen-cue
- commands:
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
@@ -2071,7 +2095,7 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-jsonnet
depends_on: []
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: verify-gen-jsonnet
- commands:
- yarn install --immutable || yarn install --immutable
@@ -2102,12 +2126,14 @@ steps:
image: node:22.11.0-alpine
name: build-frontend-packages
- commands:
- - docker run --privileged --rm tonistiigi/binfmt --install all
+ - docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --version
+ - docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --uninstall 'qemu-*'
+ - docker run --privileged --rm tonistiigi/binfmt:qemu-v7.0.0-28 --install all
- /src/grafana-build artifacts -a targz:grafana:linux/amd64 -a targz:grafana:linux/arm64
-a targz:grafana:linux/arm/v7 -a docker:grafana:linux/amd64 -a docker:grafana:linux/amd64:ubuntu
-a docker:grafana:linux/arm64 -a docker:grafana:linux/arm64:ubuntu -a docker:grafana:linux/arm/v7
- -a docker:grafana:linux/arm/v7:ubuntu --go-version=1.23.5 --yarn-cache=$$YARN_CACHE_FOLDER
- --build-id=$$DRONE_BUILD_NUMBER --ubuntu-base=ubuntu:22.04 --alpine-base=alpine:3.20.3
+ -a docker:grafana:linux/arm/v7:ubuntu --go-version=1.23.7 --yarn-cache=$$YARN_CACHE_FOLDER
+ --build-id=$$DRONE_BUILD_NUMBER --ubuntu-base=ubuntu:22.04 --alpine-base=alpine:3.21.3
--tag-format='{{ .version_base }}-{{ .buildID }}-{{ .arch }}' --ubuntu-tag-format='{{
.version_base }}-{{ .buildID }}-ubuntu-{{ .arch }}' --verify='false' --grafana-dir=$$PWD
> packages.txt
@@ -2168,7 +2194,7 @@ steps:
GF_APP_MODE: development
GF_SERVER_HTTP_PORT: "3001"
GF_SERVER_ROUTER_LOGGING: "1"
- image: alpine:3.20.3
+ image: alpine:3.21.3
name: grafana-server
- commands:
- ./bin/build e2e-tests --port 3001 --suite dashboards-suite
@@ -2572,7 +2598,7 @@ services:
steps:
- commands:
- mkdir -p bin
- - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.1/grabpl
+ - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.2/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -2581,11 +2607,11 @@ steps:
depends_on: []
environment:
CGO_ENABLED: 0
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: compile-build-cmd
- commands:
- echo $DRONE_RUNNER_NAME
- image: alpine:3.20.3
+ image: alpine:3.21.3
name: identify-runner
- commands:
- '# It is required that code generated from Thema/CUE be committed and in sync
@@ -2595,7 +2621,7 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-cue
depends_on: []
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: verify-gen-cue
- commands:
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
@@ -2604,14 +2630,14 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-jsonnet
depends_on: []
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: verify-gen-jsonnet
- commands:
- apk add --update make
- make gen-go
depends_on:
- verify-gen-cue
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: wire-install
- commands:
- dockerize -wait tcp://postgres:5432 -timeout 120s
@@ -2632,7 +2658,7 @@ steps:
GRAFANA_TEST_DB: postgres
PGPASSWORD: grafanatest
POSTGRES_HOST: postgres
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: postgres-integration-tests
- commands:
- dockerize -wait tcp://mysql80:3306 -timeout 120s
@@ -2653,7 +2679,7 @@ steps:
environment:
GRAFANA_TEST_DB: mysql
MYSQL_HOST: mysql80
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: mysql-8.0-integration-tests
- commands:
- dockerize -wait tcp://redis:6379 -timeout 120s
@@ -2669,7 +2695,7 @@ steps:
- wait-for-redis
environment:
REDIS_URL: redis://redis:6379/0
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: redis-integration-tests
- commands:
- dockerize -wait tcp://memcached:11211 -timeout 120s
@@ -2685,7 +2711,7 @@ steps:
- wait-for-memcached
environment:
MEMCACHED_HOSTS: memcached:11211
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: memcached-integration-tests
- commands:
- dockerize -wait tcp://mimir_backend:8080 -timeout 120s
@@ -2701,7 +2727,7 @@ steps:
environment:
AM_TENANT_ID: test
AM_URL: http://mimir_backend:8080
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: remote-alertmanager-integration-tests
trigger:
branch: main
@@ -2830,7 +2856,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
- image: alpine:3.20.3
+ image: alpine:3.21.3
name: identify-runner
- commands:
- yarn install --immutable || yarn install --immutable
@@ -2839,7 +2865,7 @@ steps:
name: yarn-install
- commands:
- apk add --update git bash
- - yarn betterer ci
+ - yarn betterer:ci
depends_on:
- yarn-install
image: node:22.11.0-alpine
@@ -2886,7 +2912,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
- image: alpine:3.20.3
+ image: alpine:3.21.3
name: identify-runner
- commands:
- yarn install --immutable || yarn install --immutable
@@ -2916,6 +2942,16 @@ steps:
- yarn-install
image: node:22-bookworm
name: verify-i18n
+- commands:
+ - yarn generate-apis
+ - "\n file_diff=$(git diff ':!conf')\n if [ -n \"$file_diff\"
+ ]; then\n echo $file_diff\n echo \"\nAPI client
+ generation has not been committed. Please run 'yarn generate-apis', commit the
+ changes and push again.\"\n exit 1\n fi\n "
+ depends_on:
+ - yarn-install
+ image: node:22-bookworm
+ name: verify-api-clients
trigger:
branch:
- instant
@@ -2950,7 +2986,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
- image: alpine:3.20.3
+ image: alpine:3.21.3
name: identify-runner
- commands:
- '# It is required that code generated from Thema/CUE be committed and in sync
@@ -2960,7 +2996,7 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-cue
depends_on: []
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: verify-gen-cue
- commands:
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
@@ -2969,21 +3005,21 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-jsonnet
depends_on: []
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: verify-gen-jsonnet
- commands:
- apk add --update make
- make gen-go
depends_on:
- verify-gen-cue
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: wire-install
- commands:
- apk add --update build-base shared-mime-info shared-mime-info-lang
- go list -f '{{.Dir}}/...' -m | xargs go test -short -covermode=atomic -timeout=5m
depends_on:
- wire-install
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: test-backend
- commands:
- apk add --update build-base
@@ -2992,7 +3028,7 @@ steps:
| grep -o '\(.*\)/' | sort -u)
depends_on:
- wire-install
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: test-backend-integration
trigger:
branch:
@@ -3028,29 +3064,29 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
- image: alpine:3.20.3
+ image: alpine:3.21.3
name: identify-runner
- commands:
- go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd
depends_on: []
environment:
CGO_ENABLED: 0
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: compile-build-cmd
- commands:
- apk add --update make
- make gen-go
depends_on: []
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: wire-install
- commands:
- go run scripts/modowners/modowners.go check go.mod
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: validate-modfile
- commands:
- apk add --update make
- make swagger-validate
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: validate-openapi-spec
trigger:
branch:
@@ -3120,7 +3156,7 @@ services:
steps:
- commands:
- mkdir -p bin
- - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.1/grabpl
+ - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.2/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -3129,11 +3165,11 @@ steps:
depends_on: []
environment:
CGO_ENABLED: 0
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: compile-build-cmd
- commands:
- echo $DRONE_RUNNER_NAME
- image: alpine:3.20.3
+ image: alpine:3.21.3
name: identify-runner
- commands:
- '# It is required that code generated from Thema/CUE be committed and in sync
@@ -3143,7 +3179,7 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-cue
depends_on: []
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: verify-gen-cue
- commands:
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
@@ -3152,14 +3188,14 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-jsonnet
depends_on: []
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: verify-gen-jsonnet
- commands:
- apk add --update make
- make gen-go
depends_on:
- verify-gen-cue
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: wire-install
- commands:
- dockerize -wait tcp://postgres:5432 -timeout 120s
@@ -3180,7 +3216,7 @@ steps:
GRAFANA_TEST_DB: postgres
PGPASSWORD: grafanatest
POSTGRES_HOST: postgres
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: postgres-integration-tests
- commands:
- dockerize -wait tcp://mysql80:3306 -timeout 120s
@@ -3201,7 +3237,7 @@ steps:
environment:
GRAFANA_TEST_DB: mysql
MYSQL_HOST: mysql80
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: mysql-8.0-integration-tests
- commands:
- dockerize -wait tcp://redis:6379 -timeout 120s
@@ -3217,7 +3253,7 @@ steps:
- wait-for-redis
environment:
REDIS_URL: redis://redis:6379/0
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: redis-integration-tests
- commands:
- dockerize -wait tcp://memcached:11211 -timeout 120s
@@ -3233,7 +3269,7 @@ steps:
- wait-for-memcached
environment:
MEMCACHED_HOSTS: memcached:11211
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: memcached-integration-tests
- commands:
- dockerize -wait tcp://mimir_backend:8080 -timeout 120s
@@ -3249,7 +3285,7 @@ steps:
environment:
AM_TENANT_ID: test
AM_URL: http://mimir_backend:8080
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: remote-alertmanager-integration-tests
trigger:
branch:
@@ -3336,11 +3372,11 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
- image: alpine:3.20.3
+ image: alpine:3.21.3
name: identify-runner
- commands:
- mkdir -p bin
- - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.1/grabpl
+ - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.2/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -3349,7 +3385,7 @@ steps:
depends_on: []
environment:
CGO_ENABLED: 0
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: compile-build-cmd
- commands:
- ./bin/build artifacts docker fetch --edition oss
@@ -3468,11 +3504,11 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
- image: alpine:3.20.3
+ image: alpine:3.21.3
name: identify-runner
- commands:
- mkdir -p bin
- - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.1/grabpl
+ - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.2/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
@@ -3481,7 +3517,7 @@ steps:
depends_on: []
environment:
CGO_ENABLED: 0
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: compile-build-cmd
- commands:
- ./bin/build artifacts docker fetch --edition oss
@@ -3622,7 +3658,7 @@ steps:
depends_on: []
environment:
CGO_ENABLED: 0
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: compile-build-cmd
- commands:
- ./bin/build artifacts packages --artifacts-editions=oss --tag $${DRONE_TAG} --src-bucket
@@ -3714,7 +3750,7 @@ steps:
depends_on: []
environment:
CGO_ENABLED: 0
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: compile-build-cmd
- commands:
- yarn install --immutable || yarn install --immutable
@@ -3814,7 +3850,7 @@ steps:
depends_on: []
environment:
CGO_ENABLED: 0
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: compile-build-cmd
- depends_on:
- compile-build-cmd
@@ -3911,7 +3947,7 @@ steps:
depends_on: []
environment:
CGO_ENABLED: 0
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: compile-build-cmd
- commands:
- ./bin/build publish grafana-com --edition oss ${DRONE_TAG}
@@ -3958,7 +3994,7 @@ steps:
environment:
_EXPERIMENTAL_DAGGER_CLOUD_TOKEN:
from_secret: dagger_token
- ALPINE_BASE: alpine:3.20.3
+ ALPINE_BASE: alpine:3.21.3
CDN_DESTINATION:
from_secret: rgm_cdn_destination
DESTINATION:
@@ -3973,7 +4009,7 @@ steps:
from_secret: grafana_api_key
GCP_KEY_BASE64:
from_secret: gcp_key_base64
- GO_VERSION: 1.23.5
+ GO_VERSION: 1.23.7
GPG_PASSPHRASE:
from_secret: packages_gpg_passphrase
GPG_PRIVATE_KEY:
@@ -4033,7 +4069,7 @@ steps:
environment:
_EXPERIMENTAL_DAGGER_CLOUD_TOKEN:
from_secret: dagger_token
- ALPINE_BASE: alpine:3.20.3
+ ALPINE_BASE: alpine:3.21.3
CDN_DESTINATION:
from_secret: rgm_cdn_destination
DESTINATION:
@@ -4048,7 +4084,7 @@ steps:
from_secret: grafana_api_key
GCP_KEY_BASE64:
from_secret: gcp_key_base64
- GO_VERSION: 1.23.5
+ GO_VERSION: 1.23.7
GPG_PASSPHRASE:
from_secret: packages_gpg_passphrase
GPG_PRIVATE_KEY:
@@ -4083,51 +4119,6 @@ volumes:
path: /var/run/docker.sock
name: docker
---
-clone:
- retries: 3
-depends_on: []
-environment:
- EDITION: oss
-image_pull_secrets:
-- gcr
-- gar
-kind: pipeline
-name: release-whatsnew-checker
-node:
- type: no-parallel
-platform:
- arch: amd64
- os: linux
-services: []
-steps:
-- commands:
- - go build -o ./bin/build -ldflags '-extldflags -static' ./pkg/build/cmd
- depends_on: []
- environment:
- CGO_ENABLED: 0
- image: golang:1.23.5-alpine
- name: compile-build-cmd
-- commands:
- - ./bin/build whatsnew-checker
- depends_on:
- - compile-build-cmd
- image: golang:1.23.5-alpine
- name: whats-new-checker
-trigger:
- event:
- exclude:
- - promote
- ref:
- exclude:
- - refs/tags/*-cloud*
- include:
- - refs/tags/v*
-type: docker
-volumes:
-- host:
- path: /var/run/docker.sock
- name: docker
----
clone:
retries: 3
depends_on:
@@ -4195,7 +4186,7 @@ steps:
environment:
_EXPERIMENTAL_DAGGER_CLOUD_TOKEN:
from_secret: dagger_token
- ALPINE_BASE: alpine:3.20.3
+ ALPINE_BASE: alpine:3.21.3
CDN_DESTINATION:
from_secret: rgm_cdn_destination
DESTINATION:
@@ -4210,7 +4201,7 @@ steps:
from_secret: grafana_api_key
GCP_KEY_BASE64:
from_secret: gcp_key_base64
- GO_VERSION: 1.23.5
+ GO_VERSION: 1.23.7
GPG_PASSPHRASE:
from_secret: packages_gpg_passphrase
GPG_PRIVATE_KEY:
@@ -4297,7 +4288,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
- image: alpine:3.20.3
+ image: alpine:3.21.3
name: identify-runner
- commands:
- yarn install --immutable || yarn install --immutable
@@ -4306,7 +4297,7 @@ steps:
name: yarn-install
- commands:
- apk add --update git bash
- - yarn betterer ci
+ - yarn betterer:ci
depends_on:
- yarn-install
image: node:22.11.0-alpine
@@ -4351,7 +4342,7 @@ services: []
steps:
- commands:
- echo $DRONE_RUNNER_NAME
- image: alpine:3.20.3
+ image: alpine:3.21.3
name: identify-runner
- commands:
- '# It is required that code generated from Thema/CUE be committed and in sync
@@ -4361,7 +4352,7 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-cue
depends_on: []
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: verify-gen-cue
- commands:
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
@@ -4370,21 +4361,21 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-jsonnet
depends_on: []
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: verify-gen-jsonnet
- commands:
- apk add --update make
- make gen-go
depends_on:
- verify-gen-cue
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: wire-install
- commands:
- apk add --update build-base shared-mime-info shared-mime-info-lang
- go list -f '{{.Dir}}/...' -m | xargs go test -short -covermode=atomic -timeout=5m
depends_on:
- wire-install
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: test-backend
- commands:
- apk add --update build-base
@@ -4393,7 +4384,7 @@ steps:
| grep -o '\(.*\)/' | sort -u)
depends_on:
- wire-install
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: test-backend-integration
trigger:
cron:
@@ -4432,7 +4423,7 @@ steps:
environment:
_EXPERIMENTAL_DAGGER_CLOUD_TOKEN:
from_secret: dagger_token
- ALPINE_BASE: alpine:3.20.3
+ ALPINE_BASE: alpine:3.21.3
CDN_DESTINATION:
from_secret: rgm_cdn_destination
DESTINATION:
@@ -4447,7 +4438,7 @@ steps:
from_secret: grafana_api_key
GCP_KEY_BASE64:
from_secret: gcp_key_base64
- GO_VERSION: 1.23.5
+ GO_VERSION: 1.23.7
GPG_PASSPHRASE:
from_secret: packages_gpg_passphrase
GPG_PRIVATE_KEY:
@@ -4576,7 +4567,7 @@ steps:
environment:
_EXPERIMENTAL_DAGGER_CLOUD_TOKEN:
from_secret: dagger_token
- ALPINE_BASE: alpine:3.20.3
+ ALPINE_BASE: alpine:3.21.3
CDN_DESTINATION:
from_secret: rgm_cdn_destination
DESTINATION:
@@ -4591,7 +4582,7 @@ steps:
from_secret: grafana_api_key
GCP_KEY_BASE64:
from_secret: gcp_key_base64
- GO_VERSION: 1.23.5
+ GO_VERSION: 1.23.7
GPG_PASSPHRASE:
from_secret: packages_gpg_passphrase
GPG_PRIVATE_KEY:
@@ -4696,15 +4687,15 @@ steps:
path: /github-app
- commands:
- export GITHUB_TOKEN=$(cat /github-app/token)
- - 'dagger run --silent /src/grafana-build artifacts -a $${ARTIFACTS} --grafana-ref=$${GRAFANA_REF}
- --enterprise-ref=$${ENTERPRISE_REF} --grafana-repo=$${GRAFANA_REPO} --version=$${VERSION} '
- - --go-version=1.23.5
+ - dagger run --silent /src/grafana-build artifacts -a $${ARTIFACTS} --grafana-ref=$${GRAFANA_REF}
+ --enterprise-ref=$${ENTERPRISE_REF} --grafana-repo=$${GRAFANA_REPO} --version=$${VERSION}
+ --go-version=1.23.7
depends_on:
- github-app-generate-token
environment:
_EXPERIMENTAL_DAGGER_CLOUD_TOKEN:
from_secret: dagger_token
- ALPINE_BASE: alpine:3.20.3
+ ALPINE_BASE: alpine:3.21.3
CDN_DESTINATION:
from_secret: rgm_cdn_destination
DESTINATION:
@@ -4719,7 +4710,7 @@ steps:
from_secret: grafana_api_key
GCP_KEY_BASE64:
from_secret: gcp_key_base64
- GO_VERSION: 1.23.5
+ GO_VERSION: 1.23.7
GPG_PASSPHRASE:
from_secret: packages_gpg_passphrase
GPG_PRIVATE_KEY:
@@ -4743,6 +4734,8 @@ steps:
- printenv GCP_KEY_BASE64 | base64 -d > /tmp/key.json
- gcloud auth activate-service-account --key-file=/tmp/key.json
- gcloud storage cp -r dist/* $${UPLOAD_TO}
+ depends_on:
+ - rgm-build
environment:
_EXPERIMENTAL_DAGGER_CLOUD_TOKEN:
from_secret: dagger_token
@@ -4783,6 +4776,8 @@ volumes:
name: docker
- name: github-app
path: /github-app
+- name: github-app
+ temp: {}
---
clone:
retries: 3
@@ -4837,13 +4832,13 @@ services:
steps:
- commands:
- mkdir -p bin
- - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.1/grabpl
+ - curl -fL -o bin/grabpl https://grafana-downloads.storage.googleapis.com/grafana-build-pipeline/v3.1.2/grabpl
- chmod +x bin/grabpl
image: byrnedo/alpine-curl:0.1.8
name: grabpl
- commands:
- echo $DRONE_RUNNER_NAME
- image: alpine:3.20.3
+ image: alpine:3.21.3
name: identify-runner
- commands:
- '# It is required that code generated from Thema/CUE be committed and in sync
@@ -4853,7 +4848,7 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-cue
depends_on: []
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: verify-gen-cue
- commands:
- '# It is required that generated jsonnet is committed and in sync with its inputs.'
@@ -4862,14 +4857,14 @@ steps:
- apk add --update make
- CODEGEN_VERIFY=1 make gen-jsonnet
depends_on: []
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: verify-gen-jsonnet
- commands:
- apk add --update make
- make gen-go
depends_on:
- verify-gen-cue
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: wire-install
- commands:
- dockerize -wait tcp://postgres:5432 -timeout 120s
@@ -4890,7 +4885,7 @@ steps:
GRAFANA_TEST_DB: postgres
PGPASSWORD: grafanatest
POSTGRES_HOST: postgres
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: postgres-integration-tests
- commands:
- dockerize -wait tcp://mysql80:3306 -timeout 120s
@@ -4911,7 +4906,7 @@ steps:
environment:
GRAFANA_TEST_DB: mysql
MYSQL_HOST: mysql80
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: mysql-8.0-integration-tests
- commands:
- dockerize -wait tcp://redis:6379 -timeout 120s
@@ -4927,7 +4922,7 @@ steps:
- wait-for-redis
environment:
REDIS_URL: redis://redis:6379/0
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: redis-integration-tests
- commands:
- dockerize -wait tcp://memcached:11211 -timeout 120s
@@ -4943,7 +4938,7 @@ steps:
- wait-for-memcached
environment:
MEMCACHED_HOSTS: memcached:11211
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: memcached-integration-tests
- commands:
- dockerize -wait tcp://mimir_backend:8080 -timeout 120s
@@ -4959,7 +4954,7 @@ steps:
environment:
AM_TENANT_ID: test
AM_URL: http://mimir_backend:8080
- image: golang:1.23.5-alpine
+ image: golang:1.23.7-alpine
name: remote-alertmanager-integration-tests
trigger:
event:
@@ -5262,12 +5257,12 @@ steps:
- commands:
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM docker:27-cli
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM alpine/git:2.40.1
- - trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM golang:1.23.5-alpine
+ - trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM golang:1.23.7-alpine
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM node:22.11.0-alpine
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM node:22-bookworm
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM google/cloud-sdk:431.0.0
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM grafana/grafana-ci-deploy:1.3.3
- - trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM alpine:3.20.3
+ - trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM alpine:3.21.3
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM ubuntu:22.04
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM byrnedo/alpine-curl:0.1.8
- trivy --exit-code 0 --severity UNKNOWN,LOW,MEDIUM plugins/slack
@@ -5300,12 +5295,12 @@ steps:
- commands:
- trivy --exit-code 1 --severity HIGH,CRITICAL docker:27-cli
- trivy --exit-code 1 --severity HIGH,CRITICAL alpine/git:2.40.1
- - trivy --exit-code 1 --severity HIGH,CRITICAL golang:1.23.5-alpine
+ - trivy --exit-code 1 --severity HIGH,CRITICAL golang:1.23.7-alpine
- trivy --exit-code 1 --severity HIGH,CRITICAL node:22.11.0-alpine
- trivy --exit-code 1 --severity HIGH,CRITICAL node:22-bookworm
- trivy --exit-code 1 --severity HIGH,CRITICAL google/cloud-sdk:431.0.0
- trivy --exit-code 1 --severity HIGH,CRITICAL grafana/grafana-ci-deploy:1.3.3
- - trivy --exit-code 1 --severity HIGH,CRITICAL alpine:3.20.3
+ - trivy --exit-code 1 --severity HIGH,CRITICAL alpine:3.21.3
- trivy --exit-code 1 --severity HIGH,CRITICAL ubuntu:22.04
- trivy --exit-code 1 --severity HIGH,CRITICAL byrnedo/alpine-curl:0.1.8
- trivy --exit-code 1 --severity HIGH,CRITICAL plugins/slack
@@ -5569,6 +5564,6 @@ kind: secret
name: gcr_credentials
---
kind: signature
-hmac: 154c1f072294cef09ba4f579eed30b1e29bc5c263897c862f4574432d321502c
+hmac: 33f2e5615dfd7889899f9f8f16f7716190fa637fe98f1efd7e29607f8946be7d
...
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index bb3c9871f91..7ff10207c35 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -38,7 +38,7 @@
/docs/sources/ @irenerl24
-/docs/sources/alerting/ @brendamuir
+/docs/sources/alerting/ @JohnnyK-Grafana
/docs/sources/dashboards/ @imatwawana
/docs/sources/datasources/ @lwandz13
/docs/sources/panels-visualizations/ @imatwawana
@@ -66,9 +66,14 @@
/scripts/go-workspace @grafana/grafana-app-platform-squad
/hack/ @grafana/grafana-app-platform-squad
+/pkg/apis/provisioning @grafana/grafana-git-ui-sync-team
+/public/app/features/provisioning @grafana/grafana-git-ui-sync-team
+/pkg/registry/apis/provisioning @grafana/grafana-git-ui-sync-team
+
/apps/alerting/ @grafana/alerting-backend
+/apps/dashboard/ @grafana/grafana-app-platform-squad @grafana/dashboards-squad
/apps/playlist/ @grafana/grafana-app-platform-squad
-/apps/investigation/ @fcjack @matryer
+/apps/investigations/ @fcjack @matryer @svennergr
/apps/advisor/ @grafana/plugins-platform-backend
/pkg/api/ @grafana/grafana-backend-group
/pkg/apis/ @grafana/grafana-app-platform-squad
@@ -238,6 +243,7 @@
/devenv/dev-dashboards/extensions/ @grafana/plugins-platform-frontend
/devenv/docker/blocks/alert_webhook_listener/ @grafana/alerting-backend
+/devenv/docker/blocks/stateful_webhook/ @grafana/alerting-backend
/devenv/docker/blocks/caddy_tls/ @grafana/alerting-backend
/devenv/docker/blocks/clickhouse/ @grafana/partner-datasources
/devenv/docker/blocks/collectd/ @grafana/observability-metrics
@@ -377,6 +383,11 @@
/crowdin.yml @grafana/grafana-frontend-platform
/public/locales/ @grafana/grafana-frontend-platform
+/public/locales/de-DE @grafanabot
+/public/locales/es-ES @grafanabot
+/public/locales/fr-FR @grafanabot
+/public/locales/pt-BR @grafanabot
+/public/locales/zh-Hans @grafanabot
/public/app/core/internationalization/ @grafana/grafana-frontend-platform
/e2e/ @grafana/grafana-frontend-platform
/e2e/cloud-plugins-suite/ @grafana/partner-datasources
@@ -402,7 +413,7 @@
/packages/grafana-schema/src/**/*canvas* @grafana/dataviz-squad
/packages/grafana-schema/src/**/*tempo* @grafana/observability-traces-and-profiling
/packages/grafana-sql/ @grafana/partner-datasources @grafana/oss-big-tent
-/packages/grafana-ui/.storybook/ @grafana/plugins-platform-frontend
+/packages/grafana-ui/.storybook/ @grafana/grafana-frontend-platform
/packages/grafana-ui/src/components/ @grafana/grafana-frontend-platform
/packages/grafana-ui/src/components/BarGauge/ @grafana/dataviz-squad
/packages/grafana-ui/src/components/DataLinks/ @grafana/dataviz-squad
@@ -421,7 +432,7 @@
/packages/grafana-ui/src/graveyard/Graph/ @grafana/dataviz-squad
/packages/grafana-ui/src/graveyard/GraphNG/ @grafana/dataviz-squad
/packages/grafana-ui/src/graveyard/TimeSeries/ @grafana/dataviz-squad
-/packages/grafana-ui/src/utils/storybook/ @grafana/plugins-platform-frontend
+/packages/grafana-ui/src/utils/storybook/ @grafana/grafana-frontend-platform
# root files, mostly frontend
/.browserslistrc @grafana/frontend-ops
@@ -435,6 +446,7 @@
/.betterer.eslint.config.js @grafana/frontend-ops
/.gitattributes @grafana/frontend-ops
/.gitignore @grafana/frontend-ops
+/.ignore @grafana/frontend-ops
/.nvmrc @grafana/frontend-ops
/.prettierignore @grafana/frontend-ops
/.yarn @grafana/frontend-ops
@@ -455,6 +467,7 @@
playwright.config.ts @grafana/plugins-platform-frontend
# public folder
+/public/app/api/ @grafana/grafana-frontend-platform
/public/app/core/ @grafana/grafana-frontend-platform
/public/app/core/components/TimePicker/ @grafana/grafana-frontend-platform
/public/app/core/components/Layers/ @grafana/dataviz-squad
@@ -489,8 +502,9 @@ playwright.config.ts @grafana/plugins-platform-frontend
/public/app/features/dimensions/ @grafana/dataviz-squad
/public/app/features/dataframe-import/ @grafana/dataviz-squad
/public/app/features/explore/ @grafana/observability-traces-and-profiling
-/public/app/features/expressions/ @grafana/observability-metrics
+/public/app/features/expressions/ @grafana/grafana-datasources-core-services
/public/app/features/folders/ @grafana/grafana-frontend-platform
+/public/app/features/iam/ @grafana/grafana-frontend-platform
/public/app/features/inspector/ @grafana/dashboards-squad
/public/app/features/invites/ @grafana/grafana-frontend-platform
/public/app/features/library-panels/ @grafana/dashboards-squad
@@ -504,7 +518,6 @@ playwright.config.ts @grafana/plugins-platform-frontend
/public/app/features/playlist/ @grafana/dashboards-squad
/public/app/features/plugins/ @grafana/plugins-platform-frontend
/public/app/features/profile/ @grafana/grafana-frontend-platform
-/public/app/features/query-library/ @grafana/grafana-frontend-platform
/public/app/features/runtime/ @ryantxu
/public/app/features/query/ @grafana/dashboards-squad
/public/app/features/sandbox/ @grafana/grafana-frontend-platform
@@ -533,6 +546,7 @@ playwright.config.ts @grafana/plugins-platform-frontend
/public/app/plugins/panel/heatmap/ @grafana/dataviz-squad
/public/app/plugins/panel/histogram/ @grafana/dataviz-squad
/public/app/plugins/panel/logs/ @grafana/observability-logs
+/public/app/plugins/panel/logs-new/ @grafana/observability-logs
/public/app/plugins/panel/nodeGraph/ @grafana/observability-traces-and-profiling @grafana/app-o11y-visualizations
/public/app/plugins/panel/traces/ @grafana/observability-traces-and-profiling
/public/app/plugins/panel/flamegraph/ @grafana/observability-traces-and-profiling
@@ -581,6 +595,7 @@ playwright.config.ts @grafana/plugins-platform-frontend
/public/app/features/explore/NodeGraph/ @grafana/observability-traces-and-profiling
/public/app/features/explore/FlameGraph/ @grafana/observability-traces-and-profiling
/public/app/features/explore/TraceView/ @grafana/observability-traces-and-profiling
+/public/app/features/explore/QueryLibrary/ @grafana/grafana-frontend-platform
/public/api-merged.json @grafana/grafana-backend-group
/public/api-enterprise-spec.json @grafana/grafana-backend-group
@@ -593,9 +608,6 @@ playwright.config.ts @grafana/plugins-platform-frontend
/public/app/AppWrapper.tsx @grafana/frontend-ops
/public/app/partials/ @grafana/grafana-frontend-platform
-
-
-
/scripts/benchmark-access-control.sh @grafana/access-squad
/scripts/check-breaking-changes.sh @grafana/plugins-platform-frontend
/scripts/ci-* @grafana/grafana-developer-enablement-squad
@@ -610,7 +622,7 @@ playwright.config.ts @grafana/plugins-platform-frontend
/scripts/import_many_dashboards.sh @torkelo
/scripts/mixin-check.sh @bergquist
/scripts/openapi3/ @grafana/grafana-operator-experience-squad
-/scripts/prepare-packagejson.js @grafana/frontend-ops
+/scripts/prepare-npm-package.js @grafana/frontend-ops
/scripts/protobuf-check.sh @grafana/plugins-platform-backend
/scripts/stripnulls.sh @grafana/grafana-as-code
/scripts/tag_release.sh @grafana/grafana-developer-enablement-squad
@@ -620,6 +632,7 @@ playwright.config.ts @grafana/plugins-platform-frontend
/scripts/cleanup-husky.sh @grafana/frontend-ops
/scripts/verify-repo-update/ @grafana/grafana-developer-enablement-squad
/scripts/generate-rtk-apis.ts @grafana/grafana-frontend-platform
+/scripts/process-specs.ts @grafana/grafana-frontend-platform
/scripts/generate-alerting-rtk-apis.ts @grafana/alerting-frontend
/scripts/levitate-parse-json-report.js @grafana/plugins-platform-frontend
/scripts/levitate-show-affected-plugins.js @grafana/plugins-platform-frontend
@@ -633,9 +646,6 @@ playwright.config.ts @grafana/plugins-platform-frontend
.betterer.results @grafanabot
.betterer.ts @grafana/grafana-frontend-platform
-# @grafana/ui component documentation
-*.mdx @grafana/plugins-platform-frontend
-
# Design system
/public/img/icons/unicons/ @grafana/design-system
@@ -746,14 +756,20 @@ embed.go @grafana/grafana-as-code
/.github/pr-checks.json @tolzhabayev
/.github/pr-commands.json @tolzhabayev
/.github/renovate.json5 @grafana/frontend-ops
+/.github/actions/test-coverage-processor/action.yml @grafana/grafana-backend-group
+/.github/actions/setup-grafana-bench/ @Proximyst
+/.github/workflows/add-to-whats-new.yml @grafana/docs-tooling
/.github/workflows/auto-triager/ @grafana/plugins-platform-frontend
/.github/workflows/alerting-swagger-gen.yml @grafana/alerting-backend
+/.github/workflows/alerting-update-module.yml @grafana/alerting-backend
/.github/workflows/auto-milestone.yml @grafana/grafana-developer-enablement-squad
/.github/workflows/backport.yml @grafana/grafana-developer-enablement-squad
/.github/workflows/bump-version.yml @grafana/grafana-developer-enablement-squad
/.github/workflows/close-milestone.yml @grafana/grafana-developer-enablement-squad
/.github/workflows/release-pr.yml @grafana/grafana-developer-enablement-squad
/.github/workflows/release-comms.yml @grafana/grafana-developer-enablement-squad
+/.github/workflows/migrate-prs.yml @grafana/grafana-developer-enablement-squad
+/.github/workflows/create-next-release-branch.yml @grafana/grafana-developer-enablement-squad
/.github/workflows/codeowners-validator.yml @tolzhabayev
/.github/workflows/codeql-analysis.yml @DanCech
/.github/workflows/commands.yml @torkelo
@@ -763,21 +779,23 @@ embed.go @grafana/grafana-as-code
/.github/workflows/doc-validator.yml @grafana/docs-tooling
/.github/workflows/deploy-pr-preview.yml @grafana/docs-tooling
/.github/workflows/epic-add-to-platform-ux-parent-project.yml @meanmina
+/.github/workflows/feature-toggles-ci.yml @grafana/docs-tooling
/.github/workflows/github-release.yml @grafana/grafana-developer-enablement-squad
/.github/workflows/issue-opened.yml @grafana/grafana-community-support
/.github/workflows/metrics-collector.yml @torkelo
/.github/workflows/milestone.yml @tolzhabayev
+/.github/workflows/pr-backend-code-checks.yml @grafana/grafana-backend-group
/.github/workflows/pr-checks.yml @tolzhabayev
/.github/workflows/pr-codeql-analysis-go.yml @DanCech
/.github/workflows/pr-codeql-analysis-javascript.yml @DanCech
/.github/workflows/pr-codeql-analysis-python.yml @DanCech
/.github/workflows/pr-commands.yml @tolzhabayev
/.github/workflows/pr-patch-check.yml @grafana/grafana-developer-enablement-squad
+/.github/workflows/pr-backend-unit-tests.yml @grafana/grafana-backend-group
/.github/workflows/sync-mirror.yml @grafana/grafana-developer-enablement-squad
/.github/workflows/publish-technical-documentation-next.yml @grafana/docs-tooling
/.github/workflows/publish-technical-documentation-release.yml @grafana/docs-tooling
/.github/workflows/remove-milestone.yml @grafana/grafana-developer-enablement-squad
-/.github/workflows/sbom-report.yml @grafana/security-team
/.github/workflows/scripts/json-file-to-job-output.js @grafana/plugins-platform-frontend
/.github/workflows/stale.yml @grafana/grafana-developer-enablement-squad
/.github/workflows/update-changelog.yml @grafana/grafana-developer-enablement-squad
@@ -787,6 +805,7 @@ embed.go @grafana/grafana-as-code
/.github/workflows/publish-kinds-release.yml @grafana/platform-monitoring
/.github/workflows/verify-kinds.yml @grafana/platform-monitoring
/.github/workflows/dashboards-issue-add-label.yml @grafana/dashboards-squad
+/.github/workflows/run-schema-v2-e2e.yml @grafana/dashboards-squad
/.github/workflows/ephemeral-instances-pr-comment.yml @grafana/grafana-backend-services-squad
/.github/workflows/create-security-patch-from-security-mirror.yml @grafana/grafana-developer-enablement-squad
/.github/workflows/core-plugins-build-and-release.yml @grafana/plugins-platform-frontend @grafana/plugins-platform-backend
@@ -799,6 +818,9 @@ embed.go @grafana/grafana-as-code
/.github/workflows/trivy-scan.yml @grafana/grafana-backend-services-squad
/.github/workflows/changelog.yml @zserge
/.github/workflows/actions/changelog @zserge
+/.github/workflows/frontend-unit-tests.yml @grafana/grafana-frontend-platform
+/.github/workflows/frontend-lint.yml @grafana/grafana-frontend-platform
+/.github/workflows/analytics-events-report.yml @grafana/grafana-frontend-platform
# Generated files not requiring owner approval
/packages/grafana-data/src/types/featureToggles.gen.ts @grafanabot
diff --git a/.github/actions/setup-grafana-bench/action.yml b/.github/actions/setup-grafana-bench/action.yml
new file mode 100644
index 00000000000..624ad243b7b
--- /dev/null
+++ b/.github/actions/setup-grafana-bench/action.yml
@@ -0,0 +1,44 @@
+name: 'Setup Grafana Bench'
+description: 'Sets up and installs Grafana Bench'
+
+inputs:
+ github-app-name:
+ description: 'Name of the GitHub App in Vault'
+ required: false
+ default: 'grafana-ci-bot'
+ branch:
+ description: 'The branch to install from'
+ required: false
+ default: 'main'
+
+runs:
+ using: "composite"
+ steps:
+ - name: Retrieve GitHub App secrets
+ id: get-secrets
+ uses: grafana/shared-workflows/actions/get-vault-secrets@get-vault-secrets-v1.0.1
+ with:
+ repo_secrets: |
+ APP_ID=${{ inputs.github-app-name }}:app-id
+ APP_INSTALLATION_ID=${{ inputs.github-app-name }}:app-installation-id
+ PRIVATE_KEY=${{ inputs.github-app-name }}:private-key
+
+ - name: Generate GitHub App token
+ id: generate_token
+ uses: actions/create-github-app-token@v1
+ with:
+ app-id: ${{ env.APP_ID }}
+ private-key: ${{ env.PRIVATE_KEY }}
+ repositories: "grafana-bench"
+ owner: "grafana"
+
+ - name: Setup Bench
+ shell: bash
+ env:
+ GH_TOKEN: ${{ steps.generate_token.outputs.token }}
+ run: |
+ git clone https://x-access-token:${GH_TOKEN}@github.com/grafana/grafana-bench.git ../grafana-bench
+
+ cd ../grafana-bench
+ git switch ${{ inputs.branch }}
+ go install .
diff --git a/.github/actions/test-coverage-processor/action.yml b/.github/actions/test-coverage-processor/action.yml
new file mode 100644
index 00000000000..7560031e846
--- /dev/null
+++ b/.github/actions/test-coverage-processor/action.yml
@@ -0,0 +1,48 @@
+name: 'Go Coverage Processor'
+description: 'Process Go test coverage files and generate reports'
+
+inputs:
+ test-type:
+ description: 'Type of test (e.g., be-unit, be-integration)'
+ required: true
+ type: string
+ coverage-file:
+ description: 'Path to the Go coverage file (.cov)'
+ required: true
+ type: string
+ codecov-token:
+ description: 'Token for CodeCov (required for CodeCov reporting)'
+ required: false
+ default: ''
+ codecov-flag:
+ description: 'Flag to categorize the upload to CodeCov'
+ required: false
+ default: ''
+ codecov-name:
+ description: 'Custom name for the upload to CodeCov'
+ required: false
+ default: ''
+
+runs:
+ using: 'composite'
+ steps:
+ - name: Process Go coverage output
+ shell: bash
+ run: |
+ # Ensure valid coverage file even if empty
+ if [ ! -s ${{ inputs.coverage-file }} ]; then
+ echo "Coverage file is empty, creating a minimal valid file"
+ echo "mode: set" > ${{ inputs.coverage-file }}
+ fi
+
+ - name: Report coverage to CodeCov
+ uses: codecov/codecov-action@v5
+ if: inputs.codecov-token != ''
+ with:
+ files: ${{ inputs.coverage-file }}
+ flags: ${{ inputs.codecov-flag || inputs.test-type }}
+ name: ${{ inputs.codecov-name || inputs.test-type }}
+ slug: grafana/grafana
+ # This URL doesn't use the Google auth, but is much more locked down. As such, it requires OIDC or a CodeCov-provided token to do anything.
+ url: https://codecov-webhook.grafana-dev.net
+ token: ${{ inputs.codecov-token }}
diff --git a/.github/commands.json b/.github/commands.json
index fb10220fb21..e6c2036d7cf 100644
--- a/.github/commands.json
+++ b/.github/commands.json
@@ -640,7 +640,7 @@
"name": "area/configuration",
"action": "addToProject",
"addToProject": {
- "url": "https://github.com/orgs/grafana/projects/96"
+ "url": "https://github.com/orgs/grafana/projects/665"
}
},
{
@@ -744,7 +744,7 @@
"name": "area/backend/db/postgres",
"action": "addToProject",
"addToProject": {
- "url": "https://github.com/orgs/grafana/projects/96"
+ "url": "https://github.com/orgs/grafana/projects/835"
}
},
{
@@ -1115,14 +1115,6 @@
"url": "https://github.com/orgs/grafana/projects/202"
}
},
- {
- "type": "label",
- "name": "area/editor",
- "action": "addToProject",
- "addToProject": {
- "url": "https://github.com/grafana/grafana/projects/21"
- }
- },
{
"type": "label",
"name": "area/data/export",
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index f37f7a732f6..0de94ce207d 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -8,7 +8,7 @@ updates:
directories:
- "/"
- "/apps/playlist"
- - "/apps/investigation"
+ - "/apps/investigations"
- "/pkg/aggregator"
- "/pkg/apimachinery"
- "/pkg/apiserver"
diff --git a/.github/pr-commands.json b/.github/pr-commands.json
index 1803aa29a8a..d211b5cce3a 100644
--- a/.github/pr-commands.json
+++ b/.github/pr-commands.json
@@ -247,7 +247,8 @@
"/pkg/services/sqlstore/migrations/ualert/**/*",
"/pkg/services/alerting/**/*",
"/public/app/features/alerting/**/*",
- "/pkg/tests/api/alerting/**/*"
+ "/pkg/tests/api/alerting/**/*",
+ "/pkg/tests/alertmanager/**/*"
],
"action": "updateLabel",
"addLabel": "area/alerting"
diff --git a/.github/renovate.json5 b/.github/renovate.json5
index 6cc2ac80423..43a537f2fa1 100644
--- a/.github/renovate.json5
+++ b/.github/renovate.json5
@@ -13,7 +13,6 @@
"slate-react", // we don't want to continue using this on the long run, use Monaco editor instead of Slate
"@types/slate-react", // we don't want to continue using this on the long run, use Monaco editor instead of Slate
"@types/slate", // we don't want to continue using this on the long run, use Monaco editor instead of Slate
- "storybook-dark-mode", // 4.0.2 causes storybook 8.4 to break with react hooks errors
// Temporarily pause updating lerna and nx until we resolve build issues
"lerna",
"nx"
@@ -33,6 +32,7 @@
extends: ["schedule:monthly"],
groupName: "Storybook updates",
matchPackageNames: ["/^@?storybook/"],
+ rangeStrategy: "bump",
},
{
groupName: "React Aria",
diff --git a/.github/workflows/actions/changelog/index.js b/.github/workflows/actions/changelog/index.js
index 48da9dcf33a..b658caf349c 100644
--- a/.github/workflows/actions/changelog/index.js
+++ b/.github/workflows/actions/changelog/index.js
@@ -69,8 +69,17 @@ const graphql = async (ghtoken, query, variables) => {
},
body: JSON.stringify({ query, variables }),
});
- const { data } = await results.json();
- return data;
+
+ const res = await results.json();
+
+ LOG(
+ JSON.stringify({
+ status: results.status,
+ text: results.statusText,
+ })
+ );
+
+ return res.data;
};
// Using Github GraphQL API find the timestamp for the given tag/commit hash.
@@ -99,20 +108,20 @@ const getCommitishDate = async (name, owner, target) => {
// Using Github GraphQL API get a list of PRs between the two "commitish" items.
// This resoves the "since" item's timestamp first and iterates over all PRs
// till "target" using naïve pagination.
-const getHistory = async (name, owner, target, sinceDate) => {
- LOG(`Fetching ${owner}/${name} PRs since ${sinceDate} till ${target}`);
+const getHistory = async (name, owner, from, to) => {
+ LOG(`Fetching ${owner}/${name} PRs between ${from} and ${to}`);
const query = `
query findCommitsWithAssociatedPullRequests(
$name: String!
$owner: String!
- $target: String!
- $sinceDate: GitTimestamp
+ $from: String!
+ $to: String!
$cursor: String
) {
repository(name: $name, owner: $owner) {
- object(expression: $target) {
- ... on Commit {
- history(first: 50, since: $sinceDate, after: $cursor) {
+ ref(qualifiedName: $from) {
+ compare(headRef: $to) {
+ commits(first: 25, after: $cursor) {
totalCount
pageInfo {
hasNextPage
@@ -155,13 +164,13 @@ const getHistory = async (name, owner, target, sinceDate) => {
const result = await graphql(ghtoken, query, {
name,
owner,
- target,
- sinceDate,
+ from,
+ to,
cursor,
});
LOG(`GraphQL: ${JSON.stringify(result)}`);
- nodes = [...nodes, ...result.repository.object.history.nodes];
- const { hasNextPage, endCursor } = result.repository.object.history.pageInfo;
+ nodes = [...nodes, ...result.repository.ref.compare.commits.nodes];
+ const { hasNextPage, endCursor } = result.repository.ref.compare.commits.pageInfo;
if (!hasNextPage) {
break;
}
@@ -175,11 +184,11 @@ const getHistory = async (name, owner, target, sinceDate) => {
// feature, deprecation, breaking change and plugin fixes/enhancements).
//
// PR grouping relies on Github labels only, not on the PR contents.
-const getChangeLogItems = async (name, owner, sinceDate, to) => {
+const getChangeLogItems = async (name, owner, from, to) => {
// check if a node contains a certain label
const hasLabel = ({ labels }, label) => labels.nodes.some(({ name }) => name === label);
// get all the PRs between the two "commitish" items
- const history = await getHistory(name, owner, to, sinceDate);
+ const history = await getHistory(name, owner, from, to);
const items = history.flatMap((node) => {
// discard PRs without a "changelog" label
@@ -231,13 +240,10 @@ const previous = process.argv[3] || process.env.INPUT_PREVIOUS || (await getPrev
LOG(`Previous tag/commit: ${previous}`);
-const sinceDate = await getCommitishDate('grafana', 'grafana', previous);
-LOG(`Previous tag/commit timestamp: ${sinceDate}`);
-
// Get all changelog items from Grafana OSS
-const oss = await getChangeLogItems('grafana', 'grafana', sinceDate, target);
+const oss = await getChangeLogItems('grafana', 'grafana', previous, target);
// Get all changelog items from Grafana Enterprise
-const entr = await getChangeLogItems('grafana-enterprise', 'grafana', sinceDate, target);
+const entr = await getChangeLogItems('grafana-enterprise', 'grafana', previous, target);
LOG(`Found OSS PRs: ${oss.length}`);
LOG(`Found Enterprise PRs: ${entr.length}`);
diff --git a/.github/workflows/add-to-whats-new.yml b/.github/workflows/add-to-whats-new.yml
new file mode 100644
index 00000000000..900ab9615bd
--- /dev/null
+++ b/.github/workflows/add-to-whats-new.yml
@@ -0,0 +1,16 @@
+name: Add comment about adding a What's new note
+on:
+ pull_request:
+ types: [labeled]
+
+jobs:
+ add-comment:
+ if: ${{ ! github.event.pull_request.head.repo.fork && contains(github.event.pull_request.labels.*.name, 'add to what''s new') }}
+ runs-on: ubuntu-latest
+ permissions:
+ pull-requests: write
+ steps:
+ - uses: marocchino/sticky-pull-request-comment@52423e01640425a022ef5fd42c6fb5f633a02728 # v2.9.1
+ with:
+ message: |
+ Since you've added the `Add to what's new` label, consider drafting a [What's new note](https://admin.grafana.com/content-admin/#/collections/whats-new/new) for this feature.
diff --git a/.github/workflows/alerting-update-module.yml b/.github/workflows/alerting-update-module.yml
new file mode 100644
index 00000000000..213b243f9b1
--- /dev/null
+++ b/.github/workflows/alerting-update-module.yml
@@ -0,0 +1,136 @@
+name: Update Alerting Module
+
+on:
+ workflow_dispatch:
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
+
+jobs:
+ update-grafana:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ pull-requests: write
+ id-token: write
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # 4.2.2
+
+ - name: Check if update branch exists
+ run: |
+ if git ls-remote --heads origin update-alerting-module | grep -q 'update-alerting-module'; then
+ echo "Branch 'update-alerting-module' already exists. There might be an open PR with Grafana updates."
+ echo "Please review and merge/close the existing PR before running this workflow again."
+ exit 1
+ fi
+
+ - name: Setup Go
+ uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # 5.3.0
+ with:
+ "go-version-file": "go.mod"
+
+ - name: Extract current commit hash of alerting module
+ id: current-commit
+ run: |
+ FROM_COMMIT=$(go list -m -json github.com/grafana/alerting | jq -r '.Version' | grep -oP '(?<=-)[a-f0-9]+$')
+ echo "from_commit=$FROM_COMMIT" >> $GITHUB_OUTPUT
+
+ - name: Get current branch name
+ id: current-branch-name
+ run: echo "name=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> "$GITHUB_OUTPUT"
+
+ - name: Get latest commit
+ id: latest-commit
+ env:
+ GH_TOKEN: ${{ github.token }}
+ run: |
+ BRANCH="${{ steps.current-branch-name.outputs.name }}"
+ TO_COMMIT=$(gh api repos/grafana/alerting/commits/$BRANCH --jq '.sha')
+ if [ -z "$TO_COMMIT" ]; then
+ echo "Branch $BRANCH not found in alerting repo, falling back to main branch"
+ exit 1
+ fi
+ echo "to_commit=$TO_COMMIT" >> $GITHUB_OUTPUT
+
+ - name: Compare commit hashes
+ run: |
+ FROM_COMMIT="${{ steps.current-commit.outputs.from_commit }}"
+ TO_COMMIT="${{ steps.latest-commit.outputs.to_commit }}"
+
+ # Compare just the length of the shorter hash
+ SHORT_TO_COMMIT="${TO_COMMIT:0:${#FROM_COMMIT}}"
+
+ if [ "$FROM_COMMIT" = "$SHORT_TO_COMMIT" ]; then
+ echo "Current version ($FROM_COMMIT) is already at latest ($SHORT_TO_COMMIT). No update needed."
+ exit 0
+ fi
+ echo "Updates available: $FROM_COMMIT -> $TO_COMMIT"
+
+ - name: Check for commit history
+ id: check-commits
+ env:
+ GH_TOKEN: ${{ github.token }}
+ run: |
+ # get all commits that contains 'Alerting:' in the message
+ ALERTING_COMMITS=$(gh api repos/grafana/alerting/compare/${{ steps.current-commit.outputs.from_commit }}...${{ steps.latest-commit.outputs.to_commit }} \
+ --jq '.commits[].commit.message | split("\n")[0]') || true
+
+ # Use printf instead of echo -e for better multiline handling
+ printf "%s\n" "$ALERTING_COMMITS"
+
+ # make the list for markdown and replace PR numbers with links
+ ALERTING_COMMITS_FORMATTED=$(echo "$ALERTING_COMMITS" | while read -r line; do echo "- $line" | sed -E 's/\(#([0-9]+)\)/[#\1](https:\/\/github.com\/grafana\/grafana\/pull\/\1)/g'; done)
+
+ echo "alerting_commits<> $GITHUB_OUTPUT
+ echo "$ALERTING_COMMITS_FORMATTED" >> $GITHUB_OUTPUT
+ echo "EOF" >> $GITHUB_OUTPUT
+
+ - name: Update alerting module
+ env:
+ GOSUMDB: off
+ run: |
+ go get github.com/grafana/alerting@${{ steps.latest-commit.outputs.to_commit }}
+ make update-workspace
+
+ - id: get-secrets
+ uses: grafana/shared-workflows/actions/get-vault-secrets@28361cdb22223e5f1e34358c86c20908e7248760 # 1.1.0
+ with:
+ repo_secrets: |
+ GITHUB_APP_ID=alerting-team:app-id
+ GITHUB_APP_PRIVATE_KEY=alerting-team:private-key
+
+ - name: "Generate token"
+ id: generate_token
+ uses: actions/create-github-app-token@0d564482f06ca65fa9e77e2510873638c82206f2 # 1.11.5
+ with:
+ app-id: ${{ env.GITHUB_APP_ID }}
+ private-key: ${{ env.GITHUB_APP_PRIVATE_KEY }}
+
+ - name: Create Pull Request
+ uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # 7.0.6
+ id: create-pr
+ with:
+ token: '${{ steps.generate_token.outputs.token }}'
+ title: 'Alerting: Update alerting module to ${{ steps.latest-commit.outputs.to_commit }}'
+ branch: alerting/update-alerting-module
+ delete-branch: true
+ body: |
+ Updates Grafana Alerting module to latest version.
+
+ Compare changes: https://github.com/grafana/alerting/compare/${{ steps.current-commit.outputs.from_commit }}...${{ steps.latest-commit.outputs.to_commit }}
+
+ Commits
+
+ ${{ steps.check-commits.outputs.alerting_commits }}
+
+
+
+ Created by: [GitHub Action Job](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})
+ - name: Add PR URL to Summary
+ if: steps.create-pr.outputs.pull-request-url != ''
+ run: |
+ echo "## Pull Request Created" >> $GITHUB_STEP_SUMMARY
+ echo "🔗 [View Pull Request](${{ steps.create-pr.outputs.pull-request-url }})" >> $GITHUB_STEP_SUMMARY
diff --git a/.github/workflows/analytics-events-report.yml b/.github/workflows/analytics-events-report.yml
new file mode 100644
index 00000000000..9d4d6907256
--- /dev/null
+++ b/.github/workflows/analytics-events-report.yml
@@ -0,0 +1,23 @@
+name: Analytics Events Report
+
+on:
+ workflow_dispatch:
+
+jobs:
+ generate-report:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version-file: '.nvmrc'
+ cache: 'yarn'
+
+ - name: Install dependencies
+ run: yarn install --frozen-lockfile
+
+ - name: Generate analytics report
+ run: yarn analytics-report
diff --git a/.github/workflows/auto-triager/labels.txt b/.github/workflows/auto-triager/labels.txt
index 6b7b9e37f8b..1a33cf676dc 100644
--- a/.github/workflows/auto-triager/labels.txt
+++ b/.github/workflows/auto-triager/labels.txt
@@ -32,7 +32,6 @@ area/dashboard/tv
area/dashboard/variable
area/dashboards/panel
area/data/export
-area/editor
area/explore
area/exploremetrics
area/expressions
diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml
index 18407b67f76..5f21ab276ee 100644
--- a/.github/workflows/backport.yml
+++ b/.github/workflows/backport.yml
@@ -10,24 +10,18 @@ jobs:
if: github.repository == 'grafana/grafana'
runs-on: ubuntu-latest
steps:
- - name: Checkout Actions
+ - name: Checkout
uses: actions/checkout@v4
- with:
- repository: "grafana/grafana-github-actions"
- path: ./actions
- ref: main
- - name: Install Actions
- run: npm install --production --prefix ./actions
- name: "Generate token"
id: generate_token
uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
with:
app_id: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
private_key: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
+ - run: git config --global user.email '132647405+grafana-delivery-bot[bot]@users.noreply.github.com'
+ - run: git config --global user.name 'grafana-delivery-bot[bot]'
+ - run: git remote set-url origin "https://grafana-delivery-bot:${{ steps.generate_token.outputs.token }}@github.com/grafana/grafana.git"
- name: Run backport
- uses: ./actions/backport
+ uses: grafana/grafana-github-actions-go/backport@main
with:
- metricsWriteAPIKey: ${{secrets.GRAFANA_MISC_STATS_API_KEY}}
token: ${{ steps.generate_token.outputs.token }}
- labelsToAdd: "backport"
- title: "[{{base}}] {{originalTitle}}"
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 14981389deb..c1f90ceb831 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -52,7 +52,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@v2
+ uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@@ -67,4 +67,4 @@ jobs:
make build-go
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v2
+ uses: github/codeql-action/analyze@v3
diff --git a/.github/workflows/create-next-release-branch.yml b/.github/workflows/create-next-release-branch.yml
new file mode 100644
index 00000000000..8fc01cd442d
--- /dev/null
+++ b/.github/workflows/create-next-release-branch.yml
@@ -0,0 +1,53 @@
+name: Create next release branch
+on:
+ workflow_call:
+ inputs:
+ ownerRepo:
+ type: string
+ description: Owner/repo of the repository where the branch is created (e.g. 'grafana/grafana')
+ required: true
+ source:
+ description: The release branch to increment (eg providing `release-11.2.3` will result in `release-11.2.4` being created)
+ type: string
+ required: true
+ secrets:
+ GRAFANA_DELIVERY_BOT_APP_ID:
+ required: true
+ GRAFANA_DELIVERY_BOT_APP_PEM:
+ required: true
+ outputs:
+ branch:
+ description: The new branch that was created
+ value: ${{ jobs.main.outputs.branch }}
+ workflow_dispatch:
+ inputs:
+ ownerRepo:
+ description: Owner/repo of the repository where the branch is created (e.g. 'grafana/grafana')
+ source:
+ description: The release branch to increment (eg providing `release-11.2.3` will result in `release-11.2.4` being created)
+ type: string
+ required: true
+ secrets:
+ GRAFANA_DELIVERY_BOT_APP_ID:
+ required: true
+ GRAFANA_DELIVERY_BOT_APP_PEM:
+ required: true
+jobs:
+ main:
+ runs-on: ubuntu-latest
+ outputs:
+ branch: ${{ steps.branch.outputs.branch }}
+ steps:
+ - name: "Generate token"
+ id: generate_token
+ uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
+ with:
+ app_id: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
+ private_key: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
+ - name: Create release branch
+ id: branch
+ uses: grafana/grafana-github-actions-go/bump-release@main
+ with:
+ ownerRepo: ${{ inputs.ownerRepo }}
+ source: ${{ inputs.source }}
+ token: ${{ steps.generate_token.outputs.token }}
diff --git a/.github/workflows/create-security-patch-from-security-mirror.yml b/.github/workflows/create-security-patch-from-security-mirror.yml
index e187149b8b4..f85239241ad 100644
--- a/.github/workflows/create-security-patch-from-security-mirror.yml
+++ b/.github/workflows/create-security-patch-from-security-mirror.yml
@@ -11,6 +11,7 @@ on:
branches:
- "main"
- "v*.*.*"
+ - "release-*.*.*"
# This is run before the pull request has been merged, so we'll run against the src branch
jobs:
diff --git a/.github/workflows/deploy-pr-preview.yml b/.github/workflows/deploy-pr-preview.yml
index dcb8fcd1c2a..bfad92ebf73 100644
--- a/.github/workflows/deploy-pr-preview.yml
+++ b/.github/workflows/deploy-pr-preview.yml
@@ -11,14 +11,21 @@ on:
jobs:
deploy-pr-preview:
- if: ${{ ! github.event.pull_request.head.repo.fork }}
+ if: "!github.event.pull_request.head.repo.fork"
uses: grafana/writers-toolkit/.github/workflows/deploy-preview.yml@main
with:
- sha: ${{ github.event.pull_request.head.sha }}
branch: ${{ github.head_ref }}
event_number: ${{ github.event.number }}
- title: ${{ github.event.pull_request.title }}
repo: grafana
- website_directory: content/docs/grafana/latest
- relative_prefix: /docs/grafana/latest/
- index_file: true
+ sha: ${{ github.event.pull_request.head.sha }}
+ sources: |
+ [
+ {
+ "index_file": "content/docs/grafana/_index.md",
+ "relative_prefix": "/docs/grafana/latest/",
+ "repo": "grafana",
+ "source_directory": "docs/sources",
+ "website_directory": "content/docs/grafana/latest"
+ }
+ ]
+ title: ${{ github.event.pull_request.title }}
diff --git a/.github/workflows/documentation-ci.yml b/.github/workflows/documentation-ci.yml
index 0f041220ec9..4c688968a09 100644
--- a/.github/workflows/documentation-ci.yml
+++ b/.github/workflows/documentation-ci.yml
@@ -10,10 +10,10 @@ jobs:
container:
image: grafana/vale:latest
steps:
- - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
+ - uses: actions/checkout@v4
with:
persist-credentials: false
- - uses: grafana/writers-toolkit/vale-action@13205961f20ad13843505a9b84fdf032f911a3f4 # vale-action/v1.1.0
+ - uses: grafana/writers-toolkit/vale-action@vale-action/v1
with:
filter: '.Name in ["Grafana.WordList", "Grafana.Spelling", "Grafana.ProductPossessives"]'
token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/feature-toggles-ci.yml b/.github/workflows/feature-toggles-ci.yml
new file mode 100644
index 00000000000..a6c9f5c52dc
--- /dev/null
+++ b/.github/workflows/feature-toggles-ci.yml
@@ -0,0 +1,25 @@
+name: Feature toggles CI
+
+on:
+ pull_request:
+ paths:
+ - 'pkg/services/featuremgmt/toggles_gen_test.go'
+ - 'pkg/services/featuremgmt/registry.go'
+ - 'docs/sources/setup-grafana/configure-grafana/feature-toggles/index.md'
+
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ persist-credentials: false
+
+ - name: Set up Go
+ uses: actions/setup-go@v5
+ with:
+ go-version-file: 'go.mod'
+ cache: true
+
+ - name: Run feature toggle tests
+ run: go test -v -run TestFeatureToggleFiles ./pkg/services/featuremgmt/
diff --git a/.github/workflows/frontend-lint.yml b/.github/workflows/frontend-lint.yml
new file mode 100644
index 00000000000..a9b65b247fb
--- /dev/null
+++ b/.github/workflows/frontend-lint.yml
@@ -0,0 +1,55 @@
+name: Lint Frontend
+on:
+ pull_request:
+ push:
+ branches:
+ - main
+ - release-*.*.*
+
+jobs:
+ verify-i18n:
+ name: Verify i18n
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-node@v4
+ with:
+ node-version-file: '.nvmrc'
+ cache: 'yarn'
+ cache-dependency-path: 'yarn.lock'
+ - run: yarn install --immutable --check-cache
+ - run: |
+ extract_error_message='::error::Extraction failed. Make sure that you have no dynamic translation phrases, such as "t(`preferences.theme.{themeID}`, themeName)" and that no translation key is used twice. Search the output for '[warning]' to find the offending file.'
+ make i18n-extract || (echo "${extract_error_message}" && false)
+ - run: |
+ uncommited_error_message="::error::Translation extraction has not been committed. Please run 'make i18n-extract', commit the changes and push again."
+ file_diff=$(git diff --dirstat public/locales)
+ if [ -n "$file_diff" ]; then
+ echo $file_diff
+ echo "${uncommited_error_message}"
+ exit 1
+ fi
+ prettier:
+ name: Prettier
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-node@v4
+ with:
+ node-version-file: '.nvmrc'
+ cache: 'yarn'
+ cache-dependency-path: 'yarn.lock'
+ - run: yarn install --immutable --check-cache
+ - run: yarn run prettier:check
+ typecheck:
+ name: Typecheck
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-node@v4
+ with:
+ node-version-file: '.nvmrc'
+ cache: 'yarn'
+ cache-dependency-path: 'yarn.lock'
+ - run: yarn install --immutable --check-cache
+ - run: yarn run typecheck
diff --git a/.github/workflows/frontend-unit-tests.yml b/.github/workflows/frontend-unit-tests.yml
new file mode 100644
index 00000000000..495bb647233
--- /dev/null
+++ b/.github/workflows/frontend-unit-tests.yml
@@ -0,0 +1,29 @@
+name: Frontend tests
+on:
+ pull_request:
+ push:
+ branches:
+ - main
+ - release-*.*.*
+
+jobs:
+ test-frontend:
+ runs-on: ubuntu-latest-8-cores
+ name: "Unit tests (${{ matrix.chunk }} / 8)"
+ strategy:
+ fail-fast: true
+ matrix:
+ chunk: [1, 2, 3, 4, 5, 6, 7, 8]
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-node@v4
+ with:
+ node-version-file: '.nvmrc'
+ cache: 'yarn'
+ cache-dependency-path: 'yarn.lock'
+ - run: yarn install --immutable --check-cache
+ - run: yarn run test:ci
+ env:
+ TEST_MAX_WORKERS: 2
+ TEST_SHARD: ${{ matrix.chunk }}
+ TEST_SHARD_TOTAL: 8
diff --git a/.github/workflows/i18n-crowdin-download.yml b/.github/workflows/i18n-crowdin-download.yml
index cba14abe43b..e0c3c50b9bb 100644
--- a/.github/workflows/i18n-crowdin-download.yml
+++ b/.github/workflows/i18n-crowdin-download.yml
@@ -3,7 +3,7 @@ name: Crowdin Download Action
on:
workflow_dispatch:
schedule:
- - cron: "0 * * * *"
+ - cron: "0 0 * * *"
jobs:
download-sources-from-crowdin:
@@ -12,6 +12,7 @@ jobs:
permissions:
contents: write # needed to commit changes into the PR
pull-requests: write # needed to update PR description, labels, etc
+ id-token: write # needed to get vault secrets
steps:
- name: Generate token
@@ -41,17 +42,11 @@ jobs:
pull_request_body: |
:robot: Automatic download of translations from Crowdin.
- Steps for merging:
- 1. A quick sanity check of the changes and approve. Things to look out for:
- - No changes in the English file. The source of truth is in the main branch, NOT in Crowdin.
- - Translations maybe be removed if the English phrase was removed, but there should not be many of these
- - Anything else that looks 'funky'. Ask if you're not sure.
- 2. Approve & (Auto-)merge. :tada:
+ This runs once per day and will merge automatically if all the required checks pass.
- If there's a conflict, close the pull request and **delete the branch**. A GH action will recreate the pull request.
- Remember, the longer this pull request is open, the more likely it is that it'll get conflicts.
+ If there's a conflict, close the pull request and **delete the branch**.
+ You can then either wait for the schedule to trigger a new PR, or rerun the action manually.
pull_request_labels: 'area/frontend, area/internationalization, no-changelog, no-backport'
- pull_request_reviewers: 'grafana-frontend-platform'
pull_request_base_branch_name: 'main'
base_url: 'https://grafana.api.crowdin.com'
config: 'crowdin.yml'
@@ -119,3 +114,45 @@ jobs:
with:
pr: ${{ steps.crowdin-download.outputs.pull_request_number }}
token: ${{ steps.generate_token.outputs.token }}
+
+ - name: Get vault secrets
+ id: vault-secrets
+ uses: grafana/shared-workflows/actions/get-vault-secrets@main
+ with:
+ # Secrets placed in ci/repo/grafana/grafana/grafana-pr-approver
+ repo_secrets: |
+ GRAFANA_PR_APPROVER_APP_ID=grafana-pr-approver:app-id
+ GRAFANA_PR_APPROVER_APP_PEM=grafana-pr-approver:private-key
+
+ - name: Generate approver token
+ if: steps.crowdin-download.outputs.pull_request_url
+ id: generate_approver_token
+ uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
+ with:
+ app_id: ${{ env.GRAFANA_PR_APPROVER_APP_ID }}
+ private_key: ${{ env.GRAFANA_PR_APPROVER_APP_PEM }}
+
+ - name: Approve and automerge PR
+ if: steps.crowdin-download.outputs.pull_request_url
+ shell: bash
+ # Only approve if:
+ # - the PR does not modify files other than json files under the public/locales/ directory
+ # - the PR does not modify the en-US locale
+ run: |
+ filesChanged=$(gh pr diff --name-only ${{ steps.crowdin-download.outputs.pull_request_url }})
+
+ if [[ $(echo $filesChanged | grep -v 'public/locales/[a-zA-Z\-]*/grafana.json' | wc -l) -ne 0 ]]; then
+ echo "Non-i18n changes detected, not approving"
+ exit 1
+ fi
+
+ if [[ $(echo $filesChanged | grep "public/locales/en-US" | wc -l) -ne 0 ]]; then
+ echo "public/locales/en-US changes detected, not approving"
+ exit 1
+ fi
+
+ echo "Approving and enabling automerge"
+ gh pr review ${{ steps.crowdin-download.outputs.pull_request_url }} --approve
+ gh pr merge --auto --squash ${{ steps.crowdin-download.outputs.pull_request_url }}
+ env:
+ GITHUB_TOKEN: ${{ steps.generate_approver_token.outputs.token }}
diff --git a/.github/workflows/migrate-prs.yml b/.github/workflows/migrate-prs.yml
new file mode 100644
index 00000000000..31bb8f9f9da
--- /dev/null
+++ b/.github/workflows/migrate-prs.yml
@@ -0,0 +1,60 @@
+name: Migrate open PRs
+# Migrate open PRs from a superseded release branch to the current release branch and notify authors
+on:
+ workflow_call:
+ inputs:
+ from:
+ description: 'The base branch to check for open PRs'
+ required: true
+ type: string
+ to:
+ description: 'The base branch to migrate open PRs to'
+ required: true
+ type: string
+ ownerRepo:
+ description: Owner/repo of the repository where the branch is created (e.g. 'grafana/grafana')
+ required: true
+ type: string
+ secrets:
+ GRAFANA_DELIVERY_BOT_APP_ID:
+ required: true
+ GRAFANA_DELIVERY_BOT_APP_PEM:
+ required: true
+ workflow_dispatch:
+ inputs:
+ from:
+ description: 'The base branch to check for open PRs'
+ required: true
+ type: string
+ to:
+ description: 'The base branch to migrate open PRs to'
+ required: true
+ type: string
+ ownerRepo:
+ description: Owner/repo of the repository where the branch is created (e.g. 'grafana/grafana')
+ required: true
+ type: string
+ secrets:
+ GRAFANA_DELIVERY_BOT_APP_ID:
+ required: true
+ GRAFANA_DELIVERY_BOT_APP_PEM:
+ required: true
+
+jobs:
+ main:
+ runs-on: ubuntu-latest
+ steps:
+ - name: "Generate token"
+ id: generate_token
+ uses: tibdex/github-app-token@b62528385c34dbc9f38e5f4225ac829252d1ea92
+ with:
+ app_id: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
+ private_key: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
+ - name: Migrate PRs
+ uses: grafana/grafana-github-actions-go/migrate-open-prs@main
+ with:
+ token: ${{ steps.generate_token.outputs.token }}
+ ownerRepo: ${{ inputs.ownerRepo }}
+ from: ${{ inputs.from }}
+ to: ${{ inputs.to }}
+ binary_release_tag: 'dev'
diff --git a/.github/workflows/pr-backend-code-checks.yml b/.github/workflows/pr-backend-code-checks.yml
new file mode 100644
index 00000000000..37073dc28c4
--- /dev/null
+++ b/.github/workflows/pr-backend-code-checks.yml
@@ -0,0 +1,37 @@
+name: Backend Code Checks
+description: Validate go.mod and OpenAPI specifications
+
+on:
+ pull_request:
+ paths-ignore:
+ - '*.md'
+ - 'docs/**'
+ - 'latest.json'
+
+permissions:
+ contents: read
+
+jobs:
+ validate-configs:
+ name: Validate Backend Configs
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Setup Go
+ uses: actions/setup-go@v5
+ with:
+ go-version-file: go.mod
+ cache: true
+
+ - name: Verify code generation
+ run: |
+ CODEGEN_VERIFY=1 make gen-cue
+ CODEGEN_VERIFY=1 make gen-jsonnet
+
+ - name: Validate go.mod
+ run: go run scripts/modowners/modowners.go check go.mod
+
+ - name: Generate and Validate OpenAPI Specs
+ run: |
+ make swagger-gen
diff --git a/.github/workflows/pr-backend-unit-tests.yml b/.github/workflows/pr-backend-unit-tests.yml
new file mode 100644
index 00000000000..99ec9b0ea49
--- /dev/null
+++ b/.github/workflows/pr-backend-unit-tests.yml
@@ -0,0 +1,78 @@
+name: Backend Unit Tests
+
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - main
+ paths-ignore:
+ - 'docs/**'
+ - '**/*.md'
+ pull_request:
+ paths-ignore:
+ - 'docs/**'
+ - '**/*.md'
+
+permissions:
+ contents: read
+ id-token: write
+
+env:
+ EDITION: 'oss'
+ WIRE_TAGS: 'oss'
+
+jobs:
+ backend-testing-coverage:
+ name: Backend Testing & Coverage
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Setup Go
+ uses: actions/setup-go@v5
+ with:
+ go-version-file: go.mod
+ cache: true
+
+ - name: Install dependencies
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y build-essential shared-mime-info
+ go install github.com/mfridman/tparse@c1754a1f484ac5cd422697b0fec635177ddc8507 # v0.17.0
+
+ - name: Generate Go code
+ run: make gen-go
+
+ - name: Run unit tests
+ run: COVER_OPTS="-coverprofile=be-unit.cov -coverpkg=github.com/grafana/grafana/..." GO_TEST_OUTPUT="/tmp/unit.log" make test-go-unit
+
+ - name: Process and upload coverage
+ uses: ./.github/actions/test-coverage-processor
+ with:
+ test-type: 'be-unit'
+ # Needs to be named 'unit.cov' based on the Makefile command `make test-go-unit`
+ coverage-file: 'unit.cov'
+ codecov-token: ${{ secrets.CODECOV_TOKEN }}
+ codecov-flag: 'be-unit'
+ codecov-name: 'be-unit'
+
+ - name: Install Grafana Bench
+ # We can't allow forks here, as we need secret access.
+ if: ${{ github.event_name != 'pull_request' }}
+ uses: ./.github/actions/setup-grafana-bench
+
+ - name: Process output for Bench
+ if: ${{ github.event_name != 'pull_request' }}
+ run: |
+ grafana-bench report \
+ --trigger pr-backend-unit-tests-oss \
+ --report-input go \
+ --report-output log \
+ --grafana-version "$(git rev-parse HEAD)" \
+ --suite-name grafana-oss-unit-tests \
+ /tmp/unit.log
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}
+ cancel-in-progress: true
diff --git a/.github/workflows/publish-technical-documentation-release.yml b/.github/workflows/publish-technical-documentation-release.yml
index b36eb48885a..57d779660c5 100644
--- a/.github/workflows/publish-technical-documentation-release.yml
+++ b/.github/workflows/publish-technical-documentation-release.yml
@@ -3,7 +3,7 @@ name: publish-technical-documentation-release
on:
push:
branches:
- - v[0-9]+.[0-9]+.x
+ - release-[0-9]+.[0-9]+.[0-9]+
tags:
- v[0-9]+.[0-9]+.[0-9]+
paths:
@@ -23,7 +23,7 @@ jobs:
- uses: grafana/writers-toolkit/publish-technical-documentation-release@publish-technical-documentation-release/v2
with:
release_tag_regexp: "^v(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$"
- release_branch_regexp: "^v(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.x$"
- release_branch_with_patch_regexp: "^v(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$"
+ release_branch_regexp: "^release-(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$"
+ release_branch_with_patch_regexp: "^release-(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)$"
website_directory: content/docs/grafana
version_suffix: ""
diff --git a/.github/workflows/release-comms.yml b/.github/workflows/release-comms.yml
index 02d53057184..720948e659b 100644
--- a/.github/workflows/release-comms.yml
+++ b/.github/workflows/release-comms.yml
@@ -19,7 +19,7 @@ on:
- closed
branches:
- 'main'
- - 'v*.*.*'
+ - 'release-*.*.*'
jobs:
setup:
@@ -27,6 +27,7 @@ jobs:
name: Setup and establish latest
outputs:
version: ${{ steps.output.outputs.version }}
+ release_branch: ${{ steps.output.outputs.release_branch }}
dry_run: ${{ steps.output.outputs.dry_run }}
latest: ${{ steps.output.outputs.latest }}
runs-on: ubuntu-latest
@@ -49,9 +50,54 @@ jobs:
echo "latest: $LATEST"
echo "version: $VERSION"
+ echo "release_branch=$(echo $VERSION | sed -s 's/^v/release-/g')" >> "$GITHUB_OUTPUT"
echo "dry_run=$DRY_RUN" >> "$GITHUB_OUTPUT"
echo "latest=$LATEST" >> "$GITHUB_OUTPUT"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
+ create_next_release_branch_grafana:
+ name: Create next release branch (Grafana)
+ needs: setup
+ uses: ./.github/workflows/create-next-release-branch.yml
+ secrets:
+ GRAFANA_DELIVERY_BOT_APP_ID: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
+ GRAFANA_DELIVERY_BOT_APP_PEM: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
+ with:
+ ownerRepo: 'grafana/grafana'
+ source: ${{ needs.setup.outputs.release_branch }}
+ create_next_release_branch_enterprise:
+ name: Create next release branch (Grafana Enterprise)
+ needs: setup
+ uses: ./.github/workflows/create-next-release-branch.yml
+ secrets:
+ GRAFANA_DELIVERY_BOT_APP_ID: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
+ GRAFANA_DELIVERY_BOT_APP_PEM: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
+ with:
+ ownerRepo: 'grafana/grafana-enterprise'
+ source: ${{ needs.setup.outputs.release_branch }}
+ migrate_prs_grafana:
+ needs:
+ - setup
+ - create_next_release_branch_grafana
+ uses: ./.github/workflows/migrate-prs.yml
+ secrets:
+ GRAFANA_DELIVERY_BOT_APP_ID: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
+ GRAFANA_DELIVERY_BOT_APP_PEM: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
+ with:
+ ownerRepo: 'grafana/grafana'
+ from: ${{ needs.setup.outputs.release_branch }}
+ to: ${{ needs.create_next_release_branch_grafana.outputs.branch }}
+ migrate_prs_enterprise:
+ needs:
+ - setup
+ - create_next_release_branch_enterprise
+ uses: ./.github/workflows/migrate-prs.yml
+ secrets:
+ GRAFANA_DELIVERY_BOT_APP_ID: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
+ GRAFANA_DELIVERY_BOT_APP_PEM: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
+ with:
+ ownerRepo: 'grafana/grafana-enterprise'
+ from: ${{ needs.setup.outputs.release_branch }}
+ to: ${{ needs.create_next_release_branch_enterprise.outputs.branch }}
post_changelog_on_forum:
needs: setup
uses: ./.github/workflows/community-release.yml
diff --git a/.github/workflows/release-pr.yml b/.github/workflows/release-pr.yml
index d6bcd7d5446..1234cdc75ef 100644
--- a/.github/workflows/release-pr.yml
+++ b/.github/workflows/release-pr.yml
@@ -4,7 +4,7 @@
# Please refrain from including any processes that do not result in code changes in this workflow. Instead, they should
# either be triggered in the release promotion process or in the release comms process (that is triggered by merging
# this PR).
-name: Complete a Grafana release
+name: Grafana Release PR
on:
workflow_dispatch:
inputs:
@@ -19,7 +19,7 @@ on:
target:
required: true
type: string
- description: The base branch that these changes are being merged into
+ description: The release branch pattern (eg v9.5.x) that these changes are being merged into
backport:
required: false
type: string
@@ -61,12 +61,20 @@ jobs:
with:
app_id: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_ID }}
private_key: ${{ secrets.GRAFANA_DELIVERY_BOT_APP_PEM }}
+ - name: Get release branch
+ id: branch
+ uses: grafana/grafana-github-actions-go/latest-release-branch@main
+ with:
+ token: ${{ steps.generate_token.outputs.token }}
+ ownerRepo: 'grafana/grafana'
+ pattern: ${{ inputs.target }}
- name: Checkout Grafana
uses: actions/checkout@v4
with:
- ref: ${{ inputs.target }}
+ ref: ${{ steps.branch.outputs.branch }}
fetch-depth: 0
fetch-tags: true
+ token: ${{ steps.generate_token.outputs.token }}
- name: Checkout Grafana (main)
uses: actions/checkout@v4
with:
@@ -74,6 +82,7 @@ jobs:
fetch-depth: '0'
fetch-tags: 'false'
path: .grafana-main
+ token: ${{ steps.generate_token.outputs.token }}
- name: Setup nodejs environment
uses: actions/setup-node@v4
with:
@@ -124,7 +133,6 @@ jobs:
rm -f CHANGELOG.part changelog_items.md
git diff CHANGELOG.md
-
- name: "Prettify CHANGELOG.md"
run: npx prettier --write CHANGELOG.md
- name: Commit CHANGELOG.md changes
@@ -138,6 +146,7 @@ jobs:
- name: Add package.json changes
run: |
git add package.json lerna.json yarn.lock packages public
+ test -e e2e/test-plugins && git add e2e/test-plugins
git commit -m "Update version to ${{ inputs.version }}"
- name: Git push
@@ -151,7 +160,7 @@ jobs:
$( [ "x${{ inputs.latest }}" == "xtrue" ] && printf %s '-l "release/latest"') \
-l "no-changelog" \
--dry-run=${{ inputs.dry_run }} \
- -B "${{ inputs.target }}" \
+ -B "${{ steps.branch.outputs.branch }}" \
--title "Release: ${{ inputs.version }}" \
--body "These code changes must be merged after a release is complete"
env:
@@ -165,7 +174,7 @@ jobs:
-l "product-approved" \
-l "no-changelog" \
--dry-run=${{ inputs.dry_run }} \
- -B "${{ inputs.target }}" \
+ -B "${{ steps.branch.outputs.branch }}" \
--title "Release: ${{ inputs.version }}" \
--body "These code changes must be merged after a release is complete"
env:
diff --git a/.github/workflows/run-schema-v2-e2e.yml b/.github/workflows/run-schema-v2-e2e.yml
new file mode 100644
index 00000000000..8b55aa4c430
--- /dev/null
+++ b/.github/workflows/run-schema-v2-e2e.yml
@@ -0,0 +1,44 @@
+name: Run dashboard schema v2 e2e
+
+on:
+ push:
+ branches:
+ - main
+ pull_request:
+ branches:
+ - '**'
+
+env:
+ ARCH: linux-amd64
+
+jobs:
+ dashboard-schema-v2-e2e:
+ runs-on: ubuntu-latest
+ continue-on-error: true
+ if: github.event.pull_request.draft == false
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ - name: Pin Go version to mod file
+ uses: actions/setup-go@v5
+ with:
+ go-version-file: 'go.mod'
+ - run: go version
+ - uses: actions/setup-node@v4
+ with:
+ node-version: 20
+ cache: 'yarn'
+ - name: Install dependencies
+ run: yarn install --immutable
+ - name: Build grafana
+ run: make build
+ - name: Install Cypress dependencies
+ uses: cypress-io/github-action@v6
+ with:
+ runTests: false
+ - name: Run dashboard scenes e2e
+ run: yarn e2e:schema-v2 || echo "Test failed but marking as success since schema V2 is behind a feature flag and should not block PRs"
+
+ - name: Always succeed # This is a workaround to make the job pass even if the previous step fails
+ if: failure()
+ run: exit 0
\ No newline at end of file
diff --git a/.github/workflows/sbom-report.yml b/.github/workflows/sbom-report.yml
deleted file mode 100644
index efd188da331..00000000000
--- a/.github/workflows/sbom-report.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-name: syft-sbom-ci
-on:
- release:
- types: [ published ]
- workflow_dispatch:
-jobs:
- syft-sbom:
- runs-on: ubuntu-latest
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- - name: Anchore SBOM Action
- uses: grafana/shared-workflows/actions@syft-sbom-v0.0.1
- with:
- artifact-name: ${{ github.event.repository.name }}-spdx.json
diff --git a/.github/workflows/trivy-scan.yml b/.github/workflows/trivy-scan.yml
index b1346236770..25104af8f29 100644
--- a/.github/workflows/trivy-scan.yml
+++ b/.github/workflows/trivy-scan.yml
@@ -27,11 +27,14 @@ jobs:
trivy fs --no-progress --download-db-only --db-repository public.ecr.aws/aquasecurity/trivy-db
- name: Run Trivy vulnerability scanner (table output)
# Use the trivy binary rather than the aquasecurity/trivy-action action
- # to avoid a few bugs
- # scan the filesystem, rather than building a Docker image prior - the
- # downside is we won't catch dependencies that are only installed in the
- # image, but the upside is we'll only catch vulnerabilities that are
- # explicitly in the our dependencies
+ # to avoid a few bugs.
+ #
+ # We scan the file system rather than building the Docker image to only scan
+ # our direct dependencies. The Docker images are still scanned by
+ # Vulnerability Observability:
+ # - OSS: https://ops.grafana-ops.net/a/grafana-vulnerabilityobs-app/projects/sources/1
+ # - Enterprise: https://ops.grafana-ops.net/a/grafana-vulnerabilityobs-app/projects/sources/12
+ # (If these links are outdated, just go to the list and find the images manually.)
run: |
trivy fs \
--scanners vuln \
diff --git a/.gitignore b/.gitignore
index ac5ad6f5f7d..1a8be100668 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,6 +16,7 @@ vendor/
/requests
tsconfig.tsbuildinfo
__debug_bin*
+*.cov
# yarn
.yarn/cache
@@ -40,6 +41,7 @@ __debug_bin*
# This is the new place of the block, but I leave the previous here for a while
/devenv/docker/blocks/auth/saml-enterprise
/devenv/docker/blocks/auth/signer
+/devenv/docker/blocks/spanner_tests
/tmp
tools/phantomjs/phantomjs
@@ -103,14 +105,19 @@ profile.cov
/pkg/cmd/grafana-cli/grafana-cli
/pkg/cmd/grafana-server/grafana-server
/pkg/cmd/grafana-server/debug
-/pkg/extensions/*
-/pkg/build/cmd/artifactspage.go
-/pkg/build/cmd/artifactspage.tmpl.html
-/pkg/build/cmd/exportversion.go
-/pkg/server/wireexts_enterprise.go
+
+# Extensions
/pkg/cmd/grafana-cli/runner/wireexts_enterprise.go
+/pkg/server/wireexts_enterprise.go
+/pkg/build/cmd/enterprise.go
+/pkg/extensions/*
+!/pkg/extensions/.keep
!/pkg/extensions/main.go
+!/pkg/extensions/enterprise_imports.go
/public/app/extensions
+!/public/app/extensions/.keep
+
+
debug.test
/examples/*/dist
/packaging/**/*.rpm
@@ -141,6 +148,7 @@ pkg/services/quota/quotaimpl/storage/storage.json
# Ignoring frontend packages specifics
/packages/grafana-ui/.yarn/.cache
/packages/grafana-ui/.storybook/static
+/packages/grafana-ui/unstable
/packages/**/dist
/packages/**/compiled
/packages/**/.rpt2_cache
@@ -170,13 +178,13 @@ compilation-stats.json
/e2e/benchmarks/**/results
/e2e/build_results.zip
/e2e/extensions
+!/e2e/extensions/.keep
/e2e/extensions-suite
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
/playwright/.auth/
-
# grafana server
/scripts/grafana-server/server.log
diff --git a/.golangci.yml b/.golangci.yml
index 9a49288fb2b..35b9bd1d4ec 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -1,5 +1,5 @@
run:
- timeout: 10m
+ timeout: 15m
concurrency: 10
allow-parallel-runners: true
linters-settings:
@@ -191,10 +191,10 @@ linters-settings:
allow: []
deny:
- pkg: github.com/grafana/grafana/pkg
- desc: apps/investigation is not allowed to import grafana core
+ desc: apps/investigations is not allowed to import grafana core
files:
- - ./apps/investigation/*
- - ./apps/investigation/**/*
+ - ./apps/investigations/*
+ - ./apps/investigations/**/*
gocritic:
enabled-checks:
- ruleguard
diff --git a/.ignore b/.ignore
new file mode 100644
index 00000000000..01e1bb8d6e2
--- /dev/null
+++ b/.ignore
@@ -0,0 +1,22 @@
+# This is a trick to ignore files only by git but not by other tools
+!/public/app/extensions
+!/pkg/extensions/*
+!/pkg/cmd/grafana-cli/runner/wireexts_enterprise.go
+!/pkg/server/wireexts_enterprise.go
+!/pkg/build/cmd/enterprise.go
+!/pkg/extensions/*
+
+# Enterprise emails
+!/emails/templates/enterprise_*
+!/public/emails/enterprise_*
+
+# Enterprise reporting fonts
+!/public/fonts/dejavu
+
+# Enterprise devenv
+!/devenv/docker/blocks/grafana-enterprise
+!/devenv/docker/blocks/saml-enterprise
+# This is the new place of the block, but I leave the previous here for a while
+!/devenv/docker/blocks/auth/saml-enterprise
+!/devenv/docker/blocks/auth/signer
+!/devenv/docker/blocks/spanner_tests
\ No newline at end of file
diff --git a/.prettierignore b/.prettierignore
index 8bf9dc13276..23d9231bc49 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -19,6 +19,9 @@ vendor
# TS generate from cue by cuetsy
**/*.gen.ts
+# TS generated by grafana-app-sdk
+**/*_gen.ts
+
# Auto-generated theme files
theme.light.generated.json
theme.dark.generated.json
diff --git a/.vale.ini b/.vale.ini
index cf4c71392dc..37e764e6d0f 100644
--- a/.vale.ini
+++ b/.vale.ini
@@ -1,5 +1,5 @@
MinAlertLevel = warning
-[*]
+[*.md]
BasedOnStyles = Grafana
TokenIgnores = (+?), \*\*[^\n]+\*\*
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 80bafb80307..67c4f82699b 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -96,6 +96,15 @@
"NODE_ENV": "test"
}
},
+ {
+ "name": "Debug ESLint",
+ "type": "node",
+ "request": "launch",
+ "runtimeExecutable": "yarn",
+ "runtimeArgs": ["run", "eslint", "${file}"],
+ "console": "integratedTerminal",
+ "internalConsoleOptions": "neverOpen"
+ },
{
"name": "Debug Go test",
"type": "go",
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6bb3ea46a8e..5b7107fc70a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,407 @@
+
+
+# 11.5.2 (2025-02-18)
+
+### Features and enhancements
+
+- **Docker:** Use our own glibc 2.40 binaries [#99918](https://github.com/grafana/grafana/pull/99918), [@DanCech](https://github.com/DanCech)
+- **TransformationFilter:** Include transformation outputs in transformation filtering options [#99878](https://github.com/grafana/grafana/pull/99878), [@Sergej-Vlasov](https://github.com/Sergej-Vlasov)
+- **grafana-ui:** Update InlineField error prop type to React.ReactNode [#100373](https://github.com/grafana/grafana/pull/100373), [@Clarity-89](https://github.com/Clarity-89)
+
+### Bug fixes
+
+- **Alerting:** Allow specifying uid for new rules added to groups [#100450](https://github.com/grafana/grafana/pull/100450), [@yuri-tceretian](https://github.com/yuri-tceretian)
+- **Alerting:** Allow specifying uid for new rules added to groups [#100450](https://github.com/grafana/grafana/pull/100450), [@yuri-tceretian](https://github.com/yuri-tceretian)
+- **Alerting:** Call RLock() before reading sendAlertsTo map [#99880](https://github.com/grafana/grafana/pull/99880), [@santihernandezc](https://github.com/santihernandezc)
+- **Auth:** Fix redirect with JWT auth URL login [#100355](https://github.com/grafana/grafana/pull/100355), [@mgyongyosi](https://github.com/mgyongyosi)
+- **AuthN:** Refetch user on "ErrUserAlreadyExists" [#100582](https://github.com/grafana/grafana/pull/100582), [@kalleep](https://github.com/kalleep)
+- **Azure:** Correctly set application insights resource values [#99599](https://github.com/grafana/grafana/pull/99599), [@aangelisc](https://github.com/aangelisc)
+- **CodeEditor:** Fix cursor alignment [#99863](https://github.com/grafana/grafana/pull/99863), [@ashharrison90](https://github.com/ashharrison90)
+- **DashboardList:** Throttle the re-renders [#100046](https://github.com/grafana/grafana/pull/100046), [@bfmatei](https://github.com/bfmatei)
+- **Dashboards:** Bring back scripted dashboards [#100633](https://github.com/grafana/grafana/pull/100633), [@dprokop](https://github.com/dprokop)
+- **Plugin Metrics:** Eliminate data race in plugin metrics middleware [#100078](https://github.com/grafana/grafana/pull/100078), [@clord](https://github.com/clord)
+- **RBAC:** Don't check folder access if `annotationPermissionUpdate` FT is enabled [#100117](https://github.com/grafana/grafana/pull/100117), [@IevaVasiljeva](https://github.com/IevaVasiljeva)
+
+
+
+
+# 11.4.2 (2025-02-18)
+
+### Features and enhancements
+
+- **Docker:** Use our own glibc 2.40 binaries [#99924](https://github.com/grafana/grafana/pull/99924), [@DanCech](https://github.com/DanCech)
+
+### Bug fixes
+
+- **Auth:** Fix redirect with JWT auth URL login [#100494](https://github.com/grafana/grafana/pull/100494), [@mgyongyosi](https://github.com/mgyongyosi)
+- **AuthN:** Refetch user on "ErrUserAlreadyExists" [#100585](https://github.com/grafana/grafana/pull/100585), [@kalleep](https://github.com/kalleep)
+- **Azure:** Correctly set application insights resource values [#99598](https://github.com/grafana/grafana/pull/99598), [@aangelisc](https://github.com/aangelisc)
+- **Dashboards:** Bring back scripted dashboards [#100629](https://github.com/grafana/grafana/pull/100629), [@dprokop](https://github.com/dprokop)
+- **Plugin Metrics:** Eliminate data race in plugin metrics middleware [#100077](https://github.com/grafana/grafana/pull/100077), [@clord](https://github.com/clord)
+- **RBAC:** Don't check folder access if `annotationPermissionUpdate` FT is enabled [#100116](https://github.com/grafana/grafana/pull/100116), [@IevaVasiljeva](https://github.com/IevaVasiljeva)
+
+
+
+
+# 11.3.4 (2025-02-18)
+
+### Features and enhancements
+
+- **Docker:** Use our own glibc 2.40 binaries [#99923](https://github.com/grafana/grafana/pull/99923), [@DanCech](https://github.com/DanCech)
+
+### Bug fixes
+
+- **Auth:** Fix redirect with JWT auth URL login [#100495](https://github.com/grafana/grafana/pull/100495), [@mgyongyosi](https://github.com/mgyongyosi)
+- **Azure:** Correctly set application insights resource values [#99597](https://github.com/grafana/grafana/pull/99597), [@aangelisc](https://github.com/aangelisc)
+- **Dashboards:** Bring back scripted dashboards [#100627](https://github.com/grafana/grafana/pull/100627), [@dprokop](https://github.com/dprokop)
+- **Plugin Metrics:** Eliminate data race in plugin metrics middleware [#100076](https://github.com/grafana/grafana/pull/100076), [@clord](https://github.com/clord)
+
+
+
+
+# 11.2.7 (2025-02-18)
+
+### Features and enhancements
+
+- **Docker:** Use our own glibc 2.40 binaries [#99922](https://github.com/grafana/grafana/pull/99922), [@DanCech](https://github.com/DanCech)
+
+### Bug fixes
+
+- **Azure:** Correctly set application insights resource values [#99596](https://github.com/grafana/grafana/pull/99596), [@aangelisc](https://github.com/aangelisc)
+
+
+
+
+# 11.1.12 (2025-02-18)
+
+### Features and enhancements
+
+- **Docker:** Use our own glibc 2.40 binaries [#99917](https://github.com/grafana/grafana/pull/99917), [@DanCech](https://github.com/DanCech)
+
+### Bug fixes
+
+- **Azure:** Correctly set application insights resource values [#99595](https://github.com/grafana/grafana/pull/99595), [@aangelisc](https://github.com/aangelisc)
+
+
+
+
+# 11.0.11 (2025-02-18)
+
+### Features and enhancements
+
+- **Docker:** Use our own glibc 2.40 binaries [#100730](https://github.com/grafana/grafana/pull/100730), [@DanCech](https://github.com/DanCech)
+
+### Bug fixes
+
+- **Azure:** Correctly set application insights resource values [#99594](https://github.com/grafana/grafana/pull/99594), [@aangelisc](https://github.com/aangelisc)
+
+
+
+
+# 10.4.16 (2025-02-18)
+
+### Features and enhancements
+
+- **Docker:** Use our own glibc 2.40 binaries [#99920](https://github.com/grafana/grafana/pull/99920), [@DanCech](https://github.com/DanCech)
+
+### Bug fixes
+
+- **Dashboard:** Fix for overwriting an edited dashboard in the old architecture [#100288](https://github.com/grafana/grafana/pull/100288), [@bfmatei](https://github.com/bfmatei)
+
+
+
+
+# 11.5.1 (2025-02-03)
+
+### Bug fixes
+
+- **CodeEditor:** Fix cursor alignment [#99090](https://github.com/grafana/grafana/pull/99090), [@ashharrison90](https://github.com/ashharrison90)
+- **TransformationFilter**: Include transformation outputs in transformation filtering options: Include transformation outputs in transformation filtering options [#98323](https://github.com/grafana/grafana/pull/98323), [@Sergej-Vlasov](https://github.com/Sergej-Vlasov)
+
+
+
+
+# 11.5.0 (2025-01-28)
+
+### Features and enhancements
+
+- ** CloudMigration:** Create authapi service [#96581](https://github.com/grafana/grafana/pull/96581), [@leandro-deveikis](https://github.com/leandro-deveikis)
+- **Alerting:** Add new button for exporting new alert rule in HCL format [#96785](https://github.com/grafana/grafana/pull/96785), [@soniaAguilarPeiron](https://github.com/soniaAguilarPeiron)
+- **Alerting:** Add option to show inactive alerts in alert list panel [#96888](https://github.com/grafana/grafana/pull/96888), [@bradleypettit](https://github.com/bradleypettit)
+- **Alerting:** Add state_periodic_save_batch_size config option [#98019](https://github.com/grafana/grafana/pull/98019), [@alexander-akhmetov](https://github.com/alexander-akhmetov)
+- **Alerting:** Change default for max_attempts to 3. [#97461](https://github.com/grafana/grafana/pull/97461), [@stevesg](https://github.com/stevesg)
+- **Alerting:** Consume k8s API for notification policies tree [#96147](https://github.com/grafana/grafana/pull/96147), [@konrad147](https://github.com/konrad147)
+- **Alerting:** Enable flag alertingApiServer by default [#98282](https://github.com/grafana/grafana/pull/98282), [@yuri-tceretian](https://github.com/yuri-tceretian)
+- **Alerting:** Explore button in Insights view [#96496](https://github.com/grafana/grafana/pull/96496), [@ppcano](https://github.com/ppcano)
+- **Alerting:** Improve performance ash page [#97619](https://github.com/grafana/grafana/pull/97619), [@soniaAguilarPeiron](https://github.com/soniaAguilarPeiron)
+- **Alerting:** Make alert rule policies preview use k8s API [#97070](https://github.com/grafana/grafana/pull/97070), [@tomratcliffe](https://github.com/tomratcliffe)
+- **Alerting:** Return default builtin templates in k8s templategroup API and UI [#96330](https://github.com/grafana/grafana/pull/96330), [@JacobsonMT](https://github.com/JacobsonMT)
+- **Alerting:** Simplify notification step [#96430](https://github.com/grafana/grafana/pull/96430), [@soniaAguilarPeiron](https://github.com/soniaAguilarPeiron)
+- **Alerting:** Update state manager to take image only once per rule evaluation [#98289](https://github.com/grafana/grafana/pull/98289), [@yuri-tceretian](https://github.com/yuri-tceretian)
+- **Analytics Views:** Deprecate :dashboardID endpoints in favor of uid/:dashboardUID (Enterprise)
+- **Analytics:** Summaries: Deprecate dashboard_id endpoints in favor of dashboard_uid (Enterprise)
+- **Announcement Banners:** Enable feature for all cloud tiers (Enterprise)
+- **Announcement banner:** Remove feature toggle [#98782](https://github.com/grafana/grafana/pull/98782), [@Clarity-89](https://github.com/Clarity-89)
+- **Announcement banner:** Remove feature toggle (Enterprise)
+- **Announcement banner:** Sort by last updated (Enterprise)
+- **Auth:** Return error when retries have been exhausted for OAuth token refresh [#98034](https://github.com/grafana/grafana/pull/98034), [@mgyongyosi](https://github.com/mgyongyosi)
+- **Azure Monitor:** Add a feature flag to toggle user auth for Azure Monitor only [#96858](https://github.com/grafana/grafana/pull/96858), [@adamyeats](https://github.com/adamyeats)
+- **Azure:** Improve Azure Prometheus exemplars UI/UX [#97198](https://github.com/grafana/grafana/pull/97198), [@aangelisc](https://github.com/aangelisc)
+- **Azure:** Unify credentials in frontend for Prometheus [#96568](https://github.com/grafana/grafana/pull/96568), [@yjsong11](https://github.com/yjsong11)
+- **Chore:** Bump Go to 1.23.4 [#98853](https://github.com/grafana/grafana/pull/98853), [@Proximyst](https://github.com/Proximyst)
+- **Chore:** Bump Go to 1.23.4 (Enterprise)
+- **Chore:** Remove experimental Storage UI [#96887](https://github.com/grafana/grafana/pull/96887), [@ryantxu](https://github.com/ryantxu)
+- **Chore:** Update to node 22 [#97779](https://github.com/grafana/grafana/pull/97779), [@ashharrison90](https://github.com/ashharrison90)
+- **CloudMigrations:** Enable feature toggle by default in 11.5 [#98686](https://github.com/grafana/grafana/pull/98686), [@mmandrus](https://github.com/mmandrus)
+- **CloudMigrations:** Introduce RBAC role for migration assistant [#98588](https://github.com/grafana/grafana/pull/98588), [@macabu](https://github.com/macabu)
+- **CloudWatch:** Add OpenSearch PPL and SQL support in Logs Insights [#97508](https://github.com/grafana/grafana/pull/97508), [@idastambuk](https://github.com/idastambuk)
+- **CloudWatch:** Batch different time ranges separately [#98230](https://github.com/grafana/grafana/pull/98230), [@iwysiu](https://github.com/iwysiu)
+- **Cloudwatch:** Accept empty string for logstimeout and mark errors downstream [#96947](https://github.com/grafana/grafana/pull/96947), [@iwysiu](https://github.com/iwysiu)
+- **Cloudwatch:** Update grafana-aws-sdk for AWS/AmplifyHosting metrics [#97799](https://github.com/grafana/grafana/pull/97799), [@iwysiu](https://github.com/iwysiu)
+- **Dashboard Scene:** Shows usages in variables list [#96000](https://github.com/grafana/grafana/pull/96000), [@harisrozajac](https://github.com/harisrozajac)
+- **Dashboards:** Add option to specify explicit percent change text size for stat panels [#96952](https://github.com/grafana/grafana/pull/96952), [@XZCendence](https://github.com/XZCendence)
+- **Dashboards:** Allow DashboardDS subqueries in MixedDS [#97116](https://github.com/grafana/grafana/pull/97116), [@mdvictor](https://github.com/mdvictor)
+- **Dashboards:** Update docs of the `overwrite` param in Save Dashboard API Call [#97011](https://github.com/grafana/grafana/pull/97011), [@ArturWierzbicki](https://github.com/ArturWierzbicki)
+- **Datasources:** Add toggle to control default behaviour of 'Manage alerts via Alerts UI' toggle [#98441](https://github.com/grafana/grafana/pull/98441), [@macabu](https://github.com/macabu)
+- **Datasources:** Allow clearing trace to logs, metrics and profiles datasource pickers [#96554](https://github.com/grafana/grafana/pull/96554), [@adrapereira](https://github.com/adrapereira)
+- **Docker:** Don't use legacy ENV syntax [#93218](https://github.com/grafana/grafana/pull/93218), [@simPod](https://github.com/simPod)
+- **Elasticsearch:** Health endpoint should handle http errors [#96803](https://github.com/grafana/grafana/pull/96803), [@iwysiu](https://github.com/iwysiu)
+- **Elasticsearch:** Use \_field_caps instead of \_mapping to get fields [#97607](https://github.com/grafana/grafana/pull/97607), [@iwysiu](https://github.com/iwysiu)
+- **Explore Profiles:** Preinstall for onprem Grafana instances [#97775](https://github.com/grafana/grafana/pull/97775), [@ifrost](https://github.com/ifrost)
+- **Explore metrics:** Consolidate filters with the OTel experience [#98371](https://github.com/grafana/grafana/pull/98371), [@bohandley](https://github.com/bohandley)
+- **Explore:** Show links to queryless apps [#96625](https://github.com/grafana/grafana/pull/96625), [@ifrost](https://github.com/ifrost)
+- **Expressions:** Add notification for Strict Mode behavior in Reduce component [#97224](https://github.com/grafana/grafana/pull/97224), [@shubhankarunhale](https://github.com/shubhankarunhale)
+- **Faro:** Improve performance of TRACKING_URLS regex [#98022](https://github.com/grafana/grafana/pull/98022), [@kpelelis](https://github.com/kpelelis)
+- **FeatureToggles:** Make newFiltersUI feature toggle generally available [#97460](https://github.com/grafana/grafana/pull/97460), [@Sergej-Vlasov](https://github.com/Sergej-Vlasov)
+- **Features:** Remove cloudwatchMetricInsightsCrossAccount feature toggle [#98826](https://github.com/grafana/grafana/pull/98826), [@idastambuk](https://github.com/idastambuk)
+- **Frontend Sandbox:** Add switch to toggle plugins frontend sandbox via catalog UI (Enterprise)
+- **Graphite:** Set `maxDataPoints` based on user value in alerting [#97178](https://github.com/grafana/grafana/pull/97178), [@aangelisc](https://github.com/aangelisc)
+- **Licensing:** Tidy up license token database code (Enterprise)
+- **LoginAttempt:** Add setting to control max number of attempts before user login gets locked [#97091](https://github.com/grafana/grafana/pull/97091), [@kalleep](https://github.com/kalleep)
+- **Logs Panel:** Add infinite scrolling support for Dashboards and Apps [#97095](https://github.com/grafana/grafana/pull/97095), [@matyax](https://github.com/matyax)
+- **Logs Panel:** Allow text selection without changing Log Details state [#96995](https://github.com/grafana/grafana/pull/96995), [@matyax](https://github.com/matyax)
+- **Logs Panel:** Limit displayed characters to MAX_CHARACTERS [#96997](https://github.com/grafana/grafana/pull/96997), [@matyax](https://github.com/matyax)
+- **Logs:** Added option to show the log line body when displayed fields are used [#97209](https://github.com/grafana/grafana/pull/97209), [@matyax](https://github.com/matyax)
+- **Logs:** Added support to disable and re-enable the popover menu [#98254](https://github.com/grafana/grafana/pull/98254), [@matyax](https://github.com/matyax)
+- **Logs:** Allow scroll to reach the bottom of the log list before loading more [#96668](https://github.com/grafana/grafana/pull/96668), [@matyax](https://github.com/matyax)
+- **Loki:** Added support for disabled operations in Query Builder [#96751](https://github.com/grafana/grafana/pull/96751), [@matyax](https://github.com/matyax)
+- **Loki:** Added support to show label types in Log Details [#97284](https://github.com/grafana/grafana/pull/97284), [@matyax](https://github.com/matyax)
+- **Loki:** Allow regex in `label` derived field [#96609](https://github.com/grafana/grafana/pull/96609), [@svennergr](https://github.com/svennergr)
+- **Loki:** Hide internal labels [#97323](https://github.com/grafana/grafana/pull/97323), [@svennergr](https://github.com/svennergr)
+- **Loki:** Sync query direction with sort order in Explore and Dashboards [#98722](https://github.com/grafana/grafana/pull/98722), [@matyax](https://github.com/matyax)
+- **OAuth:** Support client_secret_jwt for oauth providers when doing token exchange [#95455](https://github.com/grafana/grafana/pull/95455), [@naizerjohn-ms](https://github.com/naizerjohn-ms)
+- **OAuth:** Use the attached external session data in OAuthToken and OAuthTokenSync [#96655](https://github.com/grafana/grafana/pull/96655), [@mgyongyosi](https://github.com/mgyongyosi)
+- **Org Selection:** Show correct selected org when select is open [#96601](https://github.com/grafana/grafana/pull/96601), [@yincongcyincong](https://github.com/yincongcyincong)
+- **PDF:** Add new zoom options (Enterprise)
+- **Plugin Extensions:** Only load app plugins when necessary [#86624](https://github.com/grafana/grafana/pull/86624), [@leventebalogh](https://github.com/leventebalogh)
+- **Plugins:** Add token to gcom requests [#96261](https://github.com/grafana/grafana/pull/96261), [@oshirohugo](https://github.com/oshirohugo)
+- **Plugins:** Add token to gcom requests (Enterprise)
+- **Plugins:** Disable version install when angular version is not supported [#97189](https://github.com/grafana/grafana/pull/97189), [@oshirohugo](https://github.com/oshirohugo)
+- **Plugins:** Disable version installation for specific plugin types [#98597](https://github.com/grafana/grafana/pull/98597), [@oshirohugo](https://github.com/oshirohugo)
+- **Plugins:** Update to latest go plugin SDK (v0.260.3) w/ arrow v18 [#97561](https://github.com/grafana/grafana/pull/97561), [@ryantxu](https://github.com/ryantxu)
+- **Plugins:** Use grafana-com sso_api_token [#97096](https://github.com/grafana/grafana/pull/97096), [@oshirohugo](https://github.com/oshirohugo)
+- **Plugins:** Use grafana-com sso_api_token (Enterprise)
+- **Prometheus datasource:** Show info annotations in the UI [#97978](https://github.com/grafana/grafana/pull/97978), [@zenador](https://github.com/zenador)
+- **Prometheus:** Improve handling of special chars in label values [#96067](https://github.com/grafana/grafana/pull/96067), [@NWRichmond](https://github.com/NWRichmond)
+- **PublicDashboards:** Remove publicDashboards FF [#96578](https://github.com/grafana/grafana/pull/96578), [@juanicabanas](https://github.com/juanicabanas)
+- **Reporting:** Add allow list email domain configuration (Enterprise)
+- **Reporting:** Include the apiserver by default and deprecated internal ids (Enterprise)
+- **RuntimeDataSource:** Support in core for runtime registered data sources [#93956](https://github.com/grafana/grafana/pull/93956), [@torkelo](https://github.com/torkelo)
+- **SAML:** Add the ability to specify EntityID (Enterprise)
+- **SAML:** Implement correct SLO with NameID and SessionIndex handling (Enterprise)
+- **Security:** Update to Go 1.23.5 - Backport to v11.5.x [#99122](https://github.com/grafana/grafana/pull/99122), [@Proximyst](https://github.com/Proximyst)
+- **Security:** Update to Go 1.23.5 - Backport to v11.5.x (Enterprise)
+- **Snapshots:** Add RBAC roles for creating and deleting [#96126](https://github.com/grafana/grafana/pull/96126), [@evictorero](https://github.com/evictorero)
+- **Storage:** Removes integration tests for MySQL 5.7 since it is EOL [#98013](https://github.com/grafana/grafana/pull/98013), [@inf0rmer](https://github.com/inf0rmer)
+- **Tempo:** Add support for TraceQL Metrics exemplars [#96859](https://github.com/grafana/grafana/pull/96859), [@adrapereira](https://github.com/adrapereira)
+- **Tempo:** Honor datasource TLS settings for gRPC requests [#97484](https://github.com/grafana/grafana/pull/97484), [@mdisibio](https://github.com/mdisibio)
+- **Tempo:** Improve handling of multiple values in the Search tab query generation [#98427](https://github.com/grafana/grafana/pull/98427), [@adrapereira](https://github.com/adrapereira)
+- **ToolbarButton:** Auto width on smaller screen sizes [#96023](https://github.com/grafana/grafana/pull/96023), [@yincongcyincong](https://github.com/yincongcyincong)
+- **Trace View:** Set span filters as panel options [#98328](https://github.com/grafana/grafana/pull/98328), [@adrapereira](https://github.com/adrapereira)
+- **TransformationFilter:** Implement RefID multi picker [#96841](https://github.com/grafana/grafana/pull/96841), [@Sergej-Vlasov](https://github.com/Sergej-Vlasov)
+- **Transformations:** Add Delimiter format option to Extract fields [#97340](https://github.com/grafana/grafana/pull/97340), [@tskarhed](https://github.com/tskarhed)
+- **Transformations:** Add RegExp option to Extract fields transformer [#96593](https://github.com/grafana/grafana/pull/96593), [@leeoniya](https://github.com/leeoniya)
+- **Transformations:** GroupToMatrix add 0 as special value [#97642](https://github.com/grafana/grafana/pull/97642), [@tskarhed](https://github.com/tskarhed)
+- **Zipkin:** Run queries through backend [#97754](https://github.com/grafana/grafana/pull/97754), [@ivanahuckova](https://github.com/ivanahuckova)
+
+### Bug fixes
+
+- **Alerting:** AlertingQueryRunner should skip descendant nodes of invalid queries [#97528](https://github.com/grafana/grafana/pull/97528), [@gillesdemey](https://github.com/gillesdemey)
+- **Alerting:** Allow notification policy filters to match quoted matchers [#98525](https://github.com/grafana/grafana/pull/98525), [@gillesdemey](https://github.com/gillesdemey)
+- **Alerting:** Fix alert rule list view summaries [#98433](https://github.com/grafana/grafana/pull/98433), [@yincongcyincong](https://github.com/yincongcyincong)
+- **Alerting:** Fix alert rules unpausing after moving rule to different folder [#97580](https://github.com/grafana/grafana/pull/97580), [@santihernandezc](https://github.com/santihernandezc)
+- **Alerting:** Fix ash not showing history graph in firefox [#98128](https://github.com/grafana/grafana/pull/98128), [@soniaAguilarPeiron](https://github.com/soniaAguilarPeiron)
+- **Alerting:** Fix bug when saving a rule more than once [#96658](https://github.com/grafana/grafana/pull/96658), [@soniaAguilarPeiron](https://github.com/soniaAguilarPeiron)
+- **Alerting:** Fix data-testid in RuleEditorSection [#97473](https://github.com/grafana/grafana/pull/97473), [@soniaAguilarPeiron](https://github.com/soniaAguilarPeiron)
+- **Alerting:** Fix filtering rule group permissions based on their full path (Enterprise)
+- **Alerting:** Fix go template parsing [#97145](https://github.com/grafana/grafana/pull/97145), [@konrad147](https://github.com/konrad147)
+- **Alerting:** Fix label escaping in rule export [#97985](https://github.com/grafana/grafana/pull/97985), [@moustafab](https://github.com/moustafab)
+- **Alerting:** Fix missing instances and history when Grafana rule is stored in folder with / [#97956](https://github.com/grafana/grafana/pull/97956), [@gillesdemey](https://github.com/gillesdemey)
+- **Alerting:** Fix navigating to URLs with "%25" [#96992](https://github.com/grafana/grafana/pull/96992), [@gillesdemey](https://github.com/gillesdemey)
+- **Alerting:** Fix no-change scenario in provisioning rule update API [#98389](https://github.com/grafana/grafana/pull/98389), [@alexander-akhmetov](https://github.com/alexander-akhmetov)
+- **Alerting:** Fix not being able to remove a reducer when using range query [#97757](https://github.com/grafana/grafana/pull/97757), [@soniaAguilarPeiron](https://github.com/soniaAguilarPeiron)
+- **Alerting:** Fix recording rules rendering simplified condition [#97497](https://github.com/grafana/grafana/pull/97497), [@soniaAguilarPeiron](https://github.com/soniaAguilarPeiron)
+- **Alerting:** Fix removing reducer when inital value is instant [#97054](https://github.com/grafana/grafana/pull/97054), [@soniaAguilarPeiron](https://github.com/soniaAguilarPeiron)
+- **Alerting:** Fix simplified query step [#97046](https://github.com/grafana/grafana/pull/97046), [@soniaAguilarPeiron](https://github.com/soniaAguilarPeiron)
+- **Alerting:** Fix slack image uploading to use new api [#97817](https://github.com/grafana/grafana/pull/97817), [@moustafab](https://github.com/moustafab)
+- **Alerting:** Fix terraform export of notification policy [#98429](https://github.com/grafana/grafana/pull/98429), [@moustafab](https://github.com/moustafab)
+- **Alerting:** Fix updating condition when refId changes [#97753](https://github.com/grafana/grafana/pull/97753), [@soniaAguilarPeiron](https://github.com/soniaAguilarPeiron)
+- **Alerting:** Fix using stacks- prefix instead of stack- for checking the namespace in boot data [#97492](https://github.com/grafana/grafana/pull/97492), [@soniaAguilarPeiron](https://github.com/soniaAguilarPeiron)
+- **Anonymous User:** Adds validator service for anonymous users (Enterprise)
+- **Auth:** Fix SAML user IsExternallySynced not being set correctly [#98487](https://github.com/grafana/grafana/pull/98487), [@volcanonoodle](https://github.com/volcanonoodle)
+- **Azure Monitor:** Add safety around usage of frame.Meta.Custom struct [#97766](https://github.com/grafana/grafana/pull/97766), [@adamyeats](https://github.com/adamyeats)
+- **Azure/GCM:** Improve error display [#96921](https://github.com/grafana/grafana/pull/96921), [@aangelisc](https://github.com/aangelisc)
+- **CloudWatch:** Fix conditions for fetching wildcards [#98648](https://github.com/grafana/grafana/pull/98648), [@iwysiu](https://github.com/iwysiu)
+- **CloudWatch:** Fix interpolation of log groups when fetching fields [#98054](https://github.com/grafana/grafana/pull/98054), [@idastambuk](https://github.com/idastambuk)
+- **Dashboard:** Fixes issue with compatability of old DashboardModel.annotations [#97328](https://github.com/grafana/grafana/pull/97328), [@torkelo](https://github.com/torkelo)
+- **Dashboards:** Fix issue where filtered panels would not react to variable changes [#98718](https://github.com/grafana/grafana/pull/98718), [@oscarkilhed](https://github.com/oscarkilhed)
+- **Dashboards:** Fixes week relative time ranges when weekStart was changed [#98167](https://github.com/grafana/grafana/pull/98167), [@torkelo](https://github.com/torkelo)
+- **Dashboards:** Panel react for `timeFrom` and `timeShift` changes using variables [#98510](https://github.com/grafana/grafana/pull/98510), [@Sergej-Vlasov](https://github.com/Sergej-Vlasov)
+- **DateTimePicker:** Fixes issue with date picker showing invalid date [#97888](https://github.com/grafana/grafana/pull/97888), [@torkelo](https://github.com/torkelo)
+- **Fix:** Add support for datasource variable queries [#98098](https://github.com/grafana/grafana/pull/98098), [@sunker](https://github.com/sunker)
+- **Fix:** Do not fetch Orgs if the user is authenticated by apikey/sa or render key [#97162](https://github.com/grafana/grafana/pull/97162), [@mgyongyosi](https://github.com/mgyongyosi)
+- **Fix:** Double encoding of URLs when using data proxy [#98494](https://github.com/grafana/grafana/pull/98494), [@s4kh](https://github.com/s4kh)
+- **Font:** Disable contextual font ligatures [#98521](https://github.com/grafana/grafana/pull/98521), [@ashharrison90](https://github.com/ashharrison90)
+- **GrafanaUI:** Fix inconsistent controlled/uncontrolled state in AutoSizeInput [#96696](https://github.com/grafana/grafana/pull/96696), [@joshhunt](https://github.com/joshhunt)
+- **GrafanaUI:** Revert: Fix inconsistent controlled/uncontrolled state in AutoSizeInput [#97551](https://github.com/grafana/grafana/pull/97551), [@itsmylife](https://github.com/itsmylife)
+- **InfluxDB:** Adhoc filters can use template vars as values [#98567](https://github.com/grafana/grafana/pull/98567), [@bossinc](https://github.com/bossinc)
+- **Library Panel:** Fix issue where library panels did not display panel links. [#98655](https://github.com/grafana/grafana/pull/98655), [@yincongcyincong](https://github.com/yincongcyincong)
+- **LibraryPanel:** Fallback to panel title if library panel title is not set [#99411](https://github.com/grafana/grafana/pull/99411), [@ivanortegaalba](https://github.com/ivanortegaalba)
+- **Loki:** Fix a bug when reading frames without values but warnings [#97197](https://github.com/grafana/grafana/pull/97197), [@svennergr](https://github.com/svennergr)
+- **Loki:** Only hide a set of labels instead of every label starting with `__` [#98730](https://github.com/grafana/grafana/pull/98730), [@svennergr](https://github.com/svennergr)
+- **Org:** Fix redirection logic to work consistently [#96521](https://github.com/grafana/grafana/pull/96521), [@yincongcyincong](https://github.com/yincongcyincong)
+- **Panel inspect:** Fix file names of data download included uninterpolated variable names. [#98832](https://github.com/grafana/grafana/pull/98832), [@alexrosenfeld10](https://github.com/alexrosenfeld10)
+- **Scenes:** Upgrade to 5.36.3 [#98661](https://github.com/grafana/grafana/pull/98661), [@ivanortegaalba](https://github.com/ivanortegaalba)
+- **Snapshot:** Show proper breadcrumb path [#98806](https://github.com/grafana/grafana/pull/98806), [@ashharrison90](https://github.com/ashharrison90)
+- **Time Picker:** Fix "Fiscal year start month" selection behaviour [#98576](https://github.com/grafana/grafana/pull/98576), [@ashharrison90](https://github.com/ashharrison90)
+- **Unified Storage:** Add support for verify-full in postgres [#96825](https://github.com/grafana/grafana/pull/96825), [@chaudyg](https://github.com/chaudyg)
+- **Unified Storage:** Use tls preferred when grafana db using ssl [#97378](https://github.com/grafana/grafana/pull/97378), [@owensmallwood](https://github.com/owensmallwood)
+- **Usage Insights:** Fix usage insight errors being logged as [object Object] [#93502](https://github.com/grafana/grafana/pull/93502), [@mmandrus](https://github.com/mmandrus)
+
+### Breaking changes
+
+- **Loki:** Default to `/labels` API with `query` param instead of `/series` API [#97935](https://github.com/grafana/grafana/pull/97935), [@svennergr](https://github.com/svennergr)
+
+### Plugin development fixes & changes
+
+- **Grafana UI:** Re-add react-router-dom as a dependency [#97540](https://github.com/grafana/grafana/pull/97540), [@leventebalogh](https://github.com/leventebalogh)
+
+
+
+
+# 11.4.1 (2025-01-28)
+
+### Features and enhancements
+
+- **Security:** Update to Go 1.23.5 - Backport to v11.4.x [#99123](https://github.com/grafana/grafana/pull/99123), [@Proximyst](https://github.com/Proximyst)
+- **Security:** Update to Go 1.23.5 - Backport to v11.4.x (Enterprise)
+
+### Bug fixes
+
+- **Alerting:** AlertingQueryRunner should skip descendant nodes of invalid queries [#97830](https://github.com/grafana/grafana/pull/97830), [@gillesdemey](https://github.com/gillesdemey)
+- **Alerting:** Fix alert rules unpausing after moving rule to different folder [#97583](https://github.com/grafana/grafana/pull/97583), [@santihernandezc](https://github.com/santihernandezc)
+- **Alerting:** Fix label escaping in rule export [#98649](https://github.com/grafana/grafana/pull/98649), [@moustafab](https://github.com/moustafab)
+- **Alerting:** Fix slack image uploading to use new api [#98066](https://github.com/grafana/grafana/pull/98066), [@moustafab](https://github.com/moustafab)
+- **Azure/GCM:** Improve error display [#97594](https://github.com/grafana/grafana/pull/97594), [@aangelisc](https://github.com/aangelisc)
+- **Dashboards:** Fix issue where filtered panels would not react to variable changes [#98734](https://github.com/grafana/grafana/pull/98734), [@oscarkilhed](https://github.com/oscarkilhed)
+- **Dashboards:** Fixes issue with panel header showing even when hide time override was enabled [#98747](https://github.com/grafana/grafana/pull/98747), [@torkelo](https://github.com/torkelo)
+- **Dashboards:** Fixes week relative time ranges when weekStart was changed [#98269](https://github.com/grafana/grafana/pull/98269), [@torkelo](https://github.com/torkelo)
+- **Dashboards:** Panel react for `timeFrom` and `timeShift` changes using variables [#98659](https://github.com/grafana/grafana/pull/98659), [@Sergej-Vlasov](https://github.com/Sergej-Vlasov)
+- **DateTimePicker:** Fixes issue with date picker showing invalid date [#97971](https://github.com/grafana/grafana/pull/97971), [@torkelo](https://github.com/torkelo)
+- **Fix:** Add support for datasource variable queries [#98119](https://github.com/grafana/grafana/pull/98119), [@sunker](https://github.com/sunker)
+- **InfluxDB:** Adhoc filters can use template vars as values [#98786](https://github.com/grafana/grafana/pull/98786), [@bossinc](https://github.com/bossinc)
+- **LibraryPanel:** Fallback to panel title if library panel title is not set [#99410](https://github.com/grafana/grafana/pull/99410), [@ivanortegaalba](https://github.com/ivanortegaalba)
+
+### Plugin development fixes & changes
+
+- **Grafana UI:** Re-add react-router-dom as a dependency [#98422](https://github.com/grafana/grafana/pull/98422), [@leventebalogh](https://github.com/leventebalogh)
+
+
+
+
+# 11.3.3 (2025-01-28)
+
+### Features and enhancements
+
+- **Azure Monitor:** Add a feature flag to toggle user auth for Azure Monitor only [#97576](https://github.com/grafana/grafana/pull/97576), [@adamyeats](https://github.com/adamyeats)
+- **Security:** Update to Go 1.23.5 - Backport to v11.3.x [#99124](https://github.com/grafana/grafana/pull/99124), [@Proximyst](https://github.com/Proximyst)
+- **Security:** Update to Go 1.23.5 - Backport to v11.3.x (Enterprise)
+
+### Bug fixes
+
+- **Alerting:** AlertingQueryRunner should skip descendant nodes of invalid queries [#97829](https://github.com/grafana/grafana/pull/97829), [@gillesdemey](https://github.com/gillesdemey)
+- **Azure/GCM:** Improve error display [#97593](https://github.com/grafana/grafana/pull/97593), [@aangelisc](https://github.com/aangelisc)
+- **Dashboard:** Fixes issue with compatability of old DashboardModel.annotations [#97467](https://github.com/grafana/grafana/pull/97467), [@torkelo](https://github.com/torkelo)
+- **Dashboards:** Fix issue where filtered panels would not react to variable changes [#98733](https://github.com/grafana/grafana/pull/98733), [@oscarkilhed](https://github.com/oscarkilhed)
+- **Dashboards:** Fixes issue with panel header showing even when hide time override was enabled [#97389](https://github.com/grafana/grafana/pull/97389), [@torkelo](https://github.com/torkelo)
+- **Dashboards:** Fixes week relative time ranges when weekStart was changed [#98268](https://github.com/grafana/grafana/pull/98268), [@torkelo](https://github.com/torkelo)
+- **DateTimePicker:** Fixes issue with date picker showing invalid date [#97970](https://github.com/grafana/grafana/pull/97970), [@torkelo](https://github.com/torkelo)
+- **Fix:** Add support for datasource variable queries [#98118](https://github.com/grafana/grafana/pull/98118), [@sunker](https://github.com/sunker)
+- **InfluxDB:** Adhoc filters can use template vars as values [#98785](https://github.com/grafana/grafana/pull/98785), [@bossinc](https://github.com/bossinc)
+- **Unified Storage:** Use tls preferred when grafana db using ssl [#97379](https://github.com/grafana/grafana/pull/97379), [@owensmallwood](https://github.com/owensmallwood)
+
+### Plugin development fixes & changes
+
+- **Grafana UI:** Re-add react-router-dom as a dependency [#98421](https://github.com/grafana/grafana/pull/98421), [@leventebalogh](https://github.com/leventebalogh)
+
+
+
+
+# 11.2.6 (2025-01-28)
+
+### Features and enhancements
+
+- **Azure Monitor:** Add a feature flag to toggle user auth for Azure Monitor only [#97565](https://github.com/grafana/grafana/pull/97565), [@adamyeats](https://github.com/adamyeats)
+- **Security:** Update to Go 1.22.11 - Backport to v11.2.x [#99125](https://github.com/grafana/grafana/pull/99125), [@Proximyst](https://github.com/Proximyst)
+- **Security:** Update to Go 1.22.11 - Backport to v11.2.x (Enterprise)
+
+### Bug fixes
+
+- **Azure/GCM:** Improve error display [#97591](https://github.com/grafana/grafana/pull/97591), [@aangelisc](https://github.com/aangelisc)
+
+
+
+
+# 11.1.11 (2025-01-28)
+
+### Features and enhancements
+
+- **Security:** Update to Go 1.22.11 - Backport to v11.1.x [#99126](https://github.com/grafana/grafana/pull/99126), [@Proximyst](https://github.com/Proximyst)
+- **Security:** Update to Go 1.22.11 - Backport to v11.1.x (Enterprise)
+
+### Bug fixes
+
+- **Azure/GCM:** Improve error display [#97595](https://github.com/grafana/grafana/pull/97595), [@aangelisc](https://github.com/aangelisc)
+
+
+
+
+# 11.0.10 (2025-01-28)
+
+### Features and enhancements
+
+- **Security:** Update to Go 1.22.11 - Backport to v11.0.x [#99127](https://github.com/grafana/grafana/pull/99127), [@Proximyst](https://github.com/Proximyst)
+- **Security:** Update to Go 1.22.11 - Backport to v11.0.x (Enterprise)
+
+### Bug fixes
+
+- **Azure/GCM:** Improve error display [#97592](https://github.com/grafana/grafana/pull/97592), [@aangelisc](https://github.com/aangelisc)
+
+
+
+
+# 10.4.15 (2025-01-28)
+
+### Features and enhancements
+
+- **Security:** Update to Go 1.22.11 - Backport to v10.4.x [#99128](https://github.com/grafana/grafana/pull/99128), [@Proximyst](https://github.com/Proximyst)
+- **Security:** Update to Go 1.22.11 - Backport to v10.4.x (Enterprise)
+
+### Bug fixes
+
+- **Azure/GCM:** Improve error display [#97590](https://github.com/grafana/grafana/pull/97590), [@aangelisc](https://github.com/aangelisc)
+
+
# 11.4.0 (2024-12-05)
diff --git a/Dockerfile b/Dockerfile
index 7f05689eef2..1ba856b9220 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,13 +1,19 @@
+# syntax=docker/dockerfile:1
-ARG BASE_IMAGE=alpine:3.20
+# to maintain formatting of multiline commands in vscode, add the following to settings.json:
+# "docker.languageserver.formatter.ignoreMultilineInstructions": true
+
+ARG BASE_IMAGE=alpine:3.21
ARG JS_IMAGE=node:22-alpine
ARG JS_PLATFORM=linux/amd64
-ARG GO_IMAGE=golang:1.23.5-alpine
+ARG GO_IMAGE=golang:1.23.7-alpine
+# Default to building locally
ARG GO_SRC=go-builder
ARG JS_SRC=js-builder
-FROM --platform=${JS_PLATFORM} ${JS_IMAGE} as js-builder
+# Javascript build stage
+FROM --platform=${JS_PLATFORM} ${JS_IMAGE} AS js-builder
ENV NODE_OPTIONS=--max_old_space_size=8000
@@ -32,7 +38,8 @@ COPY emails emails
ENV NODE_ENV=production
RUN yarn build
-FROM ${GO_IMAGE} as go-builder
+# Golang build stage
+FROM ${GO_IMAGE} AS go-builder
ARG COMMIT_SHA=""
ARG BUILD_BRANCH=""
@@ -55,24 +62,24 @@ COPY go.* ./
COPY .bingo .bingo
# Include vendored dependencies
-COPY pkg/util/xorm/go.* pkg/util/xorm/
-COPY pkg/apiserver/go.* pkg/apiserver/
-COPY pkg/apimachinery/go.* pkg/apimachinery/
-COPY pkg/build/go.* pkg/build/
-COPY pkg/build/wire/go.* pkg/build/wire/
-COPY pkg/promlib/go.* pkg/promlib/
-COPY pkg/storage/unified/resource/go.* pkg/storage/unified/resource/
-COPY pkg/storage/unified/apistore/go.* pkg/storage/unified/apistore/
-COPY pkg/semconv/go.* pkg/semconv/
-COPY pkg/aggregator/go.* pkg/aggregator/
-COPY apps/playlist/go.* apps/playlist/
-COPY apps/investigation/go.* apps/investigation/
-COPY apps/advisor/go.* apps/advisor/
+COPY pkg/util/xorm pkg/util/xorm
+COPY pkg/apiserver pkg/apiserver
+COPY pkg/apimachinery pkg/apimachinery
+COPY pkg/build pkg/build
+COPY pkg/build/wire pkg/build/wire
+COPY pkg/promlib pkg/promlib
+COPY pkg/storage/unified/resource pkg/storage/unified/resource
+COPY pkg/storage/unified/apistore pkg/storage/unified/apistore
+COPY pkg/semconv pkg/semconv
+COPY pkg/aggregator pkg/aggregator
+COPY apps/playlist apps/playlist
+COPY apps/investigations apps/investigations
+COPY apps/advisor apps/advisor
COPY apps apps
COPY kindsv2 kindsv2
-COPY apps/alerting/notifications/go.* apps/alerting/notifications/
-COPY pkg/codegen/go.* pkg/codegen/
-COPY pkg/plugins/codegen/go.* pkg/plugins/codegen/
+COPY apps/alerting/notifications apps/alerting/notifications
+COPY pkg/codegen pkg/codegen
+COPY pkg/plugins/codegen pkg/plugins/codegen
RUN go mod download
RUN if [[ "$BINGO" = "true" ]]; then \
@@ -97,7 +104,8 @@ ENV BUILD_BRANCH=${BUILD_BRANCH}
RUN make build-go GO_BUILD_TAGS=${GO_BUILD_TAGS} WIRE_TAGS=${WIRE_TAGS}
-FROM ${BASE_IMAGE} as tgz-builder
+# From-tarball build stage
+FROM ${BASE_IMAGE} AS tgz-builder
WORKDIR /tmp/grafana
@@ -109,13 +117,14 @@ COPY ${GRAFANA_TGZ} /tmp/grafana.tar.gz
RUN tar x -z -f /tmp/grafana.tar.gz --strip-components=1
# helpers for COPY --from
-FROM ${GO_SRC} as go-src
-FROM ${JS_SRC} as js-src
+FROM ${GO_SRC} AS go-src
+FROM ${JS_SRC} AS js-src
# Final stage
FROM ${BASE_IMAGE}
LABEL maintainer="Grafana Labs "
+LABEL org.opencontainers.image.source="https://github.com/grafana/grafana"
ARG GF_UID="472"
ARG GF_GID="0"
@@ -145,19 +154,20 @@ RUN if grep -i -q alpine /etc/issue; then \
fi
# glibc support for alpine x86_64 only
+# docker run --rm --env STDOUT=1 sgerrand/glibc-builder 2.40 /usr/glibc-compat > glibc-bin-2.40.tar.gz
+ARG GLIBC_VERSION=2.40
+
RUN if grep -i -q alpine /etc/issue && [ `arch` = "x86_64" ]; then \
- wget -q -O /etc/apk/keys/sgerrand.rsa.pub https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub && \
- wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.35-r0/glibc-2.35-r0.apk \
- -O /tmp/glibc-2.35-r0.apk && \
- wget https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.35-r0/glibc-bin-2.35-r0.apk \
- -O /tmp/glibc-bin-2.35-r0.apk && \
- apk add --force-overwrite --no-cache /tmp/glibc-2.35-r0.apk /tmp/glibc-bin-2.35-r0.apk && \
- rm -f /lib64/ld-linux-x86-64.so.2 && \
- ln -s /usr/glibc-compat/lib64/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2 && \
- rm -f /tmp/glibc-2.35-r0.apk && \
- rm -f /tmp/glibc-bin-2.35-r0.apk && \
- rm -f /lib/ld-linux-x86-64.so.2 && \
- rm -f /etc/ld.so.cache; \
+ wget -qO- "https://dl.grafana.com/glibc/glibc-bin-$GLIBC_VERSION.tar.gz" | tar zxf - -C / \
+ usr/glibc-compat/lib/ld-linux-x86-64.so.2 \
+ usr/glibc-compat/lib/libc.so.6 \
+ usr/glibc-compat/lib/libdl.so.2 \
+ usr/glibc-compat/lib/libm.so.6 \
+ usr/glibc-compat/lib/libpthread.so.0 \
+ usr/glibc-compat/lib/librt.so.1 \
+ usr/glibc-compat/lib/libresolv.so.2 && \
+ mkdir /lib64 && \
+ ln -s /usr/glibc-compat/lib/ld-linux-x86-64.so.2 /lib64; \
fi
COPY --from=go-src /tmp/grafana/conf ./conf
diff --git a/MAINTAINERS.md b/MAINTAINERS.md
index cab21a089cc..b1443b33722 100644
--- a/MAINTAINERS.md
+++ b/MAINTAINERS.md
@@ -8,4 +8,4 @@
- @davkal
- Docs:
- @chri2547
- - @brendamuir
+ - @JohnnyK-Grafana
diff --git a/Makefile b/Makefile
index 3df11c69545..699cfb0652e 100644
--- a/Makefile
+++ b/Makefile
@@ -8,7 +8,7 @@ WIRE_TAGS = "oss"
include .bingo/Variables.mk
GO = go
-GO_VERSION = 1.23.5
+GO_VERSION = 1.23.7
GO_LINT_FILES ?= $(shell ./scripts/go-workspace/golangci-lint-includes.sh)
GO_TEST_FILES ?= $(shell ./scripts/go-workspace/test-includes.sh)
SH_FILES ?= $(shell find ./scripts -name *.sh)
@@ -17,6 +17,7 @@ GO_RACE_FLAG := $(if $(GO_RACE),-race)
GO_BUILD_FLAGS += $(if $(GO_BUILD_DEV),-dev)
GO_BUILD_FLAGS += $(if $(GO_BUILD_TAGS),-build-tags=$(GO_BUILD_TAGS))
GO_BUILD_FLAGS += $(GO_RACE_FLAG)
+GO_TEST_OUTPUT := $(shell [ -n "$(GO_TEST_OUTPUT)" ] && echo '-json | tee $(GO_TEST_OUTPUT) | tparse -all')
GIT_BASE = remotes/origin/main
# GNU xargs has flag -r, and BSD xargs (e.g. MacOS) has that behaviour by default
@@ -130,14 +131,12 @@ else
i18n-extract-enterprise:
@echo "Extracting i18n strings for Enterprise"
yarn run i18next --config public/locales/i18next-parser-enterprise.config.cjs
- node ./public/locales/pseudo.mjs --mode enterprise
endif
.PHONY: i18n-extract
i18n-extract: i18n-extract-enterprise
@echo "Extracting i18n strings for OSS"
yarn run i18next --config public/locales/i18next-parser.config.cjs
- node ./public/locales/pseudo.mjs --mode oss
##@ Building
.PHONY: gen-cue
@@ -248,8 +247,7 @@ test-go: test-go-unit test-go-integration
.PHONY: test-go-unit
test-go-unit: ## Run unit tests for backend with flags.
@echo "test backend unit tests"
- printf '$(GO_TEST_FILES)' | xargs \
- $(GO) test $(GO_RACE_FLAG) -short -covermode=atomic -timeout=30m
+ $(GO) test $(GO_RACE_FLAG) -short -covermode=atomic -coverprofile=unit.cov -timeout=30m $(GO_TEST_FILES) $(GO_TEST_OUTPUT)
.PHONY: test-go-unit-pretty
test-go-unit-pretty: check-tparse
@@ -262,7 +260,7 @@ test-go-unit-pretty: check-tparse
.PHONY: test-go-integration
test-go-integration: ## Run integration tests for backend with flags.
@echo "test backend integration tests"
- $(GO) test $(GO_RACE_FLAG) -count=1 -run "^TestIntegration" -covermode=atomic -timeout=5m $(GO_INTEGRATION_TESTS)
+ $(GO) test $(GO_RACE_FLAG) -count=1 -run "^TestIntegration" -covermode=atomic -coverprofile=integration.cov -timeout=5m $(GO_INTEGRATION_TESTS) $(GO_TEST_OUTPUT)
.PHONY: test-go-integration-alertmanager
test-go-integration-alertmanager: ## Run integration tests for the remote alertmanager (config taken from the mimir_backend block).
@@ -271,6 +269,14 @@ test-go-integration-alertmanager: ## Run integration tests for the remote alertm
AM_URL=http://localhost:8080 AM_TENANT_ID=test \
$(GO) test $(GO_RACE_FLAG) -count=1 -run "^TestIntegrationRemoteAlertmanager" -covermode=atomic -timeout=5m ./pkg/services/ngalert/...
+.PHONY: test-go-integration-grafana-alertmanager
+test-go-integration-grafana-alertmanager: ## Run integration tests for the grafana alertmanager
+ @echo "test grafana alertmanager integration tests"
+ @export GRAFANA_VERSION=11.5.0-81938; \
+ $(GO) run tools/setup_grafana_alertmanager_integration_test_images.go; \
+ $(GO) clean -testcache; \
+ $(GO) test $(GO_RACE_FLAG) -count=1 -run "^TestAlertmanagerIntegration" -covermode=atomic -timeout=10m ./pkg/tests/alertmanager/...
+
.PHONY: test-go-integration-postgres
test-go-integration-postgres: devenv-postgres ## Run integration tests for postgres backend with flags.
@echo "test backend integration postgres tests"
@@ -421,6 +427,7 @@ protobuf: ## Compile protobuf definitions
buf generate pkg/plugins/backendplugin/secretsmanagerplugin --template pkg/plugins/backendplugin/secretsmanagerplugin/buf.gen.yaml
buf generate pkg/storage/unified/resource --template pkg/storage/unified/resource/buf.gen.yaml
buf generate pkg/services/authz/proto/v1 --template pkg/services/authz/proto/v1/buf.gen.yaml
+ buf generate pkg/services/ngalert/store/proto/v1 --template pkg/services/ngalert/store/proto/v1/buf.gen.yaml
.PHONY: clean
clean: ## Clean up intermediate build artifacts.
diff --git a/README.md b/README.md
index 7322e6a1c7d..033ebdc1ea6 100644
--- a/README.md
+++ b/README.md
@@ -43,7 +43,7 @@ If you're interested in contributing to the Grafana project:
- If you have a specific question, check out our [discussion forums](https://community.grafana.com/).
- For general discussions, join us on the [official Slack](https://slack.grafana.com) team.
-This project is tested with [BrowserStack](https://www.browserstack.com/)
+This project is tested with [BrowserStack](https://www.browserstack.com/).
## License
diff --git a/apps/advisor/.gitignore b/apps/advisor/.gitignore
new file mode 100644
index 00000000000..9e73bafbae8
--- /dev/null
+++ b/apps/advisor/.gitignore
@@ -0,0 +1 @@
+plugin/src
\ No newline at end of file
diff --git a/apps/advisor/Makefile b/apps/advisor/Makefile
index 926f5a2840f..7a5f1c99365 100644
--- a/apps/advisor/Makefile
+++ b/apps/advisor/Makefile
@@ -1,8 +1,3 @@
.PHONY: generate
generate:
- @grafana-app-sdk generate -g ./pkg/apis --grouping=group --postprocess
- # HACK: Clean up generated CRD files.
- # TODO: The SDK currently omits generating the manifest Go file with `--defencoding=none`,
- # which we would normally use here to skip generating the CRD files.
- # This needs to be addressed.
- @rm -rf definitions
+ @grafana-app-sdk generate -g ./pkg/apis --grouping=group --postprocess --defencoding=none
diff --git a/apps/advisor/go.mod b/apps/advisor/go.mod
index 8fcc336a52b..917e2f985b4 100644
--- a/apps/advisor/go.mod
+++ b/apps/advisor/go.mod
@@ -1,10 +1,10 @@
module github.com/grafana/grafana/apps/advisor
-go 1.23.4
+go 1.23.7
require (
- github.com/grafana/grafana-app-sdk v0.30.0
- k8s.io/apimachinery v0.32.0
+ github.com/grafana/grafana-app-sdk v0.31.0
+ k8s.io/apimachinery v0.32.1
k8s.io/klog/v2 v2.130.1
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f
)
@@ -31,7 +31,7 @@ require (
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
github.com/google/uuid v1.6.0 // indirect
- github.com/grafana/grafana-app-sdk/logging v0.29.0 // indirect
+ github.com/grafana/grafana-app-sdk/logging v0.30.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
@@ -53,31 +53,31 @@ require (
github.com/spf13/pflag v1.0.5 // indirect
github.com/x448/float16 v0.8.4 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
- go.opentelemetry.io/otel v1.33.0 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0 // indirect
- go.opentelemetry.io/otel/metric v1.33.0 // indirect
- go.opentelemetry.io/otel/sdk v1.33.0 // indirect
- go.opentelemetry.io/otel/trace v1.33.0 // indirect
+ go.opentelemetry.io/otel v1.34.0 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 // indirect
+ go.opentelemetry.io/otel/metric v1.34.0 // indirect
+ go.opentelemetry.io/otel/sdk v1.34.0 // indirect
+ go.opentelemetry.io/otel/trace v1.34.0 // indirect
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
- golang.org/x/net v0.34.0 // indirect
+ golang.org/x/net v0.36.0 // indirect
golang.org/x/oauth2 v0.25.0 // indirect
- golang.org/x/sync v0.10.0 // indirect
- golang.org/x/sys v0.29.0 // indirect
- golang.org/x/term v0.28.0 // indirect
- golang.org/x/text v0.21.0 // indirect
+ golang.org/x/sync v0.11.0 // indirect
+ golang.org/x/sys v0.30.0 // indirect
+ golang.org/x/term v0.29.0 // indirect
+ golang.org/x/text v0.22.0 // indirect
golang.org/x/time v0.9.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
- google.golang.org/genproto/googleapis/api v0.0.0-20250102185135-69823020774d // indirect
- google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d // indirect
+ google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect
google.golang.org/grpc v1.69.4 // indirect
- google.golang.org/protobuf v1.36.1 // indirect
+ google.golang.org/protobuf v1.36.3 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
- k8s.io/api v0.32.0 // indirect
- k8s.io/apiextensions-apiserver v0.32.0 // indirect
- k8s.io/client-go v0.32.0 // indirect
+ k8s.io/api v0.32.1 // indirect
+ k8s.io/apiextensions-apiserver v0.32.1 // indirect
+ k8s.io/client-go v0.32.1 // indirect
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.5.0 // indirect
diff --git a/apps/advisor/go.sum b/apps/advisor/go.sum
index 858c73dd4b4..cdf6cf446ed 100644
--- a/apps/advisor/go.sum
+++ b/apps/advisor/go.sum
@@ -51,8 +51,10 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grafana/grafana-app-sdk v0.30.0 h1:Hqn2pETu2mQ4RpWkZYEQfu01P7xd1Z1Gj+HX/8aB0tw=
github.com/grafana/grafana-app-sdk v0.30.0/go.mod h1:jhfqNIovb+Mes2vdMf9iMCWQkp1GTNtyNuExONtiNuk=
+github.com/grafana/grafana-app-sdk v0.31.0/go.mod h1:Xw00NL7qpRLo5r3Gn48Bl1Xn2n4eUDI5pYf/wMufKWs=
github.com/grafana/grafana-app-sdk/logging v0.29.0 h1:mgbXaAf33aFwqwGVeaX30l8rkeAJH0iACgX5Rn6YkN4=
github.com/grafana/grafana-app-sdk/logging v0.29.0/go.mod h1:xy6ZyVXl50Z3DBDLybvBPphbykPhuVNed/VNmen9DQM=
+github.com/grafana/grafana-app-sdk/logging v0.30.0/go.mod h1:xy6ZyVXl50Z3DBDLybvBPphbykPhuVNed/VNmen9DQM=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@@ -126,20 +128,27 @@ go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJyS
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw=
go.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I=
+go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 h1:Vh5HayB/0HHfOQA7Ctx69E/Y/DcQSMPpKANYVMQ7fBA=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0/go.mod h1:cpgtDBaqD/6ok/UG0jT15/uKjAY8mRA53diogHBg3UI=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0 h1:5pojmb1U1AogINhN3SurB+zm/nIcusopeBNp42f45QM=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0/go.mod h1:57gTHJSE5S1tqg+EKsLPlTWhpHMsWlVmer+LA926XiA=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0 h1:wpMfgF8E1rkrT1Z6meFh1NDtownE9Ii3n3X2GJYjsaU=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0/go.mod h1:wAy0T/dUbs468uOlkT31xjvqQgEVXv58BRFWEgn5v/0=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0/go.mod h1:9cKLGBDzI/F3NoHLQGm4ZrYdIHsvGt6ej6hUowxY0J4=
go.opentelemetry.io/otel/metric v1.33.0 h1:r+JOocAyeRVXD8lZpjdQjzMadVZp2M4WmQ+5WtEnklQ=
go.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M=
+go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
go.opentelemetry.io/otel/sdk v1.33.0 h1:iax7M131HuAm9QkZotNHEfstof92xM+N8sr3uHXc2IM=
go.opentelemetry.io/otel/sdk v1.33.0/go.mod h1:A1Q5oi7/9XaMlIWzPSxLRWOI8nG3FnzHJNbiENQuihM=
+go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc=
go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8=
go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s=
go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck=
+go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
@@ -155,6 +164,8 @@ golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
+golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA=
+golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I=
golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70=
golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -162,17 +173,21 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
+golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
+golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -189,12 +204,15 @@ gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw
gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
google.golang.org/genproto/googleapis/api v0.0.0-20250102185135-69823020774d h1:H8tOf8XM88HvKqLTxe755haY6r1fqqzLbEnfrmLXlSA=
google.golang.org/genproto/googleapis/api v0.0.0-20250102185135-69823020774d/go.mod h1:2v7Z7gP2ZUOGsaFyxATQSRoBnKygqVq2Cwnvom7QiqY=
+google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:Ic02D47M+zbarjYYUlK57y316f2MoN0gjAwI3f2S95o=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d h1:xJJRGY7TJcvIlpSrN3K6LAWgNFUILlO+OMAqtg9aqnw=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d/go.mod h1:3ENsm/5D1mzDyhpzeRi1NR784I0BcofWBoSc5QqqMK4=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:+2Yz8+CLJbIfL9z73EW45avw8Lmge3xVElCP9zEKi50=
google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A=
google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4=
google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk=
google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
@@ -206,12 +224,16 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.32.0 h1:OL9JpbvAU5ny9ga2fb24X8H6xQlVp+aJMFlgtQjR9CE=
k8s.io/api v0.32.0/go.mod h1:4LEwHZEf6Q/cG96F3dqR965sYOfmPM7rq81BLgsE0p0=
+k8s.io/api v0.32.1/go.mod h1:/Yi/BqkuueW1BgpoePYBRdDYfjPF5sgTr5+YqDZra5k=
k8s.io/apiextensions-apiserver v0.32.0 h1:S0Xlqt51qzzqjKPxfgX1xh4HBZE+p8KKBq+k2SWNOE0=
k8s.io/apiextensions-apiserver v0.32.0/go.mod h1:86hblMvN5yxMvZrZFX2OhIHAuFIMJIZ19bTvzkP+Fmw=
+k8s.io/apiextensions-apiserver v0.32.1/go.mod h1:sxWIGuGiYov7Io1fAS2X06NjMIk5CbRHc2StSmbaQto=
k8s.io/apimachinery v0.32.0 h1:cFSE7N3rmEEtv4ei5X6DaJPHHX0C+upp+v5lVPiEwpg=
k8s.io/apimachinery v0.32.0/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
+k8s.io/apimachinery v0.32.1/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
k8s.io/client-go v0.32.0 h1:DimtMcnN/JIKZcrSrstiwvvZvLjG0aSxy8PxN8IChp8=
k8s.io/client-go v0.32.0/go.mod h1:boDWvdM1Drk4NJj/VddSLnx59X3OPgwrOo0vGbtq9+8=
+k8s.io/client-go v0.32.1/go.mod h1:aTTKZY7MdxUaJ/KiUs8D+GssR9zJZi77ZqtzcGXIiDg=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y=
diff --git a/apps/advisor/kinds/check.cue b/apps/advisor/kinds/check.cue
index 4ab33fb05df..4aea38d6759 100644
--- a/apps/advisor/kinds/check.cue
+++ b/apps/advisor/kinds/check.cue
@@ -7,28 +7,45 @@ check: {
versions: {
"v0alpha1": {
codegen: {
- frontend: false
+ frontend: true
backend: true
}
+ validation: {
+ operations: [
+ "CREATE",
+ "UPDATE",
+ ]
+ }
schema: {
- spec: {
+ #Data: {
// Generic data input that a check can receive
data?: [string]: string
}
- status: {
- report: {
+ #ErrorLink: {
+ // URL to a page with more information about the error
+ url: string
+ // Human readable error message
+ message: string
+ }
+ #ReportFailure: {
+ // Severity of the failure
+ severity: "high" | "low"
+ // Step ID that the failure is associated with
+ stepID: string
+ // Human readable identifier of the item that failed
+ item: string
+ // Links to actions that can be taken to resolve the failure
+ links: [...#ErrorLink]
+ }
+ #Report: {
// Number of elements analyzed
count: int
- // List of errors
- errors: [...{
- // Severity of the error
- severity: "high" | "low"
- // Human readable reason for the error
- reason: string
- // Action to take to resolve the error
- action: string
- }]
- }
+ // List of failures
+ failures: [...#ReportFailure]
+ }
+ spec: #Data
+ status: {
+ report: #Report
}
}
}
diff --git a/apps/advisor/kinds/checktype.cue b/apps/advisor/kinds/checktype.cue
new file mode 100644
index 00000000000..e2d653e629e
--- /dev/null
+++ b/apps/advisor/kinds/checktype.cue
@@ -0,0 +1,27 @@
+package advisor
+
+checktype: {
+ kind: "CheckType"
+ pluralName: "CheckTypes"
+ current: "v0alpha1"
+ versions: {
+ "v0alpha1": {
+ codegen: {
+ frontend: true
+ backend: true
+ }
+ schema: {
+ #Step: {
+ title: string
+ description: string
+ stepID: string
+ resolution: string
+ }
+ spec: {
+ name: string
+ steps: [...#Step]
+ }
+ }
+ }
+ }
+}
diff --git a/apps/advisor/kinds/manifest.cue b/apps/advisor/kinds/manifest.cue
index 6f96066967d..75a0eee05ef 100644
--- a/apps/advisor/kinds/manifest.cue
+++ b/apps/advisor/kinds/manifest.cue
@@ -5,5 +5,6 @@ manifest: {
groupOverride: "advisor.grafana.app"
kinds: [
check,
+ checktype,
]
}
diff --git a/apps/advisor/pkg/apis/advisor/v0alpha1/check_status_gen.go b/apps/advisor/pkg/apis/advisor/v0alpha1/check_status_gen.go
index 057ed6c4b7e..c9acc5ce31c 100644
--- a/apps/advisor/pkg/apis/advisor/v0alpha1/check_status_gen.go
+++ b/apps/advisor/pkg/apis/advisor/v0alpha1/check_status_gen.go
@@ -2,6 +2,36 @@
package v0alpha1
+// +k8s:openapi-gen=true
+type CheckErrorLink struct {
+ // URL to a page with more information about the error
+ Url string `json:"url"`
+ // Human readable error message
+ Message string `json:"message"`
+}
+
+// NewCheckErrorLink creates a new CheckErrorLink object.
+func NewCheckErrorLink() *CheckErrorLink {
+ return &CheckErrorLink{}
+}
+
+// +k8s:openapi-gen=true
+type CheckReportFailure struct {
+ // Severity of the failure
+ Severity CheckReportFailureSeverity `json:"severity"`
+ // Step ID that the failure is associated with
+ StepID string `json:"stepID"`
+ // Human readable identifier of the item that failed
+ Item string `json:"item"`
+ // Links to actions that can be taken to resolve the failure
+ Links []CheckErrorLink `json:"links"`
+}
+
+// NewCheckReportFailure creates a new CheckReportFailure object.
+func NewCheckReportFailure() *CheckReportFailure {
+ return &CheckReportFailure{}
+}
+
// +k8s:openapi-gen=true
type CheckstatusOperatorState struct {
// lastEvaluation is the ResourceVersion last evaluated
@@ -37,6 +67,14 @@ func NewCheckStatus() *CheckStatus {
}
}
+// +k8s:openapi-gen=true
+type CheckReportFailureSeverity string
+
+const (
+ CheckReportFailureSeverityHigh CheckReportFailureSeverity = "high"
+ CheckReportFailureSeverityLow CheckReportFailureSeverity = "low"
+)
+
// +k8s:openapi-gen=true
type CheckStatusOperatorStateState string
@@ -46,35 +84,12 @@ const (
CheckStatusOperatorStateStateFailed CheckStatusOperatorStateState = "failed"
)
-// +k8s:openapi-gen=true
-type CheckStatusSeverity string
-
-const (
- CheckStatusSeverityHigh CheckStatusSeverity = "high"
- CheckStatusSeverityLow CheckStatusSeverity = "low"
-)
-
-// +k8s:openapi-gen=true
-type CheckV0alpha1StatusReportErrors struct {
- // Severity of the error
- Severity CheckStatusSeverity `json:"severity"`
- // Human readable reason for the error
- Reason string `json:"reason"`
- // Action to take to resolve the error
- Action string `json:"action"`
-}
-
-// NewCheckV0alpha1StatusReportErrors creates a new CheckV0alpha1StatusReportErrors object.
-func NewCheckV0alpha1StatusReportErrors() *CheckV0alpha1StatusReportErrors {
- return &CheckV0alpha1StatusReportErrors{}
-}
-
// +k8s:openapi-gen=true
type CheckV0alpha1StatusReport struct {
// Number of elements analyzed
Count int64 `json:"count"`
- // List of errors
- Errors []CheckV0alpha1StatusReportErrors `json:"errors"`
+ // List of failures
+ Failures []CheckReportFailure `json:"failures"`
}
// NewCheckV0alpha1StatusReport creates a new CheckV0alpha1StatusReport object.
diff --git a/apps/advisor/pkg/apis/advisor/v0alpha1/checktype_codec_gen.go b/apps/advisor/pkg/apis/advisor/v0alpha1/checktype_codec_gen.go
new file mode 100644
index 00000000000..9881ce9d96f
--- /dev/null
+++ b/apps/advisor/pkg/apis/advisor/v0alpha1/checktype_codec_gen.go
@@ -0,0 +1,28 @@
+//
+// Code generated by grafana-app-sdk. DO NOT EDIT.
+//
+
+package v0alpha1
+
+import (
+ "encoding/json"
+ "io"
+
+ "github.com/grafana/grafana-app-sdk/resource"
+)
+
+// CheckTypeJSONCodec is an implementation of resource.Codec for kubernetes JSON encoding
+type CheckTypeJSONCodec struct{}
+
+// Read reads JSON-encoded bytes from `reader` and unmarshals them into `into`
+func (*CheckTypeJSONCodec) Read(reader io.Reader, into resource.Object) error {
+ return json.NewDecoder(reader).Decode(into)
+}
+
+// Write writes JSON-encoded bytes into `writer` marshaled from `from`
+func (*CheckTypeJSONCodec) Write(writer io.Writer, from resource.Object) error {
+ return json.NewEncoder(writer).Encode(from)
+}
+
+// Interface compliance checks
+var _ resource.Codec = &CheckTypeJSONCodec{}
diff --git a/apps/advisor/pkg/apis/advisor/v0alpha1/checktype_metadata_gen.go b/apps/advisor/pkg/apis/advisor/v0alpha1/checktype_metadata_gen.go
new file mode 100644
index 00000000000..9998cffb37d
--- /dev/null
+++ b/apps/advisor/pkg/apis/advisor/v0alpha1/checktype_metadata_gen.go
@@ -0,0 +1,28 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+package v0alpha1
+
+import (
+ time "time"
+)
+
+// metadata contains embedded CommonMetadata and can be extended with custom string fields
+// TODO: use CommonMetadata instead of redefining here; currently needs to be defined here
+// without external reference as using the CommonMetadata reference breaks thema codegen.
+type CheckTypeMetadata struct {
+ UpdateTimestamp time.Time `json:"updateTimestamp"`
+ CreatedBy string `json:"createdBy"`
+ Uid string `json:"uid"`
+ CreationTimestamp time.Time `json:"creationTimestamp"`
+ DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"`
+ Finalizers []string `json:"finalizers"`
+ ResourceVersion string `json:"resourceVersion"`
+ Generation int64 `json:"generation"`
+ UpdatedBy string `json:"updatedBy"`
+ Labels map[string]string `json:"labels"`
+}
+
+// NewCheckTypeMetadata creates a new CheckTypeMetadata object.
+func NewCheckTypeMetadata() *CheckTypeMetadata {
+ return &CheckTypeMetadata{}
+}
diff --git a/apps/advisor/pkg/apis/advisor/v0alpha1/checktype_object_gen.go b/apps/advisor/pkg/apis/advisor/v0alpha1/checktype_object_gen.go
new file mode 100644
index 00000000000..80bd02b1cc8
--- /dev/null
+++ b/apps/advisor/pkg/apis/advisor/v0alpha1/checktype_object_gen.go
@@ -0,0 +1,266 @@
+//
+// Code generated by grafana-app-sdk. DO NOT EDIT.
+//
+
+package v0alpha1
+
+import (
+ "fmt"
+ "github.com/grafana/grafana-app-sdk/resource"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/apimachinery/pkg/types"
+ "time"
+)
+
+// +k8s:openapi-gen=true
+type CheckType struct {
+ metav1.TypeMeta `json:",inline" yaml:",inline"`
+ metav1.ObjectMeta `json:"metadata" yaml:"metadata"`
+ Spec CheckTypeSpec `json:"spec" yaml:"spec"`
+ CheckTypeStatus CheckTypeStatus `json:"status" yaml:"status"`
+}
+
+func (o *CheckType) GetSpec() any {
+ return o.Spec
+}
+
+func (o *CheckType) SetSpec(spec any) error {
+ cast, ok := spec.(CheckTypeSpec)
+ if !ok {
+ return fmt.Errorf("cannot set spec type %#v, not of type Spec", spec)
+ }
+ o.Spec = cast
+ return nil
+}
+
+func (o *CheckType) GetSubresources() map[string]any {
+ return map[string]any{
+ "status": o.CheckTypeStatus,
+ }
+}
+
+func (o *CheckType) GetSubresource(name string) (any, bool) {
+ switch name {
+ case "status":
+ return o.CheckTypeStatus, true
+ default:
+ return nil, false
+ }
+}
+
+func (o *CheckType) SetSubresource(name string, value any) error {
+ switch name {
+ case "status":
+ cast, ok := value.(CheckTypeStatus)
+ if !ok {
+ return fmt.Errorf("cannot set status type %#v, not of type CheckTypeStatus", value)
+ }
+ o.CheckTypeStatus = cast
+ return nil
+ default:
+ return fmt.Errorf("subresource '%s' does not exist", name)
+ }
+}
+
+func (o *CheckType) GetStaticMetadata() resource.StaticMetadata {
+ gvk := o.GroupVersionKind()
+ return resource.StaticMetadata{
+ Name: o.ObjectMeta.Name,
+ Namespace: o.ObjectMeta.Namespace,
+ Group: gvk.Group,
+ Version: gvk.Version,
+ Kind: gvk.Kind,
+ }
+}
+
+func (o *CheckType) SetStaticMetadata(metadata resource.StaticMetadata) {
+ o.Name = metadata.Name
+ o.Namespace = metadata.Namespace
+ o.SetGroupVersionKind(schema.GroupVersionKind{
+ Group: metadata.Group,
+ Version: metadata.Version,
+ Kind: metadata.Kind,
+ })
+}
+
+func (o *CheckType) GetCommonMetadata() resource.CommonMetadata {
+ dt := o.DeletionTimestamp
+ var deletionTimestamp *time.Time
+ if dt != nil {
+ deletionTimestamp = &dt.Time
+ }
+ // Legacy ExtraFields support
+ extraFields := make(map[string]any)
+ if o.Annotations != nil {
+ extraFields["annotations"] = o.Annotations
+ }
+ if o.ManagedFields != nil {
+ extraFields["managedFields"] = o.ManagedFields
+ }
+ if o.OwnerReferences != nil {
+ extraFields["ownerReferences"] = o.OwnerReferences
+ }
+ return resource.CommonMetadata{
+ UID: string(o.UID),
+ ResourceVersion: o.ResourceVersion,
+ Generation: o.Generation,
+ Labels: o.Labels,
+ CreationTimestamp: o.CreationTimestamp.Time,
+ DeletionTimestamp: deletionTimestamp,
+ Finalizers: o.Finalizers,
+ UpdateTimestamp: o.GetUpdateTimestamp(),
+ CreatedBy: o.GetCreatedBy(),
+ UpdatedBy: o.GetUpdatedBy(),
+ ExtraFields: extraFields,
+ }
+}
+
+func (o *CheckType) SetCommonMetadata(metadata resource.CommonMetadata) {
+ o.UID = types.UID(metadata.UID)
+ o.ResourceVersion = metadata.ResourceVersion
+ o.Generation = metadata.Generation
+ o.Labels = metadata.Labels
+ o.CreationTimestamp = metav1.NewTime(metadata.CreationTimestamp)
+ if metadata.DeletionTimestamp != nil {
+ dt := metav1.NewTime(*metadata.DeletionTimestamp)
+ o.DeletionTimestamp = &dt
+ } else {
+ o.DeletionTimestamp = nil
+ }
+ o.Finalizers = metadata.Finalizers
+ if o.Annotations == nil {
+ o.Annotations = make(map[string]string)
+ }
+ if !metadata.UpdateTimestamp.IsZero() {
+ o.SetUpdateTimestamp(metadata.UpdateTimestamp)
+ }
+ if metadata.CreatedBy != "" {
+ o.SetCreatedBy(metadata.CreatedBy)
+ }
+ if metadata.UpdatedBy != "" {
+ o.SetUpdatedBy(metadata.UpdatedBy)
+ }
+ // Legacy support for setting Annotations, ManagedFields, and OwnerReferences via ExtraFields
+ if metadata.ExtraFields != nil {
+ if annotations, ok := metadata.ExtraFields["annotations"]; ok {
+ if cast, ok := annotations.(map[string]string); ok {
+ o.Annotations = cast
+ }
+ }
+ if managedFields, ok := metadata.ExtraFields["managedFields"]; ok {
+ if cast, ok := managedFields.([]metav1.ManagedFieldsEntry); ok {
+ o.ManagedFields = cast
+ }
+ }
+ if ownerReferences, ok := metadata.ExtraFields["ownerReferences"]; ok {
+ if cast, ok := ownerReferences.([]metav1.OwnerReference); ok {
+ o.OwnerReferences = cast
+ }
+ }
+ }
+}
+
+func (o *CheckType) GetCreatedBy() string {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ return o.ObjectMeta.Annotations["grafana.com/createdBy"]
+}
+
+func (o *CheckType) SetCreatedBy(createdBy string) {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ o.ObjectMeta.Annotations["grafana.com/createdBy"] = createdBy
+}
+
+func (o *CheckType) GetUpdateTimestamp() time.Time {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ parsed, _ := time.Parse(time.RFC3339, o.ObjectMeta.Annotations["grafana.com/updateTimestamp"])
+ return parsed
+}
+
+func (o *CheckType) SetUpdateTimestamp(updateTimestamp time.Time) {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ o.ObjectMeta.Annotations["grafana.com/updateTimestamp"] = updateTimestamp.Format(time.RFC3339)
+}
+
+func (o *CheckType) GetUpdatedBy() string {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ return o.ObjectMeta.Annotations["grafana.com/updatedBy"]
+}
+
+func (o *CheckType) SetUpdatedBy(updatedBy string) {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ o.ObjectMeta.Annotations["grafana.com/updatedBy"] = updatedBy
+}
+
+func (o *CheckType) Copy() resource.Object {
+ return resource.CopyObject(o)
+}
+
+func (o *CheckType) DeepCopyObject() runtime.Object {
+ return o.Copy()
+}
+
+// Interface compliance compile-time check
+var _ resource.Object = &CheckType{}
+
+// +k8s:openapi-gen=true
+type CheckTypeList struct {
+ metav1.TypeMeta `json:",inline" yaml:",inline"`
+ metav1.ListMeta `json:"metadata" yaml:"metadata"`
+ Items []CheckType `json:"items" yaml:"items"`
+}
+
+func (o *CheckTypeList) DeepCopyObject() runtime.Object {
+ return o.Copy()
+}
+
+func (o *CheckTypeList) Copy() resource.ListObject {
+ cpy := &CheckTypeList{
+ TypeMeta: o.TypeMeta,
+ Items: make([]CheckType, len(o.Items)),
+ }
+ o.ListMeta.DeepCopyInto(&cpy.ListMeta)
+ for i := 0; i < len(o.Items); i++ {
+ if item, ok := o.Items[i].Copy().(*CheckType); ok {
+ cpy.Items[i] = *item
+ }
+ }
+ return cpy
+}
+
+func (o *CheckTypeList) GetItems() []resource.Object {
+ items := make([]resource.Object, len(o.Items))
+ for i := 0; i < len(o.Items); i++ {
+ items[i] = &o.Items[i]
+ }
+ return items
+}
+
+func (o *CheckTypeList) SetItems(items []resource.Object) {
+ o.Items = make([]CheckType, len(items))
+ for i := 0; i < len(items); i++ {
+ o.Items[i] = *items[i].(*CheckType)
+ }
+}
+
+// Interface compliance compile-time check
+var _ resource.ListObject = &CheckTypeList{}
diff --git a/apps/advisor/pkg/apis/advisor/v0alpha1/checktype_schema_gen.go b/apps/advisor/pkg/apis/advisor/v0alpha1/checktype_schema_gen.go
new file mode 100644
index 00000000000..15b4a6fbb11
--- /dev/null
+++ b/apps/advisor/pkg/apis/advisor/v0alpha1/checktype_schema_gen.go
@@ -0,0 +1,34 @@
+//
+// Code generated by grafana-app-sdk. DO NOT EDIT.
+//
+
+package v0alpha1
+
+import (
+ "github.com/grafana/grafana-app-sdk/resource"
+)
+
+// schema is unexported to prevent accidental overwrites
+var (
+ schemaCheckType = resource.NewSimpleSchema("advisor.grafana.app", "v0alpha1", &CheckType{}, &CheckTypeList{}, resource.WithKind("CheckType"),
+ resource.WithPlural("checktypes"), resource.WithScope(resource.NamespacedScope))
+ kindCheckType = resource.Kind{
+ Schema: schemaCheckType,
+ Codecs: map[resource.KindEncoding]resource.Codec{
+ resource.KindEncodingJSON: &CheckTypeJSONCodec{},
+ },
+ }
+)
+
+// Kind returns a resource.Kind for this Schema with a JSON codec
+func CheckTypeKind() resource.Kind {
+ return kindCheckType
+}
+
+// Schema returns a resource.SimpleSchema representation of CheckType
+func CheckTypeSchema() *resource.SimpleSchema {
+ return schemaCheckType
+}
+
+// Interface compliance checks
+var _ resource.Schema = kindCheckType
diff --git a/apps/advisor/pkg/apis/advisor/v0alpha1/checktype_spec_gen.go b/apps/advisor/pkg/apis/advisor/v0alpha1/checktype_spec_gen.go
new file mode 100644
index 00000000000..528643b69dd
--- /dev/null
+++ b/apps/advisor/pkg/apis/advisor/v0alpha1/checktype_spec_gen.go
@@ -0,0 +1,27 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+package v0alpha1
+
+// +k8s:openapi-gen=true
+type CheckTypeStep struct {
+ Title string `json:"title"`
+ Description string `json:"description"`
+ StepID string `json:"stepID"`
+ Resolution string `json:"resolution"`
+}
+
+// NewCheckTypeStep creates a new CheckTypeStep object.
+func NewCheckTypeStep() *CheckTypeStep {
+ return &CheckTypeStep{}
+}
+
+// +k8s:openapi-gen=true
+type CheckTypeSpec struct {
+ Name string `json:"name"`
+ Steps []CheckTypeStep `json:"steps"`
+}
+
+// NewCheckTypeSpec creates a new CheckTypeSpec object.
+func NewCheckTypeSpec() *CheckTypeSpec {
+ return &CheckTypeSpec{}
+}
diff --git a/apps/advisor/pkg/apis/advisor/v0alpha1/checktype_status_gen.go b/apps/advisor/pkg/apis/advisor/v0alpha1/checktype_status_gen.go
new file mode 100644
index 00000000000..87db65316d0
--- /dev/null
+++ b/apps/advisor/pkg/apis/advisor/v0alpha1/checktype_status_gen.go
@@ -0,0 +1,44 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+package v0alpha1
+
+// +k8s:openapi-gen=true
+type CheckTypestatusOperatorState struct {
+ // lastEvaluation is the ResourceVersion last evaluated
+ LastEvaluation string `json:"lastEvaluation"`
+ // state describes the state of the lastEvaluation.
+ // It is limited to three possible states for machine evaluation.
+ State CheckTypeStatusOperatorStateState `json:"state"`
+ // descriptiveState is an optional more descriptive state field which has no requirements on format
+ DescriptiveState *string `json:"descriptiveState,omitempty"`
+ // details contains any extra information that is operator-specific
+ Details map[string]interface{} `json:"details,omitempty"`
+}
+
+// NewCheckTypestatusOperatorState creates a new CheckTypestatusOperatorState object.
+func NewCheckTypestatusOperatorState() *CheckTypestatusOperatorState {
+ return &CheckTypestatusOperatorState{}
+}
+
+// +k8s:openapi-gen=true
+type CheckTypeStatus struct {
+ // operatorStates is a map of operator ID to operator state evaluations.
+ // Any operator which consumes this kind SHOULD add its state evaluation information to this field.
+ OperatorStates map[string]CheckTypestatusOperatorState `json:"operatorStates,omitempty"`
+ // additionalFields is reserved for future use
+ AdditionalFields map[string]interface{} `json:"additionalFields,omitempty"`
+}
+
+// NewCheckTypeStatus creates a new CheckTypeStatus object.
+func NewCheckTypeStatus() *CheckTypeStatus {
+ return &CheckTypeStatus{}
+}
+
+// +k8s:openapi-gen=true
+type CheckTypeStatusOperatorStateState string
+
+const (
+ CheckTypeStatusOperatorStateStateSuccess CheckTypeStatusOperatorStateState = "success"
+ CheckTypeStatusOperatorStateStateInProgress CheckTypeStatusOperatorStateState = "in_progress"
+ CheckTypeStatusOperatorStateStateFailed CheckTypeStatusOperatorStateState = "failed"
+)
diff --git a/apps/advisor/pkg/apis/advisor/v0alpha1/zz_openapi_gen.go b/apps/advisor/pkg/apis/advisor/v0alpha1/zz_openapi_gen.go
index a78d033bb26..79d78cd2766 100644
--- a/apps/advisor/pkg/apis/advisor/v0alpha1/zz_openapi_gen.go
+++ b/apps/advisor/pkg/apis/advisor/v0alpha1/zz_openapi_gen.go
@@ -12,13 +12,20 @@ import (
func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
return map[string]common.OpenAPIDefinition{
- "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.Check": schema_pkg_apis_advisor_v0alpha1_Check(ref),
- "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckList": schema_pkg_apis_advisor_v0alpha1_CheckList(ref),
- "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckSpec": schema_pkg_apis_advisor_v0alpha1_CheckSpec(ref),
- "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckStatus": schema_pkg_apis_advisor_v0alpha1_CheckStatus(ref),
- "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckV0alpha1StatusReport": schema_pkg_apis_advisor_v0alpha1_CheckV0alpha1StatusReport(ref),
- "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckV0alpha1StatusReportErrors": schema_pkg_apis_advisor_v0alpha1_CheckV0alpha1StatusReportErrors(ref),
- "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckstatusOperatorState": schema_pkg_apis_advisor_v0alpha1_CheckstatusOperatorState(ref),
+ "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.Check": schema_pkg_apis_advisor_v0alpha1_Check(ref),
+ "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckErrorLink": schema_pkg_apis_advisor_v0alpha1_CheckErrorLink(ref),
+ "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckList": schema_pkg_apis_advisor_v0alpha1_CheckList(ref),
+ "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckReportFailure": schema_pkg_apis_advisor_v0alpha1_CheckReportFailure(ref),
+ "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckSpec": schema_pkg_apis_advisor_v0alpha1_CheckSpec(ref),
+ "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckStatus": schema_pkg_apis_advisor_v0alpha1_CheckStatus(ref),
+ "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckType": schema_pkg_apis_advisor_v0alpha1_CheckType(ref),
+ "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypeList": schema_pkg_apis_advisor_v0alpha1_CheckTypeList(ref),
+ "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypeSpec": schema_pkg_apis_advisor_v0alpha1_CheckTypeSpec(ref),
+ "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypeStatus": schema_pkg_apis_advisor_v0alpha1_CheckTypeStatus(ref),
+ "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypeStep": schema_pkg_apis_advisor_v0alpha1_CheckTypeStep(ref),
+ "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypestatusOperatorState": schema_pkg_apis_advisor_v0alpha1_CheckTypestatusOperatorState(ref),
+ "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckV0alpha1StatusReport": schema_pkg_apis_advisor_v0alpha1_CheckV0alpha1StatusReport(ref),
+ "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckstatusOperatorState": schema_pkg_apis_advisor_v0alpha1_CheckstatusOperatorState(ref),
}
}
@@ -69,6 +76,35 @@ func schema_pkg_apis_advisor_v0alpha1_Check(ref common.ReferenceCallback) common
}
}
+func schema_pkg_apis_advisor_v0alpha1_CheckErrorLink(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "url": {
+ SchemaProps: spec.SchemaProps{
+ Description: "URL to a page with more information about the error",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "message": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Human readable error message",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"url", "message"},
+ },
+ },
+ }
+}
+
func schema_pkg_apis_advisor_v0alpha1_CheckList(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
@@ -117,6 +153,59 @@ func schema_pkg_apis_advisor_v0alpha1_CheckList(ref common.ReferenceCallback) co
}
}
+func schema_pkg_apis_advisor_v0alpha1_CheckReportFailure(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "severity": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Severity of the failure",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "stepID": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Step ID that the failure is associated with",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "item": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Human readable identifier of the item that failed",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "links": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Links to actions that can be taken to resolve the failure",
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckErrorLink"),
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"severity", "stepID", "item", "links"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckErrorLink"},
+ }
+}
+
func schema_pkg_apis_advisor_v0alpha1_CheckSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
@@ -196,6 +285,272 @@ func schema_pkg_apis_advisor_v0alpha1_CheckStatus(ref common.ReferenceCallback)
}
}
+func schema_pkg_apis_advisor_v0alpha1_CheckType(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "apiVersion": {
+ SchemaProps: spec.SchemaProps{
+ Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "metadata": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"),
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypeSpec"),
+ },
+ },
+ "status": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypeStatus"),
+ },
+ },
+ },
+ Required: []string{"metadata", "spec", "status"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypeSpec", "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypeStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
+ }
+}
+
+func schema_pkg_apis_advisor_v0alpha1_CheckTypeList(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "apiVersion": {
+ SchemaProps: spec.SchemaProps{
+ Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "metadata": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"),
+ },
+ },
+ "items": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckType"),
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"metadata", "items"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckType", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
+ }
+}
+
+func schema_pkg_apis_advisor_v0alpha1_CheckTypeSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "name": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "steps": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypeStep"),
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"name", "steps"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypeStep"},
+ }
+}
+
+func schema_pkg_apis_advisor_v0alpha1_CheckTypeStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "operatorStates": {
+ SchemaProps: spec.SchemaProps{
+ Description: "operatorStates is a map of operator ID to operator state evaluations. Any operator which consumes this kind SHOULD add its state evaluation information to this field.",
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypestatusOperatorState"),
+ },
+ },
+ },
+ },
+ },
+ "additionalFields": {
+ SchemaProps: spec.SchemaProps{
+ Description: "additionalFields is reserved for future use",
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckTypestatusOperatorState"},
+ }
+}
+
+func schema_pkg_apis_advisor_v0alpha1_CheckTypeStep(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "title": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "description": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "stepID": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "resolution": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"title", "description", "stepID", "resolution"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_advisor_v0alpha1_CheckTypestatusOperatorState(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "lastEvaluation": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastEvaluation is the ResourceVersion last evaluated",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "state": {
+ SchemaProps: spec.SchemaProps{
+ Description: "state describes the state of the lastEvaluation. It is limited to three possible states for machine evaluation.",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "descriptiveState": {
+ SchemaProps: spec.SchemaProps{
+ Description: "descriptiveState is an optional more descriptive state field which has no requirements on format",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "details": {
+ SchemaProps: spec.SchemaProps{
+ Description: "details contains any extra information that is operator-specific",
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"lastEvaluation", "state"},
+ },
+ },
+ }
+}
+
func schema_pkg_apis_advisor_v0alpha1_CheckV0alpha1StatusReport(ref common.ReferenceCallback) common.OpenAPIDefinition {
return common.OpenAPIDefinition{
Schema: spec.Schema{
@@ -210,63 +565,26 @@ func schema_pkg_apis_advisor_v0alpha1_CheckV0alpha1StatusReport(ref common.Refer
Format: "int64",
},
},
- "errors": {
+ "failures": {
SchemaProps: spec.SchemaProps{
- Description: "List of errors",
+ Description: "List of failures",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Default: map[string]interface{}{},
- Ref: ref("github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckV0alpha1StatusReportErrors"),
+ Ref: ref("github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckReportFailure"),
},
},
},
},
},
},
- Required: []string{"count", "errors"},
+ Required: []string{"count", "failures"},
},
},
Dependencies: []string{
- "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckV0alpha1StatusReportErrors"},
- }
-}
-
-func schema_pkg_apis_advisor_v0alpha1_CheckV0alpha1StatusReportErrors(ref common.ReferenceCallback) common.OpenAPIDefinition {
- return common.OpenAPIDefinition{
- Schema: spec.Schema{
- SchemaProps: spec.SchemaProps{
- Type: []string{"object"},
- Properties: map[string]spec.Schema{
- "severity": {
- SchemaProps: spec.SchemaProps{
- Description: "Severity of the error",
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- "reason": {
- SchemaProps: spec.SchemaProps{
- Description: "Human readable reason for the error",
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- "action": {
- SchemaProps: spec.SchemaProps{
- Description: "Action to take to resolve the error",
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- },
- Required: []string{"severity", "reason", "action"},
- },
- },
+ "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1.CheckReportFailure"},
}
}
diff --git a/apps/advisor/pkg/apis/advisor_manifest.go b/apps/advisor/pkg/apis/advisor_manifest.go
index 2e8bb06fb65..e333774303f 100644
--- a/apps/advisor/pkg/apis/advisor_manifest.go
+++ b/apps/advisor/pkg/apis/advisor_manifest.go
@@ -12,9 +12,12 @@ import (
)
var (
- rawSchemaCheckv0alpha1 = []byte(`{"spec":{"properties":{"data":{"additionalProperties":{"type":"string"},"description":"Generic data input that a check can receive","type":"object"}},"type":"object"},"status":{"properties":{"additionalFields":{"description":"additionalFields is reserved for future use","type":"object","x-kubernetes-preserve-unknown-fields":true},"operatorStates":{"additionalProperties":{"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"description":"details contains any extra information that is operator-specific","type":"object","x-kubernetes-preserve-unknown-fields":true},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"},"report":{"properties":{"count":{"description":"Number of elements analyzed","type":"integer"},"errors":{"description":"List of errors","items":{"properties":{"action":{"description":"Action to take to resolve the error","type":"string"},"reason":{"description":"Human readable reason for the error","type":"string"},"severity":{"description":"Severity of the error","enum":["high","low"],"type":"string"}},"required":["severity","reason","action"],"type":"object"},"type":"array"}},"required":["count","errors"],"type":"object"}},"required":["report"],"type":"object","x-kubernetes-preserve-unknown-fields":true}}`)
- versionSchemaCheckv0alpha1 app.VersionSchema
- _ = json.Unmarshal(rawSchemaCheckv0alpha1, &versionSchemaCheckv0alpha1)
+ rawSchemaCheckv0alpha1 = []byte(`{"spec":{"properties":{"data":{"additionalProperties":{"type":"string"},"description":"Generic data input that a check can receive","type":"object"}},"type":"object"},"status":{"properties":{"additionalFields":{"description":"additionalFields is reserved for future use","type":"object","x-kubernetes-preserve-unknown-fields":true},"operatorStates":{"additionalProperties":{"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"description":"details contains any extra information that is operator-specific","type":"object","x-kubernetes-preserve-unknown-fields":true},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"},"report":{"properties":{"count":{"description":"Number of elements analyzed","type":"integer"},"failures":{"description":"List of failures","items":{"properties":{"item":{"description":"Human readable identifier of the item that failed","type":"string"},"links":{"description":"Links to actions that can be taken to resolve the failure","items":{"properties":{"message":{"description":"Human readable error message","type":"string"},"url":{"description":"URL to a page with more information about the error","type":"string"}},"required":["url","message"],"type":"object"},"type":"array"},"severity":{"description":"Severity of the failure","enum":["high","low"],"type":"string"},"stepID":{"description":"Step ID that the failure is associated with","type":"string"}},"required":["severity","stepID","item","links"],"type":"object"},"type":"array"}},"required":["count","failures"],"type":"object"}},"required":["report"],"type":"object","x-kubernetes-preserve-unknown-fields":true}}`)
+ versionSchemaCheckv0alpha1 app.VersionSchema
+ _ = json.Unmarshal(rawSchemaCheckv0alpha1, &versionSchemaCheckv0alpha1)
+ rawSchemaCheckTypev0alpha1 = []byte(`{"spec":{"properties":{"name":{"type":"string"},"steps":{"items":{"properties":{"description":{"type":"string"},"resolution":{"type":"string"},"stepID":{"type":"string"},"title":{"type":"string"}},"required":["title","description","stepID","resolution"],"type":"object"},"type":"array"}},"required":["name","steps"],"type":"object"},"status":{"properties":{"additionalFields":{"description":"additionalFields is reserved for future use","type":"object","x-kubernetes-preserve-unknown-fields":true},"operatorStates":{"additionalProperties":{"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"description":"details contains any extra information that is operator-specific","type":"object","x-kubernetes-preserve-unknown-fields":true},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object","x-kubernetes-preserve-unknown-fields":true}}`)
+ versionSchemaCheckTypev0alpha1 app.VersionSchema
+ _ = json.Unmarshal(rawSchemaCheckTypev0alpha1, &versionSchemaCheckTypev0alpha1)
)
var appManifestData = app.ManifestData{
@@ -27,11 +30,31 @@ var appManifestData = app.ManifestData{
Conversion: false,
Versions: []app.ManifestKindVersion{
{
- Name: "v0alpha1",
+ Name: "v0alpha1",
+ Admission: &app.AdmissionCapabilities{
+ Validation: &app.ValidationCapability{
+ Operations: []app.AdmissionOperation{
+ app.AdmissionOperationCreate,
+ app.AdmissionOperationUpdate,
+ },
+ },
+ },
Schema: &versionSchemaCheckv0alpha1,
},
},
},
+
+ {
+ Kind: "CheckType",
+ Scope: "Namespaced",
+ Conversion: false,
+ Versions: []app.ManifestKindVersion{
+ {
+ Name: "v0alpha1",
+ Schema: &versionSchemaCheckTypev0alpha1,
+ },
+ },
+ },
},
}
diff --git a/apps/advisor/pkg/app/app.go b/apps/advisor/pkg/app/app.go
index e4ccafbcaaf..efa9188f8e5 100644
--- a/apps/advisor/pkg/app/app.go
+++ b/apps/advisor/pkg/app/app.go
@@ -2,16 +2,49 @@ package app
import (
"context"
+ "fmt"
"github.com/grafana/grafana-app-sdk/app"
+ "github.com/grafana/grafana-app-sdk/k8s"
"github.com/grafana/grafana-app-sdk/resource"
"github.com/grafana/grafana-app-sdk/simple"
advisorv0alpha1 "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
+ "github.com/grafana/grafana/apps/advisor/pkg/app/checkregistry"
+ "github.com/grafana/grafana/apps/advisor/pkg/app/checks"
+ "github.com/grafana/grafana/apps/advisor/pkg/app/checkscheduler"
+ "github.com/grafana/grafana/apps/advisor/pkg/app/checktyperegisterer"
+ "github.com/grafana/grafana/pkg/infra/log"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/klog/v2"
)
func New(cfg app.Config) (app.App, error) {
+ // Read config
+ specificConfig, ok := cfg.SpecificConfig.(checkregistry.AdvisorAppConfig)
+ if !ok {
+ return nil, fmt.Errorf("invalid config type")
+ }
+ checkRegistry := specificConfig.CheckRegistry
+ stackID := specificConfig.StackID
+ namespace, err := checks.GetNamespace(stackID)
+ if err != nil {
+ return nil, err
+ }
+ log := log.New("advisor.app")
+
+ // Prepare storage client
+ clientGenerator := k8s.NewClientRegistry(cfg.KubeConfig, k8s.ClientConfig{})
+ client, err := clientGenerator.ClientFor(advisorv0alpha1.CheckKind())
+ if err != nil {
+ return nil, err
+ }
+
+ // Initialize checks
+ checkMap := map[string]checks.Check{}
+ for _, c := range checkRegistry.Checks() {
+ checkMap[c.ID()] = c
+ }
+
simpleConfig := simple.AppConfig{
Name: "advisor",
KubeConfig: cfg.KubeConfig,
@@ -23,6 +56,34 @@ func New(cfg app.Config) (app.App, error) {
ManagedKinds: []simple.AppManagedKind{
{
Kind: advisorv0alpha1.CheckKind(),
+ Validator: &simple.Validator{
+ ValidateFunc: func(ctx context.Context, req *app.AdmissionRequest) error {
+ if req.Object != nil {
+ _, err := getCheck(req.Object, checkMap)
+ return err
+ }
+ return nil
+ },
+ },
+ Watcher: &simple.Watcher{
+ AddFunc: func(ctx context.Context, obj resource.Object) error {
+ log.Debug("Adding check", "namespace", obj.GetNamespace())
+ if obj.GetNamespace() != namespace {
+ log.Debug("Skipping check in namespace", "namespace", obj.GetNamespace())
+ return nil
+ } else {
+ log.Debug("Processing check in namespace", "namespace", obj.GetNamespace())
+ }
+ check, err := getCheck(obj, checkMap)
+ if err != nil {
+ return err
+ }
+ return processCheck(ctx, client, obj, check)
+ },
+ },
+ },
+ {
+ Kind: advisorv0alpha1.CheckTypeKind(),
},
},
}
@@ -37,6 +98,20 @@ func New(cfg app.Config) (app.App, error) {
return nil, err
}
+ // Save check types as resources
+ ctr, err := checktyperegisterer.New(cfg)
+ if err != nil {
+ return nil, err
+ }
+ a.AddRunnable(ctr)
+
+ // Start scheduler
+ csch, err := checkscheduler.New(cfg)
+ if err != nil {
+ return nil, err
+ }
+ a.AddRunnable(csch)
+
return a, nil
}
@@ -49,6 +124,7 @@ func GetKinds() map[schema.GroupVersion][]resource.Kind {
return map[schema.GroupVersion][]resource.Kind{
gv: {
advisorv0alpha1.CheckKind(),
+ advisorv0alpha1.CheckTypeKind(),
},
}
}
diff --git a/apps/advisor/pkg/app/authorizer.go b/apps/advisor/pkg/app/authorizer.go
new file mode 100644
index 00000000000..4d216ee9edd
--- /dev/null
+++ b/apps/advisor/pkg/app/authorizer.go
@@ -0,0 +1,31 @@
+package app
+
+import (
+ "context"
+
+ "github.com/grafana/grafana/pkg/apimachinery/identity"
+ "k8s.io/apiserver/pkg/authorization/authorizer"
+)
+
+func GetAuthorizer() authorizer.Authorizer {
+ return authorizer.AuthorizerFunc(func(
+ ctx context.Context, attr authorizer.Attributes,
+ ) (authorized authorizer.Decision, reason string, err error) {
+ if !attr.IsResourceRequest() {
+ return authorizer.DecisionNoOpinion, "", nil
+ }
+
+ // require a user
+ u, err := identity.GetRequester(ctx)
+ if err != nil {
+ return authorizer.DecisionDeny, "valid user is required", err
+ }
+
+ // check if is admin
+ if u.HasRole(identity.RoleAdmin) {
+ return authorizer.DecisionAllow, "", nil
+ }
+
+ return authorizer.DecisionDeny, "forbidden", nil
+ })
+}
diff --git a/apps/advisor/pkg/app/authorizer_test.go b/apps/advisor/pkg/app/authorizer_test.go
new file mode 100644
index 00000000000..1384176969e
--- /dev/null
+++ b/apps/advisor/pkg/app/authorizer_test.go
@@ -0,0 +1,82 @@
+package app
+
+import (
+ "context"
+ "testing"
+
+ "github.com/grafana/grafana/pkg/apimachinery/identity"
+ "github.com/stretchr/testify/assert"
+ "k8s.io/apiserver/pkg/authorization/authorizer"
+)
+
+func TestGetAuthorizer(t *testing.T) {
+ tests := []struct {
+ name string
+ ctx context.Context
+ attr authorizer.Attributes
+ expectedDecision authorizer.Decision
+ expectedReason string
+ expectedErr error
+ }{
+ {
+ name: "non-resource request",
+ ctx: context.TODO(),
+ attr: &mockAttributes{resourceRequest: false},
+ expectedDecision: authorizer.DecisionNoOpinion,
+ expectedReason: "",
+ expectedErr: nil,
+ },
+ {
+ name: "user is admin",
+ ctx: identity.WithRequester(context.TODO(), &mockUser{isGrafanaAdmin: true}),
+ attr: &mockAttributes{resourceRequest: true},
+ expectedDecision: authorizer.DecisionAllow,
+ expectedReason: "",
+ expectedErr: nil,
+ },
+ {
+ name: "user is not admin",
+ ctx: identity.WithRequester(context.TODO(), &mockUser{isGrafanaAdmin: false}),
+ attr: &mockAttributes{resourceRequest: true},
+ expectedDecision: authorizer.DecisionDeny,
+ expectedReason: "forbidden",
+ expectedErr: nil,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ auth := GetAuthorizer()
+ decision, reason, err := auth.Authorize(tt.ctx, tt.attr)
+ assert.Equal(t, tt.expectedDecision, decision)
+ assert.Equal(t, tt.expectedReason, reason)
+ assert.Equal(t, tt.expectedErr, err)
+ })
+ }
+}
+
+type mockAttributes struct {
+ authorizer.Attributes
+ resourceRequest bool
+}
+
+func (m *mockAttributes) IsResourceRequest() bool {
+ return m.resourceRequest
+}
+
+// Implement other methods of authorizer.Attributes as needed
+
+type mockUser struct {
+ identity.Requester
+ isGrafanaAdmin bool
+}
+
+func (m *mockUser) GetIsGrafanaAdmin() bool {
+ return m.isGrafanaAdmin
+}
+
+func (m *mockUser) HasRole(role identity.RoleType) bool {
+ return role == identity.RoleAdmin && m.isGrafanaAdmin
+}
+
+// Implement other methods of identity.Requester as needed
diff --git a/apps/advisor/pkg/app/checkregistry/checkregistry.go b/apps/advisor/pkg/app/checkregistry/checkregistry.go
new file mode 100644
index 00000000000..335b9cc7567
--- /dev/null
+++ b/apps/advisor/pkg/app/checkregistry/checkregistry.go
@@ -0,0 +1,66 @@
+package checkregistry
+
+import (
+ "github.com/grafana/grafana/apps/advisor/pkg/app/checks"
+ "github.com/grafana/grafana/apps/advisor/pkg/app/checks/datasourcecheck"
+ "github.com/grafana/grafana/apps/advisor/pkg/app/checks/plugincheck"
+ "github.com/grafana/grafana/pkg/plugins"
+ "github.com/grafana/grafana/pkg/plugins/repo"
+ "github.com/grafana/grafana/pkg/services/datasources"
+ "github.com/grafana/grafana/pkg/services/pluginsintegration/managedplugins"
+ "github.com/grafana/grafana/pkg/services/pluginsintegration/plugincontext"
+ "github.com/grafana/grafana/pkg/services/pluginsintegration/plugininstaller"
+ "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
+)
+
+type CheckService interface {
+ Checks() []checks.Check
+}
+
+type Service struct {
+ datasourceSvc datasources.DataSourceService
+ pluginStore pluginstore.Store
+ pluginContextProvider *plugincontext.Provider
+ pluginClient plugins.Client
+ pluginRepo repo.Service
+ pluginPreinstall plugininstaller.Preinstall
+ managedPlugins managedplugins.Manager
+}
+
+func ProvideService(datasourceSvc datasources.DataSourceService, pluginStore pluginstore.Store,
+ pluginContextProvider *plugincontext.Provider, pluginClient plugins.Client,
+ pluginRepo repo.Service, pluginPreinstall plugininstaller.Preinstall, managedPlugins managedplugins.Manager) *Service {
+ return &Service{
+ datasourceSvc: datasourceSvc,
+ pluginStore: pluginStore,
+ pluginContextProvider: pluginContextProvider,
+ pluginClient: pluginClient,
+ pluginRepo: pluginRepo,
+ pluginPreinstall: pluginPreinstall,
+ managedPlugins: managedPlugins,
+ }
+}
+
+func (s *Service) Checks() []checks.Check {
+ return []checks.Check{
+ datasourcecheck.New(
+ s.datasourceSvc,
+ s.pluginStore,
+ s.pluginContextProvider,
+ s.pluginClient,
+ ),
+ plugincheck.New(
+ s.pluginStore,
+ s.pluginRepo,
+ s.pluginPreinstall,
+ s.managedPlugins,
+ ),
+ }
+}
+
+// AdvisorAppConfig is the configuration received from Grafana to run the app
+type AdvisorAppConfig struct {
+ CheckRegistry CheckService
+ PluginConfig map[string]string
+ StackID string
+}
diff --git a/apps/advisor/pkg/app/checks/datasourcecheck/check.go b/apps/advisor/pkg/app/checks/datasourcecheck/check.go
new file mode 100644
index 00000000000..0cdac81e4b8
--- /dev/null
+++ b/apps/advisor/pkg/app/checks/datasourcecheck/check.go
@@ -0,0 +1,177 @@
+package datasourcecheck
+
+import (
+ "context"
+ "errors"
+ "fmt"
+
+ "github.com/grafana/grafana-plugin-sdk-go/backend"
+ advisor "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
+ "github.com/grafana/grafana/apps/advisor/pkg/app/checks"
+ "github.com/grafana/grafana/pkg/apimachinery/identity"
+ "github.com/grafana/grafana/pkg/infra/log"
+ "github.com/grafana/grafana/pkg/plugins"
+ "github.com/grafana/grafana/pkg/services/datasources"
+ "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
+ "github.com/grafana/grafana/pkg/util"
+)
+
+type check struct {
+ DatasourceSvc datasources.DataSourceService
+ PluginStore pluginstore.Store
+ PluginContextProvider pluginContextProvider
+ PluginClient plugins.Client
+ log log.Logger
+}
+
+func New(
+ datasourceSvc datasources.DataSourceService,
+ pluginStore pluginstore.Store,
+ pluginContextProvider pluginContextProvider,
+ pluginClient plugins.Client,
+) checks.Check {
+ return &check{
+ DatasourceSvc: datasourceSvc,
+ PluginStore: pluginStore,
+ PluginContextProvider: pluginContextProvider,
+ PluginClient: pluginClient,
+ log: log.New("advisor.datasourcecheck"),
+ }
+}
+
+func (c *check) Items(ctx context.Context) ([]any, error) {
+ dss, err := c.DatasourceSvc.GetAllDataSources(ctx, &datasources.GetAllDataSourcesQuery{})
+ if err != nil {
+ return nil, err
+ }
+ res := make([]any, len(dss))
+ for i, ds := range dss {
+ res[i] = ds
+ }
+ return res, nil
+}
+
+func (c *check) ID() string {
+ return "datasource"
+}
+
+func (c *check) Steps() []checks.Step {
+ return []checks.Step{
+ &uidValidationStep{},
+ &healthCheckStep{
+ PluginContextProvider: c.PluginContextProvider,
+ PluginClient: c.PluginClient,
+ log: c.log,
+ },
+ }
+}
+
+type uidValidationStep struct{}
+
+func (s *uidValidationStep) ID() string {
+ return "uid-validation"
+}
+
+func (s *uidValidationStep) Title() string {
+ return "UID validation"
+}
+
+func (s *uidValidationStep) Description() string {
+ return "Checks if the UID of a data source is valid."
+}
+
+func (s *uidValidationStep) Resolution() string {
+ return "Check the documentation for more information or delete the data source and create a new one."
+}
+
+func (s *uidValidationStep) Run(ctx context.Context, obj *advisor.CheckSpec, i any) (*advisor.CheckReportFailure, error) {
+ ds, ok := i.(*datasources.DataSource)
+ if !ok {
+ return nil, fmt.Errorf("invalid item type %T", i)
+ }
+ // Data source UID validation
+ err := util.ValidateUID(ds.UID)
+ if err != nil {
+ return checks.NewCheckReportFailure(
+ advisor.CheckReportFailureSeverityLow,
+ s.ID(),
+ fmt.Sprintf("%s (%s)", ds.Name, ds.UID),
+ []advisor.CheckErrorLink{},
+ ), nil
+ }
+ return nil, nil
+}
+
+type healthCheckStep struct {
+ PluginContextProvider pluginContextProvider
+ PluginClient plugins.Client
+ log log.Logger
+}
+
+func (s *healthCheckStep) Title() string {
+ return "Health check"
+}
+
+func (s *healthCheckStep) Description() string {
+ return "Checks if a data sources is healthy."
+}
+
+func (s *healthCheckStep) Resolution() string {
+ return "Go to the data source configuration page and address the issues reported."
+}
+
+func (s *healthCheckStep) ID() string {
+ return "health-check"
+}
+
+func (s *healthCheckStep) Run(ctx context.Context, obj *advisor.CheckSpec, i any) (*advisor.CheckReportFailure, error) {
+ ds, ok := i.(*datasources.DataSource)
+ if !ok {
+ return nil, fmt.Errorf("invalid item type %T", i)
+ }
+
+ // Health check execution
+ requester, err := identity.GetRequester(ctx)
+ if err != nil {
+ return nil, err
+ }
+ pCtx, err := s.PluginContextProvider.GetWithDataSource(ctx, ds.Type, requester, ds)
+ if err != nil {
+ // Unable to check health check
+ s.log.Error("Failed to get plugin context", "datasource_uid", ds.UID, "error", err)
+ return nil, nil
+ }
+ req := &backend.CheckHealthRequest{
+ PluginContext: pCtx,
+ Headers: map[string]string{},
+ }
+ resp, err := s.PluginClient.CheckHealth(ctx, req)
+ if err != nil || resp.Status != backend.HealthStatusOk {
+ if err != nil {
+ s.log.Debug("Failed to check health", "datasource_uid", ds.UID, "error", err)
+ if errors.Is(err, plugins.ErrMethodNotImplemented) || errors.Is(err, plugins.ErrPluginUnavailable) {
+ // The plugin does not support backend health checks
+ return nil, nil
+ }
+ } else {
+ s.log.Debug("Failed to check health", "datasource_uid", ds.UID, "status", resp.Status, "message", resp.Message)
+ }
+ return checks.NewCheckReportFailure(
+ advisor.CheckReportFailureSeverityHigh,
+ s.ID(),
+ ds.Name,
+ []advisor.CheckErrorLink{
+ {
+ Message: "Fix me",
+ Url: fmt.Sprintf("/connections/datasources/edit/%s", ds.UID),
+ },
+ },
+ ), nil
+ }
+ return nil, nil
+}
+
+type pluginContextProvider interface {
+ GetWithDataSource(ctx context.Context, pluginID string, user identity.Requester, ds *datasources.DataSource) (backend.PluginContext, error)
+}
diff --git a/apps/advisor/pkg/app/checks/datasourcecheck/check_test.go b/apps/advisor/pkg/app/checks/datasourcecheck/check_test.go
new file mode 100644
index 00000000000..ee8a991555d
--- /dev/null
+++ b/apps/advisor/pkg/app/checks/datasourcecheck/check_test.go
@@ -0,0 +1,188 @@
+package datasourcecheck
+
+import (
+ "context"
+ "testing"
+
+ "github.com/grafana/grafana-plugin-sdk-go/backend"
+ advisor "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
+ "github.com/grafana/grafana/pkg/apimachinery/identity"
+ "github.com/grafana/grafana/pkg/infra/log"
+ "github.com/grafana/grafana/pkg/plugins"
+ "github.com/grafana/grafana/pkg/services/datasources"
+ "github.com/grafana/grafana/pkg/services/user"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestCheck_Run(t *testing.T) {
+ t.Run("should return no failures when all datasources are healthy", func(t *testing.T) {
+ datasources := []*datasources.DataSource{
+ {UID: "valid-uid-1", Type: "prometheus", Name: "Prometheus"},
+ {UID: "valid-uid-2", Type: "mysql", Name: "MySQL"},
+ }
+
+ mockDatasourceSvc := &MockDatasourceSvc{dss: datasources}
+ mockPluginContextProvider := &MockPluginContextProvider{pCtx: backend.PluginContext{}}
+ mockPluginClient := &MockPluginClient{res: &backend.CheckHealthResult{Status: backend.HealthStatusOk}}
+
+ check := &check{
+ DatasourceSvc: mockDatasourceSvc,
+ PluginContextProvider: mockPluginContextProvider,
+ PluginClient: mockPluginClient,
+ log: log.New("advisor.datasourcecheck"),
+ }
+
+ ctx := identity.WithRequester(context.Background(), &user.SignedInUser{})
+ items, err := check.Items(ctx)
+ assert.NoError(t, err)
+ failures := []advisor.CheckReportFailure{}
+ for _, step := range check.Steps() {
+ for _, item := range items {
+ stepFailures, err := step.Run(ctx, &advisor.CheckSpec{}, item)
+ assert.NoError(t, err)
+ if stepFailures != nil {
+ failures = append(failures, *stepFailures)
+ }
+ }
+ }
+
+ assert.NoError(t, err)
+ assert.Equal(t, 2, len(items))
+ assert.Empty(t, failures)
+ })
+
+ t.Run("should return failures when datasource UID is invalid", func(t *testing.T) {
+ datasources := []*datasources.DataSource{
+ {UID: "invalid uid", Type: "prometheus", Name: "Prometheus"},
+ }
+
+ mockDatasourceSvc := &MockDatasourceSvc{dss: datasources}
+ mockPluginContextProvider := &MockPluginContextProvider{pCtx: backend.PluginContext{}}
+ mockPluginClient := &MockPluginClient{res: &backend.CheckHealthResult{Status: backend.HealthStatusOk}}
+
+ check := &check{
+ DatasourceSvc: mockDatasourceSvc,
+ PluginContextProvider: mockPluginContextProvider,
+ PluginClient: mockPluginClient,
+ log: log.New("advisor.datasourcecheck"),
+ }
+
+ ctx := identity.WithRequester(context.Background(), &user.SignedInUser{})
+ items, err := check.Items(ctx)
+ assert.NoError(t, err)
+ failures := []advisor.CheckReportFailure{}
+ for _, step := range check.Steps() {
+ for _, item := range items {
+ stepFailures, err := step.Run(ctx, &advisor.CheckSpec{}, item)
+ assert.NoError(t, err)
+ if stepFailures != nil {
+ failures = append(failures, *stepFailures)
+ }
+ }
+ }
+
+ assert.NoError(t, err)
+ assert.Equal(t, 1, len(items))
+ assert.Len(t, failures, 1)
+ assert.Equal(t, "uid-validation", failures[0].StepID)
+ })
+
+ t.Run("should return failures when datasource health check fails", func(t *testing.T) {
+ datasources := []*datasources.DataSource{
+ {UID: "valid-uid-1", Type: "prometheus", Name: "Prometheus"},
+ }
+
+ mockDatasourceSvc := &MockDatasourceSvc{dss: datasources}
+ mockPluginContextProvider := &MockPluginContextProvider{pCtx: backend.PluginContext{}}
+ mockPluginClient := &MockPluginClient{res: &backend.CheckHealthResult{Status: backend.HealthStatusError}}
+
+ check := &check{
+ DatasourceSvc: mockDatasourceSvc,
+ PluginContextProvider: mockPluginContextProvider,
+ PluginClient: mockPluginClient,
+ log: log.New("advisor.datasourcecheck"),
+ }
+
+ ctx := identity.WithRequester(context.Background(), &user.SignedInUser{})
+ items, err := check.Items(ctx)
+ assert.NoError(t, err)
+ failures := []advisor.CheckReportFailure{}
+ for _, step := range check.Steps() {
+ for _, item := range items {
+ stepFailures, err := step.Run(ctx, &advisor.CheckSpec{}, item)
+ assert.NoError(t, err)
+ if stepFailures != nil {
+ failures = append(failures, *stepFailures)
+ }
+ }
+ }
+
+ assert.NoError(t, err)
+ assert.Equal(t, 1, len(items))
+ assert.Len(t, failures, 1)
+ assert.Equal(t, "health-check", failures[0].StepID)
+ })
+
+ t.Run("should skip health check when plugin does not support backend health checks", func(t *testing.T) {
+ datasources := []*datasources.DataSource{
+ {UID: "valid-uid-1", Type: "prometheus", Name: "Prometheus"},
+ }
+ mockDatasourceSvc := &MockDatasourceSvc{dss: datasources}
+ mockPluginContextProvider := &MockPluginContextProvider{pCtx: backend.PluginContext{}}
+ mockPluginClient := &MockPluginClient{err: plugins.ErrMethodNotImplemented}
+
+ check := &check{
+ DatasourceSvc: mockDatasourceSvc,
+ PluginContextProvider: mockPluginContextProvider,
+ PluginClient: mockPluginClient,
+ log: log.New("advisor.datasourcecheck"),
+ }
+
+ ctx := identity.WithRequester(context.Background(), &user.SignedInUser{})
+ items, err := check.Items(ctx)
+ assert.NoError(t, err)
+ failures := []advisor.CheckReportFailure{}
+ for _, step := range check.Steps() {
+ for _, item := range items {
+ stepFailures, err := step.Run(ctx, &advisor.CheckSpec{}, item)
+ assert.NoError(t, err)
+ if stepFailures != nil {
+ failures = append(failures, *stepFailures)
+ }
+ }
+ }
+
+ assert.NoError(t, err)
+ assert.Equal(t, 1, len(items))
+ assert.Len(t, failures, 0)
+ })
+}
+
+type MockDatasourceSvc struct {
+ datasources.DataSourceService
+
+ dss []*datasources.DataSource
+}
+
+func (m *MockDatasourceSvc) GetAllDataSources(ctx context.Context, query *datasources.GetAllDataSourcesQuery) ([]*datasources.DataSource, error) {
+ return m.dss, nil
+}
+
+type MockPluginContextProvider struct {
+ pCtx backend.PluginContext
+}
+
+func (m *MockPluginContextProvider) GetWithDataSource(ctx context.Context, pluginID string, user identity.Requester, ds *datasources.DataSource) (backend.PluginContext, error) {
+ return m.pCtx, nil
+}
+
+type MockPluginClient struct {
+ plugins.Client
+
+ res *backend.CheckHealthResult
+ err error
+}
+
+func (m *MockPluginClient) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
+ return m.res, m.err
+}
diff --git a/apps/advisor/pkg/app/checks/ifaces.go b/apps/advisor/pkg/app/checks/ifaces.go
new file mode 100644
index 00000000000..31456599381
--- /dev/null
+++ b/apps/advisor/pkg/app/checks/ifaces.go
@@ -0,0 +1,31 @@
+package checks
+
+import (
+ "context"
+
+ advisorv0alpha1 "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
+)
+
+// Check returns metadata about the check being executed and the list of Steps
+type Check interface {
+ // ID returns the unique identifier of the check
+ ID() string
+ // Items returns the list of items that will be checked
+ Items(ctx context.Context) ([]any, error)
+ // Steps returns the list of steps that will be executed
+ Steps() []Step
+}
+
+// Step is a single step in a check, including its metadata
+type Step interface {
+ // ID returns the unique identifier of the step
+ ID() string
+ // Title returns the title of the step
+ Title() string
+ // Description returns the description of the step
+ Description() string
+ // Explains the action that needs to be taken to resolve the issue
+ Resolution() string
+ // Run executes the step for an item and returns a report
+ Run(ctx context.Context, obj *advisorv0alpha1.CheckSpec, item any) (*advisorv0alpha1.CheckReportFailure, error)
+}
diff --git a/apps/advisor/pkg/app/checks/plugincheck/check.go b/apps/advisor/pkg/app/checks/plugincheck/check.go
new file mode 100644
index 00000000000..45c54d4fdc0
--- /dev/null
+++ b/apps/advisor/pkg/app/checks/plugincheck/check.go
@@ -0,0 +1,199 @@
+package plugincheck
+
+import (
+ "context"
+ "fmt"
+ sysruntime "runtime"
+
+ "github.com/Masterminds/semver/v3"
+ advisor "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
+ "github.com/grafana/grafana/apps/advisor/pkg/app/checks"
+ "github.com/grafana/grafana/pkg/cmd/grafana-cli/services"
+ "github.com/grafana/grafana/pkg/plugins/repo"
+ "github.com/grafana/grafana/pkg/services/pluginsintegration/managedplugins"
+ "github.com/grafana/grafana/pkg/services/pluginsintegration/plugininstaller"
+ "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
+)
+
+func New(
+ pluginStore pluginstore.Store,
+ pluginRepo repo.Service,
+ pluginPreinstall plugininstaller.Preinstall,
+ managedPlugins managedplugins.Manager,
+) checks.Check {
+ return &check{
+ PluginStore: pluginStore,
+ PluginRepo: pluginRepo,
+ PluginPreinstall: pluginPreinstall,
+ ManagedPlugins: managedPlugins,
+ }
+}
+
+type check struct {
+ PluginStore pluginstore.Store
+ PluginRepo repo.Service
+ PluginPreinstall plugininstaller.Preinstall
+ ManagedPlugins managedplugins.Manager
+}
+
+func (c *check) ID() string {
+ return "plugin"
+}
+
+func (c *check) Items(ctx context.Context) ([]any, error) {
+ ps := c.PluginStore.Plugins(ctx)
+ res := make([]any, len(ps))
+ for i, p := range ps {
+ res[i] = p
+ }
+ return res, nil
+}
+
+func (c *check) Steps() []checks.Step {
+ return []checks.Step{
+ &deprecationStep{
+ PluginRepo: c.PluginRepo,
+ },
+ &updateStep{
+ PluginRepo: c.PluginRepo,
+ PluginPreinstall: c.PluginPreinstall,
+ ManagedPlugins: c.ManagedPlugins,
+ },
+ }
+}
+
+type deprecationStep struct {
+ PluginRepo repo.Service
+}
+
+func (s *deprecationStep) Title() string {
+ return "Deprecation check"
+}
+
+func (s *deprecationStep) Description() string {
+ return "Check if any installed plugins are deprecated."
+}
+
+func (s *deprecationStep) Resolution() string {
+ return "Check the documentation for recommended steps or delete the plugin."
+}
+
+func (s *deprecationStep) ID() string {
+ return "deprecation"
+}
+
+func (s *deprecationStep) Run(ctx context.Context, _ *advisor.CheckSpec, it any) (*advisor.CheckReportFailure, error) {
+ p, ok := it.(pluginstore.Plugin)
+ if !ok {
+ return nil, fmt.Errorf("invalid item type %T", it)
+ }
+
+ // Skip if it's a core plugin
+ if p.IsCorePlugin() {
+ return nil, nil
+ }
+
+ // Check if plugin is deprecated
+ i, err := s.PluginRepo.PluginInfo(ctx, p.ID)
+ if err != nil {
+ // Unable to check deprecation status
+ return nil, nil
+ }
+ if i.Status == "deprecated" {
+ return checks.NewCheckReportFailure(
+ advisor.CheckReportFailureSeverityHigh,
+ s.ID(),
+ p.ID,
+ []advisor.CheckErrorLink{
+ {
+ Message: "Admin",
+ Url: fmt.Sprintf("/plugins/%s", p.ID),
+ },
+ },
+ ), nil
+ }
+ return nil, nil
+}
+
+type updateStep struct {
+ PluginRepo repo.Service
+ PluginPreinstall plugininstaller.Preinstall
+ ManagedPlugins managedplugins.Manager
+}
+
+func (s *updateStep) Title() string {
+ return "Update check"
+}
+
+func (s *updateStep) Description() string {
+ return "Checks if an installed plugins has a newer version available."
+}
+
+func (s *updateStep) Resolution() string {
+ return "Go to the plugin admin page and upgrade to the latest version."
+}
+
+func (s *updateStep) ID() string {
+ return "update"
+}
+
+func (s *updateStep) Run(ctx context.Context, _ *advisor.CheckSpec, i any) (*advisor.CheckReportFailure, error) {
+ p, ok := i.(pluginstore.Plugin)
+ if !ok {
+ return nil, fmt.Errorf("invalid item type %T", i)
+ }
+
+ // Skip if it's a core plugin
+ if p.IsCorePlugin() {
+ return nil, nil
+ }
+
+ // Skip if it's managed or pinned
+ if s.isManaged(ctx, p.ID) || s.PluginPreinstall.IsPinned(p.ID) {
+ return nil, nil
+ }
+
+ // Check if plugin has a newer version available
+ compatOpts := repo.NewCompatOpts(services.GrafanaVersion, sysruntime.GOOS, sysruntime.GOARCH)
+ info, err := s.PluginRepo.GetPluginArchiveInfo(ctx, p.ID, "", compatOpts)
+ if err != nil {
+ // Unable to check updates
+ return nil, nil
+ }
+ if hasUpdate(p, info) {
+ return checks.NewCheckReportFailure(
+ advisor.CheckReportFailureSeverityLow,
+ s.ID(),
+ p.ID,
+ []advisor.CheckErrorLink{
+ {
+ Message: "Upgrade",
+ Url: fmt.Sprintf("/plugins/%s?page=version-history", p.ID),
+ },
+ },
+ ), nil
+ }
+
+ return nil, nil
+}
+
+func hasUpdate(current pluginstore.Plugin, latest *repo.PluginArchiveInfo) bool {
+ // If both versions are semver-valid, compare them
+ v1, err1 := semver.NewVersion(current.Info.Version)
+ v2, err2 := semver.NewVersion(latest.Version)
+ if err1 == nil && err2 == nil {
+ return v1.LessThan(v2)
+ }
+ // In other case, assume that a different latest version will always be newer
+ return current.Info.Version != latest.Version
+}
+
+func (s *updateStep) isManaged(ctx context.Context, pluginID string) bool {
+ for _, managedPlugin := range s.ManagedPlugins.ManagedPlugins(ctx) {
+ if managedPlugin == pluginID {
+ return true
+ }
+ }
+ return false
+}
diff --git a/apps/advisor/pkg/app/checks/plugincheck/check_test.go b/apps/advisor/pkg/app/checks/plugincheck/check_test.go
new file mode 100644
index 00000000000..13b2a17ea1b
--- /dev/null
+++ b/apps/advisor/pkg/app/checks/plugincheck/check_test.go
@@ -0,0 +1,210 @@
+package plugincheck
+
+import (
+ "context"
+ "testing"
+
+ advisor "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
+ "github.com/grafana/grafana/pkg/plugins"
+ "github.com/grafana/grafana/pkg/plugins/repo"
+ "github.com/grafana/grafana/pkg/services/pluginsintegration/managedplugins"
+ "github.com/grafana/grafana/pkg/services/pluginsintegration/plugininstaller"
+ "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestRun(t *testing.T) {
+ tests := []struct {
+ name string
+ plugins []pluginstore.Plugin
+ pluginInfo map[string]*repo.PluginInfo
+ pluginArchives map[string]*repo.PluginArchiveInfo
+ pluginPreinstalled []string
+ pluginManaged []string
+ expectedFailures []advisor.CheckReportFailure
+ }{
+ {
+ name: "No plugins",
+ plugins: []pluginstore.Plugin{},
+ expectedFailures: []advisor.CheckReportFailure{},
+ },
+ {
+ name: "Deprecated plugin",
+ plugins: []pluginstore.Plugin{
+ {JSONData: plugins.JSONData{ID: "plugin1", Info: plugins.Info{Version: "1.0.0"}}},
+ },
+ pluginInfo: map[string]*repo.PluginInfo{
+ "plugin1": {Status: "deprecated"},
+ },
+ pluginArchives: map[string]*repo.PluginArchiveInfo{
+ "plugin1": {Version: "1.0.0"},
+ },
+ expectedFailures: []advisor.CheckReportFailure{
+ {
+ Severity: advisor.CheckReportFailureSeverityHigh,
+ StepID: "deprecation",
+ Item: "plugin1",
+ Links: []advisor.CheckErrorLink{
+ {
+ Url: "/plugins/plugin1",
+ Message: "Admin",
+ },
+ },
+ },
+ },
+ },
+ {
+ name: "Plugin with update",
+ plugins: []pluginstore.Plugin{
+ {JSONData: plugins.JSONData{ID: "plugin2", Info: plugins.Info{Version: "1.0.0"}}},
+ },
+ pluginInfo: map[string]*repo.PluginInfo{
+ "plugin2": {Status: "active"},
+ },
+ pluginArchives: map[string]*repo.PluginArchiveInfo{
+ "plugin2": {Version: "1.1.0"},
+ },
+ expectedFailures: []advisor.CheckReportFailure{
+ {
+ Severity: advisor.CheckReportFailureSeverityLow,
+ StepID: "update",
+ Item: "plugin2",
+ Links: []advisor.CheckErrorLink{
+ {
+ Url: "/plugins/plugin2?page=version-history",
+ Message: "Upgrade",
+ },
+ },
+ },
+ },
+ },
+ {
+ name: "Plugin with update (non semver)",
+ plugins: []pluginstore.Plugin{
+ {JSONData: plugins.JSONData{ID: "plugin2", Info: plugins.Info{Version: "alpha"}}},
+ },
+ pluginInfo: map[string]*repo.PluginInfo{
+ "plugin2": {Status: "active"},
+ },
+ pluginArchives: map[string]*repo.PluginArchiveInfo{
+ "plugin2": {Version: "beta"},
+ },
+ expectedFailures: []advisor.CheckReportFailure{
+ {
+ Severity: advisor.CheckReportFailureSeverityLow,
+ StepID: "update",
+ Item: "plugin2",
+ Links: []advisor.CheckErrorLink{
+ {
+ Url: "/plugins/plugin2?page=version-history",
+ Message: "Upgrade",
+ },
+ },
+ },
+ },
+ },
+ {
+ name: "Plugin pinned",
+ plugins: []pluginstore.Plugin{
+ {JSONData: plugins.JSONData{ID: "plugin3", Info: plugins.Info{Version: "1.0.0"}}},
+ },
+ pluginInfo: map[string]*repo.PluginInfo{
+ "plugin3": {Status: "active"},
+ },
+ pluginArchives: map[string]*repo.PluginArchiveInfo{
+ "plugin3": {Version: "1.1.0"},
+ },
+ pluginPreinstalled: []string{"plugin3"},
+ expectedFailures: []advisor.CheckReportFailure{},
+ },
+ {
+ name: "Managed plugin",
+ plugins: []pluginstore.Plugin{
+ {JSONData: plugins.JSONData{ID: "plugin4", Info: plugins.Info{Version: "1.0.0"}}},
+ },
+ pluginInfo: map[string]*repo.PluginInfo{
+ "plugin4": {Status: "active"},
+ },
+ pluginArchives: map[string]*repo.PluginArchiveInfo{
+ "plugin4": {Version: "1.1.0"},
+ },
+ pluginManaged: []string{"plugin4"},
+ expectedFailures: []advisor.CheckReportFailure{},
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ pluginStore := &mockPluginStore{plugins: tt.plugins}
+ pluginRepo := &mockPluginRepo{
+ pluginInfo: tt.pluginInfo,
+ pluginArchiveInfo: tt.pluginArchives,
+ }
+ pluginPreinstall := &mockPluginPreinstall{pinned: tt.pluginPreinstalled}
+ managedPlugins := &mockManagedPlugins{managed: tt.pluginManaged}
+ check := New(pluginStore, pluginRepo, pluginPreinstall, managedPlugins)
+
+ items, err := check.Items(context.Background())
+ assert.NoError(t, err)
+ failures := []advisor.CheckReportFailure{}
+ for _, step := range check.Steps() {
+ for _, item := range items {
+ stepFailures, err := step.Run(context.Background(), &advisor.CheckSpec{}, item)
+ assert.NoError(t, err)
+ if stepFailures != nil {
+ failures = append(failures, *stepFailures)
+ }
+ }
+ }
+ assert.NoError(t, err)
+ assert.Equal(t, len(tt.plugins), len(items))
+ assert.Equal(t, tt.expectedFailures, failures)
+ })
+ }
+}
+
+type mockPluginStore struct {
+ pluginstore.Store
+ plugins []pluginstore.Plugin
+}
+
+func (m *mockPluginStore) Plugins(ctx context.Context, t ...plugins.Type) []pluginstore.Plugin {
+ return m.plugins
+}
+
+type mockPluginRepo struct {
+ repo.Service
+ pluginInfo map[string]*repo.PluginInfo
+ pluginArchiveInfo map[string]*repo.PluginArchiveInfo
+}
+
+func (m *mockPluginRepo) PluginInfo(ctx context.Context, id string) (*repo.PluginInfo, error) {
+ return m.pluginInfo[id], nil
+}
+
+func (m *mockPluginRepo) GetPluginArchiveInfo(ctx context.Context, id, version string, opts repo.CompatOpts) (*repo.PluginArchiveInfo, error) {
+ return m.pluginArchiveInfo[id], nil
+}
+
+type mockPluginPreinstall struct {
+ plugininstaller.Preinstall
+ pinned []string
+}
+
+func (m *mockPluginPreinstall) IsPinned(pluginID string) bool {
+ for _, p := range m.pinned {
+ if p == pluginID {
+ return true
+ }
+ }
+ return false
+}
+
+type mockManagedPlugins struct {
+ managedplugins.Manager
+ managed []string
+}
+
+func (m *mockManagedPlugins) ManagedPlugins(ctx context.Context) []string {
+ return m.managed
+}
diff --git a/apps/advisor/pkg/app/checks/utils.go b/apps/advisor/pkg/app/checks/utils.go
new file mode 100644
index 00000000000..145c98d0961
--- /dev/null
+++ b/apps/advisor/pkg/app/checks/utils.go
@@ -0,0 +1,40 @@
+package checks
+
+import (
+ "fmt"
+ "strconv"
+
+ "github.com/grafana/authlib/types"
+ advisor "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+const (
+ TypeLabel = "advisor.grafana.app/type"
+ StatusAnnotation = "advisor.grafana.app/status"
+)
+
+func NewCheckReportFailure(
+ severity advisor.CheckReportFailureSeverity,
+ stepID string,
+ item string,
+ links []advisor.CheckErrorLink,
+) *advisor.CheckReportFailure {
+ return &advisor.CheckReportFailure{
+ Severity: severity,
+ StepID: stepID,
+ Item: item,
+ Links: links,
+ }
+}
+
+func GetNamespace(stackID string) (string, error) {
+ if stackID == "" {
+ return metav1.NamespaceDefault, nil
+ }
+ stackId, err := strconv.ParseInt(stackID, 10, 64)
+ if err != nil {
+ return "", fmt.Errorf("invalid stack id: %s", stackID)
+ }
+ return types.CloudNamespaceFormatter(stackId), nil
+}
diff --git a/apps/advisor/pkg/app/checks/utils_test.go b/apps/advisor/pkg/app/checks/utils_test.go
new file mode 100644
index 00000000000..ad0fda89de8
--- /dev/null
+++ b/apps/advisor/pkg/app/checks/utils_test.go
@@ -0,0 +1,46 @@
+package checks
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+func TestGetNamespace(t *testing.T) {
+ tests := []struct {
+ name string
+ input string
+ expected string
+ expectedErr string
+ }{
+ {
+ name: "empty stack ID",
+ input: "",
+ expected: metav1.NamespaceDefault,
+ },
+ {
+ name: "valid stack ID",
+ input: "1234567890",
+ expected: "stacks-1234567890",
+ },
+ {
+ name: "invalid stack ID",
+ input: "invalid",
+ expected: "",
+ expectedErr: "invalid stack id: invalid",
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ result, err := GetNamespace(tt.input)
+ if tt.expectedErr != "" {
+ assert.EqualError(t, err, tt.expectedErr)
+ } else {
+ assert.NoError(t, err)
+ }
+ assert.Equal(t, tt.expected, result)
+ })
+ }
+}
diff --git a/apps/advisor/pkg/app/checkscheduler/checkscheduler.go b/apps/advisor/pkg/app/checkscheduler/checkscheduler.go
new file mode 100644
index 00000000000..2bcb8d43f19
--- /dev/null
+++ b/apps/advisor/pkg/app/checkscheduler/checkscheduler.go
@@ -0,0 +1,225 @@
+package checkscheduler
+
+import (
+ "context"
+ "fmt"
+ "sort"
+ "strconv"
+ "time"
+
+ "github.com/grafana/grafana-app-sdk/app"
+ "github.com/grafana/grafana-app-sdk/k8s"
+ "github.com/grafana/grafana-app-sdk/resource"
+ "github.com/grafana/grafana-plugin-sdk-go/backend/gtime"
+ advisorv0alpha1 "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
+ "github.com/grafana/grafana/apps/advisor/pkg/app/checkregistry"
+ "github.com/grafana/grafana/apps/advisor/pkg/app/checks"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/klog/v2"
+)
+
+const defaultEvaluationInterval = 24 * time.Hour
+const defaultMaxHistory = 10
+
+// Runner is a "runnable" app used to be able to expose and API endpoint
+// with the existing checks types. This does not need to be a CRUD resource, but it is
+// the only way existing at the moment to expose the check types.
+type Runner struct {
+ checkRegistry checkregistry.CheckService
+ client resource.Client
+ evaluationInterval time.Duration
+ maxHistory int
+ namespace string
+}
+
+// NewRunner creates a new Runner.
+func New(cfg app.Config) (app.Runnable, error) {
+ // Read config
+ specificConfig, ok := cfg.SpecificConfig.(checkregistry.AdvisorAppConfig)
+ if !ok {
+ return nil, fmt.Errorf("invalid config type")
+ }
+ checkRegistry := specificConfig.CheckRegistry
+ evalInterval, err := getEvaluationInterval(specificConfig.PluginConfig)
+ if err != nil {
+ return nil, err
+ }
+ maxHistory, err := getMaxHistory(specificConfig.PluginConfig)
+ if err != nil {
+ return nil, err
+ }
+ namespace, err := checks.GetNamespace(specificConfig.StackID)
+ if err != nil {
+ return nil, err
+ }
+
+ // Prepare storage client
+ clientGenerator := k8s.NewClientRegistry(cfg.KubeConfig, k8s.ClientConfig{})
+ client, err := clientGenerator.ClientFor(advisorv0alpha1.CheckKind())
+ if err != nil {
+ return nil, err
+ }
+
+ return &Runner{
+ checkRegistry: checkRegistry,
+ client: client,
+ evaluationInterval: evalInterval,
+ maxHistory: maxHistory,
+ namespace: namespace,
+ }, nil
+}
+
+func (r *Runner) Run(ctx context.Context) error {
+ lastCreated, err := r.checkLastCreated(ctx)
+ if err != nil {
+ return err
+ }
+
+ // do an initial creation if necessary
+ if lastCreated.IsZero() {
+ err = r.createChecks(ctx)
+ if err != nil {
+ klog.Error("Error creating new check reports", "error", err)
+ } else {
+ lastCreated = time.Now()
+ }
+ }
+
+ nextSendInterval := time.Until(lastCreated.Add(r.evaluationInterval))
+ if nextSendInterval < time.Minute {
+ nextSendInterval = 1 * time.Minute
+ }
+
+ ticker := time.NewTicker(nextSendInterval)
+ defer ticker.Stop()
+
+ for {
+ select {
+ case <-ticker.C:
+ err = r.createChecks(ctx)
+ if err != nil {
+ klog.Error("Error creating new check reports", "error", err)
+ }
+
+ err = r.cleanupChecks(ctx)
+ if err != nil {
+ klog.Error("Error cleaning up old check reports", "error", err)
+ }
+
+ if nextSendInterval != r.evaluationInterval {
+ nextSendInterval = r.evaluationInterval
+ }
+ ticker.Reset(nextSendInterval)
+ case <-ctx.Done():
+ return ctx.Err()
+ }
+ }
+}
+
+// checkLastCreated returns the creation time of the last check created
+// regardless of its ID. This assumes that the checks are created in batches
+// so a batch will have a similar creation time.
+func (r *Runner) checkLastCreated(ctx context.Context) (time.Time, error) {
+ list, err := r.client.List(ctx, r.namespace, resource.ListOptions{})
+ if err != nil {
+ return time.Time{}, err
+ }
+ lastCreated := time.Time{}
+ for _, item := range list.GetItems() {
+ itemCreated := item.GetCreationTimestamp().Time
+ if itemCreated.After(lastCreated) {
+ lastCreated = itemCreated
+ }
+ }
+ return lastCreated, nil
+}
+
+// createChecks creates a new check for each check type in the registry.
+func (r *Runner) createChecks(ctx context.Context) error {
+ for _, check := range r.checkRegistry.Checks() {
+ obj := &advisorv0alpha1.Check{
+ ObjectMeta: metav1.ObjectMeta{
+ GenerateName: "check-",
+ Namespace: r.namespace,
+ Labels: map[string]string{
+ checks.TypeLabel: check.ID(),
+ },
+ },
+ Spec: advisorv0alpha1.CheckSpec{},
+ }
+ id := obj.GetStaticMetadata().Identifier()
+ _, err := r.client.Create(ctx, id, obj, resource.CreateOptions{})
+ if err != nil {
+ return fmt.Errorf("error creating check: %w", err)
+ }
+ }
+ return nil
+}
+
+// cleanupChecks deletes the olders checks if the number of checks exceeds the limit.
+func (r *Runner) cleanupChecks(ctx context.Context) error {
+ list, err := r.client.List(ctx, r.namespace, resource.ListOptions{Limit: -1})
+ if err != nil {
+ return err
+ }
+
+ // organize checks by type
+ checksByType := map[string][]resource.Object{}
+ for _, check := range list.GetItems() {
+ labels := check.GetLabels()
+ checkType, ok := labels[checks.TypeLabel]
+ if !ok {
+ klog.Error("Check type not found in labels", "check", check)
+ continue
+ }
+ checksByType[checkType] = append(checksByType[checkType], check)
+ }
+
+ for _, checks := range checksByType {
+ if len(checks) > r.maxHistory {
+ // Sort checks by creation time
+ sort.Slice(checks, func(i, j int) bool {
+ ti := checks[i].GetCreationTimestamp().Time
+ tj := checks[j].GetCreationTimestamp().Time
+ return ti.Before(tj)
+ })
+ // Delete the oldest checks
+ for i := 0; i < len(checks)-r.maxHistory; i++ {
+ check := checks[i]
+ id := check.GetStaticMetadata().Identifier()
+ err := r.client.Delete(ctx, id, resource.DeleteOptions{})
+ if err != nil {
+ return fmt.Errorf("error deleting check: %w", err)
+ }
+ }
+ }
+ }
+
+ return nil
+}
+
+func getEvaluationInterval(pluginConfig map[string]string) (time.Duration, error) {
+ evaluationInterval := defaultEvaluationInterval
+ configEvaluationInterval, ok := pluginConfig["evaluation_interval"]
+ if ok {
+ var err error
+ evaluationInterval, err = gtime.ParseDuration(configEvaluationInterval)
+ if err != nil {
+ return 0, fmt.Errorf("invalid evaluation interval: %w", err)
+ }
+ }
+ return evaluationInterval, nil
+}
+
+func getMaxHistory(pluginConfig map[string]string) (int, error) {
+ maxHistory := defaultMaxHistory
+ configMaxHistory, ok := pluginConfig["max_history"]
+ if ok {
+ var err error
+ maxHistory, err = strconv.Atoi(configMaxHistory)
+ if err != nil {
+ return 0, fmt.Errorf("invalid max history: %w", err)
+ }
+ }
+ return maxHistory, nil
+}
diff --git a/apps/advisor/pkg/app/checkscheduler/checkscheduler_test.go b/apps/advisor/pkg/app/checkscheduler/checkscheduler_test.go
new file mode 100644
index 00000000000..4fd5876b9ff
--- /dev/null
+++ b/apps/advisor/pkg/app/checkscheduler/checkscheduler_test.go
@@ -0,0 +1,279 @@
+package checkscheduler
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "math/rand/v2"
+ "testing"
+ "time"
+
+ "github.com/grafana/grafana-app-sdk/resource"
+ advisorv0alpha1 "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
+ "github.com/grafana/grafana/apps/advisor/pkg/app/checks"
+ "github.com/stretchr/testify/assert"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+func TestRunner_Run_ErrorOnList(t *testing.T) {
+ mockCheckService := &MockCheckService{}
+ mockClient := &MockClient{
+ listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) {
+ return nil, errors.New("list error")
+ },
+ createFunc: func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.CreateOptions) (resource.Object, error) {
+ return &advisorv0alpha1.Check{}, nil
+ },
+ }
+
+ runner := &Runner{
+ checkRegistry: mockCheckService,
+ client: mockClient,
+ }
+
+ err := runner.Run(context.Background())
+ assert.Error(t, err)
+}
+
+func TestRunner_checkLastCreated_ErrorOnList(t *testing.T) {
+ mockClient := &MockClient{
+ listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) {
+ return nil, errors.New("list error")
+ },
+ }
+
+ runner := &Runner{
+ client: mockClient,
+ }
+
+ lastCreated, err := runner.checkLastCreated(context.Background())
+ assert.Error(t, err)
+ assert.True(t, lastCreated.IsZero())
+}
+
+func TestRunner_createChecks_ErrorOnCreate(t *testing.T) {
+ mockCheckService := &MockCheckService{
+ checks: []checks.Check{
+ &mockCheck{
+ id: "check-1",
+ },
+ },
+ }
+ mockClient := &MockClient{
+ createFunc: func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.CreateOptions) (resource.Object, error) {
+ return nil, errors.New("create error")
+ },
+ }
+
+ runner := &Runner{
+ checkRegistry: mockCheckService,
+ client: mockClient,
+ }
+
+ err := runner.createChecks(context.Background())
+ assert.Error(t, err)
+}
+
+func TestRunner_createChecks_Success(t *testing.T) {
+ mockCheckService := &MockCheckService{
+ checks: []checks.Check{
+ &mockCheck{
+ id: "check-1",
+ },
+ },
+ }
+ mockClient := &MockClient{
+ createFunc: func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.CreateOptions) (resource.Object, error) {
+ return &advisorv0alpha1.Check{}, nil
+ },
+ }
+
+ runner := &Runner{
+ checkRegistry: mockCheckService,
+ client: mockClient,
+ }
+
+ err := runner.createChecks(context.Background())
+ assert.NoError(t, err)
+}
+
+func TestRunner_cleanupChecks_ErrorOnList(t *testing.T) {
+ mockClient := &MockClient{
+ listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) {
+ return nil, errors.New("list error")
+ },
+ }
+
+ runner := &Runner{
+ client: mockClient,
+ }
+
+ err := runner.cleanupChecks(context.Background())
+ assert.Error(t, err)
+}
+
+func TestRunner_cleanupChecks_WithinMax(t *testing.T) {
+ mockClient := &MockClient{
+ listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) {
+ return &advisorv0alpha1.CheckList{
+ Items: []advisorv0alpha1.Check{{}, {}},
+ }, nil
+ },
+ deleteFunc: func(ctx context.Context, identifier resource.Identifier, options resource.DeleteOptions) error {
+ return fmt.Errorf("shouldn't be called")
+ },
+ }
+
+ runner := &Runner{
+ client: mockClient,
+ }
+
+ err := runner.cleanupChecks(context.Background())
+ assert.NoError(t, err)
+}
+
+func TestRunner_cleanupChecks_ErrorOnDelete(t *testing.T) {
+ mockClient := &MockClient{
+ listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) {
+ items := make([]advisorv0alpha1.Check, 0, defaultMaxHistory+1)
+ for i := 0; i < defaultMaxHistory+1; i++ {
+ item := advisorv0alpha1.Check{}
+ item.ObjectMeta.SetLabels(map[string]string{
+ checks.TypeLabel: "mock",
+ })
+ items = append(items, item)
+ }
+ return &advisorv0alpha1.CheckList{
+ Items: items,
+ }, nil
+ },
+ deleteFunc: func(ctx context.Context, identifier resource.Identifier, options resource.DeleteOptions) error {
+ return errors.New("delete error")
+ },
+ }
+
+ runner := &Runner{
+ client: mockClient,
+ maxHistory: defaultMaxHistory,
+ }
+ err := runner.cleanupChecks(context.Background())
+ assert.ErrorContains(t, err, "delete error")
+}
+
+func TestRunner_cleanupChecks_Success(t *testing.T) {
+ itemsDeleted := []string{}
+ items := make([]advisorv0alpha1.Check, 0, defaultMaxHistory+1)
+ for i := 0; i < defaultMaxHistory+1; i++ {
+ item := advisorv0alpha1.Check{}
+ item.ObjectMeta.SetName(fmt.Sprintf("check-%d", i))
+ item.ObjectMeta.SetLabels(map[string]string{
+ checks.TypeLabel: "mock",
+ })
+ item.ObjectMeta.SetCreationTimestamp(metav1.NewTime(time.Time{}.Add(time.Duration(i) * time.Hour)))
+ items = append(items, item)
+ }
+ // shuffle the items to ensure the oldest are deleted
+ rand.Shuffle(len(items), func(i, j int) { items[i], items[j] = items[j], items[i] })
+
+ mockClient := &MockClient{
+ listFunc: func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) {
+ return &advisorv0alpha1.CheckList{
+ Items: items,
+ }, nil
+ },
+ deleteFunc: func(ctx context.Context, identifier resource.Identifier, options resource.DeleteOptions) error {
+ itemsDeleted = append(itemsDeleted, identifier.Name)
+ return nil
+ },
+ }
+
+ runner := &Runner{
+ client: mockClient,
+ maxHistory: defaultMaxHistory,
+ }
+ err := runner.cleanupChecks(context.Background())
+ assert.NoError(t, err)
+ assert.Equal(t, []string{"check-0"}, itemsDeleted)
+}
+
+func Test_getEvaluationInterval(t *testing.T) {
+ t.Run("default", func(t *testing.T) {
+ interval, err := getEvaluationInterval(map[string]string{})
+ assert.NoError(t, err)
+ assert.Equal(t, 24*time.Hour, interval)
+ })
+
+ t.Run("invalid", func(t *testing.T) {
+ interval, err := getEvaluationInterval(map[string]string{"evaluation_interval": "invalid"})
+ assert.Error(t, err)
+ assert.Zero(t, interval)
+ })
+
+ t.Run("custom", func(t *testing.T) {
+ interval, err := getEvaluationInterval(map[string]string{"evaluation_interval": "1h"})
+ assert.NoError(t, err)
+ assert.Equal(t, time.Hour, interval)
+ })
+}
+
+func Test_getMaxHistory(t *testing.T) {
+ t.Run("default", func(t *testing.T) {
+ history, err := getMaxHistory(map[string]string{})
+ assert.NoError(t, err)
+ assert.Equal(t, 10, history)
+ })
+
+ t.Run("invalid", func(t *testing.T) {
+ history, err := getMaxHistory(map[string]string{"max_history": "invalid"})
+ assert.Error(t, err)
+ assert.Zero(t, history)
+ })
+
+ t.Run("custom", func(t *testing.T) {
+ history, err := getMaxHistory(map[string]string{"max_history": "5"})
+ assert.NoError(t, err)
+ assert.Equal(t, 5, history)
+ })
+}
+
+type MockCheckService struct {
+ checks []checks.Check
+}
+
+func (m *MockCheckService) Checks() []checks.Check {
+ return m.checks
+}
+
+type MockClient struct {
+ resource.Client
+ listFunc func(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error)
+ createFunc func(ctx context.Context, identifier resource.Identifier, obj resource.Object, options resource.CreateOptions) (resource.Object, error)
+ deleteFunc func(ctx context.Context, identifier resource.Identifier, options resource.DeleteOptions) error
+}
+
+func (m *MockClient) List(ctx context.Context, namespace string, options resource.ListOptions) (resource.ListObject, error) {
+ return m.listFunc(ctx, namespace, options)
+}
+
+func (m *MockClient) Create(ctx context.Context, identifier resource.Identifier, obj resource.Object, options resource.CreateOptions) (resource.Object, error) {
+ return m.createFunc(ctx, identifier, obj, options)
+}
+
+func (m *MockClient) Delete(ctx context.Context, identifier resource.Identifier, options resource.DeleteOptions) error {
+ return m.deleteFunc(ctx, identifier, options)
+}
+
+type mockCheck struct {
+ checks.Check
+
+ id string
+ steps []checks.Step
+}
+
+func (m *mockCheck) ID() string {
+ return m.id
+}
+
+func (m *mockCheck) Steps() []checks.Step {
+ return m.steps
+}
diff --git a/apps/advisor/pkg/app/checktyperegisterer/checktyperegisterer.go b/apps/advisor/pkg/app/checktyperegisterer/checktyperegisterer.go
new file mode 100644
index 00000000000..2ed38e51ecb
--- /dev/null
+++ b/apps/advisor/pkg/app/checktyperegisterer/checktyperegisterer.go
@@ -0,0 +1,91 @@
+package checktyperegisterer
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/grafana/grafana-app-sdk/app"
+ "github.com/grafana/grafana-app-sdk/k8s"
+ "github.com/grafana/grafana-app-sdk/resource"
+ advisorv0alpha1 "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
+ "github.com/grafana/grafana/apps/advisor/pkg/app/checkregistry"
+ "github.com/grafana/grafana/apps/advisor/pkg/app/checks"
+ "k8s.io/apimachinery/pkg/api/errors"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// Runner is a "runnable" app used to be able to expose and API endpoint
+// with the existing checks types. This does not need to be a CRUD resource, but it is
+// the only way existing at the moment to expose the check types.
+type Runner struct {
+ checkRegistry checkregistry.CheckService
+ client resource.Client
+ namespace string
+}
+
+// NewRunner creates a new Runner.
+func New(cfg app.Config) (app.Runnable, error) {
+ // Read config
+ specificConfig, ok := cfg.SpecificConfig.(checkregistry.AdvisorAppConfig)
+ if !ok {
+ return nil, fmt.Errorf("invalid config type")
+ }
+ checkRegistry := specificConfig.CheckRegistry
+ namespace, err := checks.GetNamespace(specificConfig.StackID)
+ if err != nil {
+ return nil, err
+ }
+
+ // Prepare storage client
+ clientGenerator := k8s.NewClientRegistry(cfg.KubeConfig, k8s.ClientConfig{})
+ client, err := clientGenerator.ClientFor(advisorv0alpha1.CheckTypeKind())
+ if err != nil {
+ return nil, err
+ }
+
+ return &Runner{
+ checkRegistry: checkRegistry,
+ client: client,
+ namespace: namespace,
+ }, nil
+}
+
+func (r *Runner) Run(ctx context.Context) error {
+ for _, t := range r.checkRegistry.Checks() {
+ steps := t.Steps()
+ stepTypes := make([]advisorv0alpha1.CheckTypeStep, len(steps))
+ for i, s := range steps {
+ stepTypes[i] = advisorv0alpha1.CheckTypeStep{
+ Title: s.Title(),
+ Description: s.Description(),
+ StepID: s.ID(),
+ Resolution: s.Resolution(),
+ }
+ }
+ obj := &advisorv0alpha1.CheckType{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: t.ID(),
+ Namespace: r.namespace,
+ },
+ Spec: advisorv0alpha1.CheckTypeSpec{
+ Name: t.ID(),
+ Steps: stepTypes,
+ },
+ }
+ id := obj.GetStaticMetadata().Identifier()
+ _, err := r.client.Create(ctx, id, obj, resource.CreateOptions{})
+ if err != nil {
+ if errors.IsAlreadyExists(err) {
+ // Already exists, update
+ _, err = r.client.Update(ctx, id, obj, resource.UpdateOptions{})
+ if err != nil {
+ return err
+ } else {
+ continue
+ }
+ }
+ return err
+ }
+ }
+ return nil
+}
diff --git a/apps/advisor/pkg/app/checktyperegisterer/checktyperegisterer_test.go b/apps/advisor/pkg/app/checktyperegisterer/checktyperegisterer_test.go
new file mode 100644
index 00000000000..97fc7742504
--- /dev/null
+++ b/apps/advisor/pkg/app/checktyperegisterer/checktyperegisterer_test.go
@@ -0,0 +1,196 @@
+package checktyperegisterer
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "testing"
+
+ "github.com/grafana/grafana-app-sdk/resource"
+ advisorv0alpha1 "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
+ "github.com/grafana/grafana/apps/advisor/pkg/app/checks"
+ k8sErrs "k8s.io/apimachinery/pkg/api/errors"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+)
+
+func TestCheckTypesRegisterer_Run(t *testing.T) {
+ tests := []struct {
+ name string
+ checks []checks.Check
+ createFunc func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.CreateOptions) (resource.Object, error)
+ updateFunc func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.UpdateOptions) (resource.Object, error)
+ expectedErr error
+ }{
+ {
+ name: "successful create",
+ checks: []checks.Check{
+ &mockCheck{
+ id: "check1",
+ steps: []checks.Step{
+ &mockStep{id: "step1", title: "Step 1", description: "Description 1"},
+ },
+ },
+ },
+ createFunc: func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.CreateOptions) (resource.Object, error) {
+ return obj, nil
+ },
+ updateFunc: nil,
+ expectedErr: nil,
+ },
+ {
+ name: "create already exists, successful update",
+ checks: []checks.Check{
+ &mockCheck{
+ id: "check1",
+ steps: []checks.Step{
+ &mockStep{id: "step1", title: "Step 1", description: "Description 1"},
+ },
+ },
+ },
+ createFunc: func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.CreateOptions) (resource.Object, error) {
+ return nil, k8sErrs.NewAlreadyExists(schema.GroupResource{}, obj.GetName())
+ },
+ updateFunc: func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.UpdateOptions) (resource.Object, error) {
+ return obj, nil
+ },
+ expectedErr: nil,
+ },
+ {
+ name: "create error",
+ checks: []checks.Check{
+ &mockCheck{
+ id: "check1",
+ steps: []checks.Step{
+ &mockStep{id: "step1", title: "Step 1", description: "Description 1"},
+ },
+ },
+ },
+ createFunc: func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.CreateOptions) (resource.Object, error) {
+ return nil, errors.New("create error")
+ },
+ updateFunc: nil,
+ expectedErr: errors.New("create error"),
+ },
+ {
+ name: "update error",
+ checks: []checks.Check{
+ &mockCheck{
+ id: "check1",
+ steps: []checks.Step{
+ &mockStep{id: "step1", title: "Step 1", description: "Description 1"},
+ },
+ },
+ },
+ createFunc: func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.CreateOptions) (resource.Object, error) {
+ return nil, k8sErrs.NewAlreadyExists(schema.GroupResource{}, obj.GetName())
+ },
+ updateFunc: func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.UpdateOptions) (resource.Object, error) {
+ return nil, errors.New("update error")
+ },
+ expectedErr: errors.New("update error"),
+ },
+ {
+ name: "custom namespace",
+ checks: []checks.Check{
+ &mockCheck{
+ id: "check1",
+ steps: []checks.Step{
+ &mockStep{id: "step1", title: "Step 1", description: "Description 1"},
+ },
+ },
+ },
+ createFunc: func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.CreateOptions) (resource.Object, error) {
+ if obj.GetNamespace() != "custom-namespace" {
+ return nil, fmt.Errorf("expected namespace %s, got %s", "custom-namespace", obj.GetNamespace())
+ }
+ return obj, nil
+ },
+ expectedErr: nil,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ r := &Runner{
+ checkRegistry: &mockCheckRegistry{checks: tt.checks},
+ client: &mockClient{
+ createFunc: tt.createFunc,
+ updateFunc: tt.updateFunc,
+ },
+ namespace: "custom-namespace",
+ }
+ err := r.Run(context.Background())
+ if err != nil {
+ if tt.expectedErr == nil {
+ t.Errorf("unexpected error: %v", err)
+ } else if err.Error() != tt.expectedErr.Error() {
+ t.Errorf("expected error: %v, got: %v", tt.expectedErr, err)
+ }
+ }
+ })
+ }
+}
+
+type mockCheckRegistry struct {
+ checks []checks.Check
+}
+
+func (m *mockCheckRegistry) Checks() []checks.Check {
+ return m.checks
+}
+
+type mockCheck struct {
+ checks.Check
+
+ id string
+ steps []checks.Step
+}
+
+func (m *mockCheck) ID() string {
+ return m.id
+}
+
+func (m *mockCheck) Steps() []checks.Step {
+ return m.steps
+}
+
+type mockStep struct {
+ id string
+ title string
+ description string
+}
+
+func (m *mockStep) ID() string {
+ return m.id
+}
+
+func (m *mockStep) Title() string {
+ return m.title
+}
+
+func (m *mockStep) Description() string {
+ return m.description
+}
+
+func (m *mockStep) Resolution() string {
+ return ""
+}
+
+func (m *mockStep) Run(ctx context.Context, obj *advisorv0alpha1.CheckSpec, item any) (*advisorv0alpha1.CheckReportFailure, error) {
+ return nil, nil
+}
+
+type mockClient struct {
+ resource.Client
+
+ createFunc func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.CreateOptions) (resource.Object, error)
+ updateFunc func(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.UpdateOptions) (resource.Object, error)
+}
+
+func (m *mockClient) Create(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.CreateOptions) (resource.Object, error) {
+ return m.createFunc(ctx, id, obj, opts)
+}
+
+func (m *mockClient) Update(ctx context.Context, id resource.Identifier, obj resource.Object, opts resource.UpdateOptions) (resource.Object, error) {
+ return m.updateFunc(ctx, id, obj, opts)
+}
diff --git a/apps/advisor/pkg/app/utils.go b/apps/advisor/pkg/app/utils.go
new file mode 100644
index 00000000000..8c1b6c00eb8
--- /dev/null
+++ b/apps/advisor/pkg/app/utils.go
@@ -0,0 +1,143 @@
+package app
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "sync"
+
+ claims "github.com/grafana/authlib/types"
+ "github.com/grafana/grafana-app-sdk/resource"
+ advisorv0alpha1 "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
+ "github.com/grafana/grafana/apps/advisor/pkg/app/checks"
+ "github.com/grafana/grafana/pkg/apimachinery/identity"
+ "github.com/grafana/grafana/pkg/apimachinery/utils"
+ "github.com/grafana/grafana/pkg/services/user"
+)
+
+func getCheck(obj resource.Object, checkMap map[string]checks.Check) (checks.Check, error) {
+ labels := obj.GetLabels()
+ objTypeLabel, ok := labels[checks.TypeLabel]
+ if !ok {
+ return nil, errors.New("missing check type as label")
+ }
+ c, ok := checkMap[objTypeLabel]
+ if !ok {
+ supportedTypes := ""
+ for k := range checkMap {
+ supportedTypes += k + ", "
+ }
+ return nil, fmt.Errorf("unknown check type %s. Supported types are: %s", objTypeLabel, supportedTypes)
+ }
+
+ return c, nil
+}
+
+func getStatusAnnotation(obj resource.Object) string {
+ return obj.GetAnnotations()[checks.StatusAnnotation]
+}
+
+func setStatusAnnotation(ctx context.Context, client resource.Client, obj resource.Object, status string) error {
+ annotations := obj.GetAnnotations()
+ annotations[checks.StatusAnnotation] = status
+ return client.PatchInto(ctx, obj.GetStaticMetadata().Identifier(), resource.PatchRequest{
+ Operations: []resource.PatchOperation{{
+ Operation: resource.PatchOpAdd,
+ Path: "/metadata/annotations",
+ Value: annotations,
+ }},
+ }, resource.PatchOptions{}, obj)
+}
+
+func processCheck(ctx context.Context, client resource.Client, obj resource.Object, check checks.Check) error {
+ status := getStatusAnnotation(obj)
+ if status != "" {
+ // Check already processed
+ return nil
+ }
+ c, ok := obj.(*advisorv0alpha1.Check)
+ if !ok {
+ return fmt.Errorf("invalid object type")
+ }
+ // Populate ctx with the user that created the check
+ meta, err := utils.MetaAccessor(obj)
+ if err != nil {
+ return err
+ }
+ createdBy := meta.GetCreatedBy()
+ typ, uid, err := claims.ParseTypeID(createdBy)
+ if err != nil {
+ return err
+ }
+ ctx = identity.WithRequester(ctx, &user.SignedInUser{
+ UserUID: uid,
+ FallbackType: typ,
+ })
+ // Get the items to check
+ items, err := check.Items(ctx)
+ if err != nil {
+ setErr := setStatusAnnotation(ctx, client, obj, "error")
+ if setErr != nil {
+ return setErr
+ }
+ return fmt.Errorf("error initializing check: %w", err)
+ }
+ // Run the steps
+ steps := check.Steps()
+ failures, err := runStepsInParallel(ctx, &c.Spec, steps, items)
+ if err != nil {
+ setErr := setStatusAnnotation(ctx, client, obj, "error")
+ if setErr != nil {
+ return setErr
+ }
+ return fmt.Errorf("error running steps: %w", err)
+ }
+
+ report := &advisorv0alpha1.CheckV0alpha1StatusReport{
+ Failures: failures,
+ Count: int64(len(items)),
+ }
+ err = setStatusAnnotation(ctx, client, obj, "processed")
+ if err != nil {
+ return err
+ }
+ return client.PatchInto(ctx, obj.GetStaticMetadata().Identifier(), resource.PatchRequest{
+ Operations: []resource.PatchOperation{{
+ Operation: resource.PatchOpAdd,
+ Path: "/status/report",
+ Value: *report,
+ }},
+ }, resource.PatchOptions{}, obj)
+}
+
+func runStepsInParallel(ctx context.Context, spec *advisorv0alpha1.CheckSpec, steps []checks.Step, items []any) ([]advisorv0alpha1.CheckReportFailure, error) {
+ reportFailures := []advisorv0alpha1.CheckReportFailure{}
+ var internalErr error
+ var wg sync.WaitGroup
+ var mu sync.Mutex
+ // Avoid too many concurrent requests
+ limit := make(chan struct{}, 10)
+
+ for _, step := range steps {
+ for _, item := range items {
+ wg.Add(1)
+ limit <- struct{}{}
+ go func(step checks.Step, item any) {
+ defer wg.Done()
+ defer func() { <-limit }()
+ stepErr, err := step.Run(ctx, spec, item)
+ mu.Lock()
+ defer mu.Unlock()
+ if err != nil {
+ internalErr = fmt.Errorf("error running step %s: %w", step.ID(), err)
+ return
+ }
+ if stepErr != nil {
+ reportFailures = append(reportFailures, *stepErr)
+ }
+ }(step, item)
+ }
+ }
+ wg.Wait()
+ return reportFailures, internalErr
+}
diff --git a/apps/advisor/pkg/app/utils_test.go b/apps/advisor/pkg/app/utils_test.go
new file mode 100644
index 00000000000..b3b8d36f60b
--- /dev/null
+++ b/apps/advisor/pkg/app/utils_test.go
@@ -0,0 +1,200 @@
+package app
+
+import (
+ "context"
+ "errors"
+ "fmt"
+ "testing"
+
+ "github.com/grafana/grafana-app-sdk/resource"
+ advisorv0alpha1 "github.com/grafana/grafana/apps/advisor/pkg/apis/advisor/v0alpha1"
+ "github.com/grafana/grafana/apps/advisor/pkg/app/checks"
+ "github.com/grafana/grafana/pkg/apimachinery/utils"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestGetCheck(t *testing.T) {
+ obj := &advisorv0alpha1.Check{}
+ obj.SetLabels(map[string]string{checks.TypeLabel: "testType"})
+
+ checkMap := map[string]checks.Check{
+ "testType": &mockCheck{},
+ }
+
+ check, err := getCheck(obj, checkMap)
+ assert.NoError(t, err)
+ assert.NotNil(t, check)
+}
+
+func TestGetCheck_MissingLabel(t *testing.T) {
+ obj := &advisorv0alpha1.Check{}
+ checkMap := map[string]checks.Check{}
+
+ _, err := getCheck(obj, checkMap)
+ assert.Error(t, err)
+ assert.Equal(t, "missing check type as label", err.Error())
+}
+
+func TestGetCheck_UnknownType(t *testing.T) {
+ obj := &advisorv0alpha1.Check{}
+ obj.SetLabels(map[string]string{checks.TypeLabel: "unknownType"})
+
+ checkMap := map[string]checks.Check{
+ "testType": &mockCheck{},
+ }
+
+ _, err := getCheck(obj, checkMap)
+ assert.Error(t, err)
+ assert.Contains(t, err.Error(), "unknown check type unknownType")
+}
+
+func TestSetStatusAnnotation(t *testing.T) {
+ obj := &advisorv0alpha1.Check{}
+ obj.SetAnnotations(map[string]string{})
+ client := &mockClient{}
+ ctx := context.TODO()
+
+ err := setStatusAnnotation(ctx, client, obj, "processed")
+ assert.NoError(t, err)
+ assert.Equal(t, "processed", obj.GetAnnotations()[checks.StatusAnnotation])
+}
+
+func TestProcessCheck(t *testing.T) {
+ obj := &advisorv0alpha1.Check{}
+ obj.SetAnnotations(map[string]string{})
+ meta, err := utils.MetaAccessor(obj)
+ if err != nil {
+ t.Fatal(err)
+ }
+ meta.SetCreatedBy("user:1")
+ client := &mockClient{}
+ ctx := context.TODO()
+ check := &mockCheck{
+ items: []any{"item"},
+ }
+
+ err = processCheck(ctx, client, obj, check)
+ assert.NoError(t, err)
+ assert.Equal(t, "processed", obj.GetAnnotations()[checks.StatusAnnotation])
+}
+
+func TestProcessMultipleCheckItems(t *testing.T) {
+ obj := &advisorv0alpha1.Check{}
+ obj.SetAnnotations(map[string]string{})
+ meta, err := utils.MetaAccessor(obj)
+ if err != nil {
+ t.Fatal(err)
+ }
+ meta.SetCreatedBy("user:1")
+ client := &mockClient{}
+ ctx := context.TODO()
+ items := make([]any, 100)
+ for i := range items {
+ if i%2 == 0 {
+ items[i] = fmt.Sprintf("item-%d", i)
+ } else {
+ items[i] = errors.New("error")
+ }
+ }
+ check := &mockCheck{
+ items: items,
+ }
+
+ err = processCheck(ctx, client, obj, check)
+ assert.NoError(t, err)
+ assert.Equal(t, "processed", obj.GetAnnotations()[checks.StatusAnnotation])
+ r := client.lastValue.(advisorv0alpha1.CheckV0alpha1StatusReport)
+ assert.Equal(t, r.Count, int64(100))
+ assert.Len(t, r.Failures, 50)
+}
+
+func TestProcessCheck_AlreadyProcessed(t *testing.T) {
+ obj := &advisorv0alpha1.Check{}
+ obj.SetAnnotations(map[string]string{checks.StatusAnnotation: "processed"})
+ client := &mockClient{}
+ ctx := context.TODO()
+ check := &mockCheck{}
+
+ err := processCheck(ctx, client, obj, check)
+ assert.NoError(t, err)
+}
+
+func TestProcessCheck_RunError(t *testing.T) {
+ obj := &advisorv0alpha1.Check{}
+ obj.SetAnnotations(map[string]string{})
+ meta, err := utils.MetaAccessor(obj)
+ if err != nil {
+ t.Fatal(err)
+ }
+ meta.SetCreatedBy("user:1")
+ client := &mockClient{}
+ ctx := context.TODO()
+
+ check := &mockCheck{
+ items: []any{"item"},
+ err: errors.New("run error"),
+ }
+
+ err = processCheck(ctx, client, obj, check)
+ assert.Error(t, err)
+ assert.Equal(t, "error", obj.GetAnnotations()[checks.StatusAnnotation])
+}
+
+type mockClient struct {
+ resource.Client
+ lastValue any
+}
+
+func (m *mockClient) PatchInto(ctx context.Context, id resource.Identifier, req resource.PatchRequest, opts resource.PatchOptions, obj resource.Object) error {
+ m.lastValue = req.Operations[0].Value
+ return nil
+}
+
+type mockCheck struct {
+ err error
+ items []any
+}
+
+func (m *mockCheck) ID() string {
+ return "mock"
+}
+
+func (m *mockCheck) Items(ctx context.Context) ([]any, error) {
+ return m.items, nil
+}
+
+func (m *mockCheck) Steps() []checks.Step {
+ return []checks.Step{
+ &mockStep{err: m.err},
+ }
+}
+
+type mockStep struct {
+ err error
+}
+
+func (m *mockStep) Run(ctx context.Context, obj *advisorv0alpha1.CheckSpec, items any) (*advisorv0alpha1.CheckReportFailure, error) {
+ if m.err != nil {
+ return nil, m.err
+ }
+ if _, ok := items.(error); ok {
+ return &advisorv0alpha1.CheckReportFailure{}, nil
+ }
+ return nil, nil
+}
+
+func (m *mockStep) Title() string {
+ return "mock"
+}
+
+func (m *mockStep) Description() string {
+ return "mock"
+}
+
+func (m *mockStep) Resolution() string {
+ return "mock"
+}
+
+func (m *mockStep) ID() string {
+ return "mock"
+}
diff --git a/apps/advisor/plugin/README.md b/apps/advisor/plugin/README.md
new file mode 100644
index 00000000000..5b9e2bc8744
--- /dev/null
+++ b/apps/advisor/plugin/README.md
@@ -0,0 +1,7 @@
+This folder contains the automatically generated types for the frontend that are used in the app plugin.
+
+To update the types:
+
+1. Make any necessary changes in the `kinds` directory
+2. Run `make generate`
+3. Copy the `plugin` directory to the frontend app: https://github.com/grafana/grafana-advisor-app/tree/main/src/plugin
diff --git a/apps/alerting/notifications/go.mod b/apps/alerting/notifications/go.mod
index 61093d88f4b..eaa0b14475d 100644
--- a/apps/alerting/notifications/go.mod
+++ b/apps/alerting/notifications/go.mod
@@ -1,14 +1,14 @@
module github.com/grafana/grafana/apps/alerting/notifications
-go 1.23.5
+go 1.23.7
replace github.com/grafana/grafana => ../../..
require (
github.com/grafana/grafana v11.4.0-00010101000000-000000000000+incompatible
- github.com/grafana/grafana-app-sdk v0.30.0
- k8s.io/apimachinery v0.32.0
- k8s.io/apiserver v0.32.0
+ github.com/grafana/grafana-app-sdk v0.31.0
+ k8s.io/apimachinery v0.32.1
+ k8s.io/apiserver v0.32.1
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f
)
@@ -32,13 +32,13 @@ require (
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
- github.com/google/go-cmp v0.6.0 // indirect
+ github.com/google/go-cmp v0.7.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
github.com/google/uuid v1.6.0 // indirect
- github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250121113133-e747350fee2d // indirect
+ github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250220154326-6e5de80ef295 // indirect
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 // indirect
- github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 // indirect
+ github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jmespath-community/go-jmespath v1.1.1 // indirect
github.com/josharian/intern v1.0.0 // indirect
@@ -50,46 +50,46 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pkg/errors v0.9.1 // indirect
- github.com/prometheus/client_golang v1.20.5 // indirect
+ github.com/prometheus/client_golang v1.21.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
- github.com/prometheus/common v0.61.0 // indirect
+ github.com/prometheus/common v0.62.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
- github.com/spf13/cobra v1.8.1 // indirect
- github.com/spf13/pflag v1.0.5 // indirect
+ github.com/spf13/cobra v1.9.1 // indirect
+ github.com/spf13/pflag v1.0.6 // indirect
github.com/x448/float16 v0.8.4 // indirect
go.etcd.io/etcd/api/v3 v3.5.16 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.16 // indirect
go.etcd.io/etcd/client/v3 v3.5.16 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
- go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0 // indirect
- go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 // indirect
- go.opentelemetry.io/otel v1.33.0 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0 // indirect
- go.opentelemetry.io/otel/metric v1.33.0 // indirect
- go.opentelemetry.io/otel/sdk v1.33.0 // indirect
- go.opentelemetry.io/otel/trace v1.33.0 // indirect
+ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 // indirect
+ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect
+ go.opentelemetry.io/otel v1.34.0 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 // indirect
+ go.opentelemetry.io/otel/metric v1.34.0 // indirect
+ go.opentelemetry.io/otel/sdk v1.34.0 // indirect
+ go.opentelemetry.io/otel/trace v1.34.0 // indirect
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
- golang.org/x/crypto v0.32.0 // indirect
+ golang.org/x/crypto v0.35.0 // indirect
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect
- golang.org/x/net v0.34.0 // indirect
- golang.org/x/oauth2 v0.25.0 // indirect
- golang.org/x/sys v0.29.0 // indirect
- golang.org/x/term v0.28.0 // indirect
- golang.org/x/text v0.21.0 // indirect
+ golang.org/x/net v0.36.0 // indirect
+ golang.org/x/oauth2 v0.27.0 // indirect
+ golang.org/x/sys v0.30.0 // indirect
+ golang.org/x/term v0.29.0 // indirect
+ golang.org/x/text v0.22.0 // indirect
golang.org/x/time v0.9.0 // indirect
- google.golang.org/genproto/googleapis/api v0.0.0-20250102185135-69823020774d // indirect
- google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d // indirect
- google.golang.org/grpc v1.69.4 // indirect
- google.golang.org/protobuf v1.36.1 // indirect
+ google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20250207221924-e9438ea467c6 // indirect
+ google.golang.org/grpc v1.70.0 // indirect
+ google.golang.org/protobuf v1.36.5 // indirect
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
- k8s.io/api v0.32.0 // indirect
- k8s.io/client-go v0.32.0 // indirect
- k8s.io/component-base v0.32.0 // indirect
+ k8s.io/api v0.32.1 // indirect
+ k8s.io/client-go v0.32.1 // indirect
+ k8s.io/component-base v0.32.1 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0 // indirect
diff --git a/apps/alerting/notifications/go.sum b/apps/alerting/notifications/go.sum
index a140089cc39..26ad8bf9fc2 100644
--- a/apps/alerting/notifications/go.sum
+++ b/apps/alerting/notifications/go.sum
@@ -19,7 +19,7 @@ github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
-github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
@@ -60,8 +60,8 @@ github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl76
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
-github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
-github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
+github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -71,18 +71,18 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
-github.com/grafana/grafana-app-sdk v0.30.0 h1:Hqn2pETu2mQ4RpWkZYEQfu01P7xd1Z1Gj+HX/8aB0tw=
-github.com/grafana/grafana-app-sdk v0.30.0/go.mod h1:jhfqNIovb+Mes2vdMf9iMCWQkp1GTNtyNuExONtiNuk=
-github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250121113133-e747350fee2d h1:0WJ4uZ3gtbX7S5RGMarA+0TccmB7qEPhhNm34NcfBzs=
-github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250121113133-e747350fee2d/go.mod h1:PNmbi49lVrv2b2I8pdu46dTs2728lKEbnVuQD8I5MnM=
+github.com/grafana/grafana-app-sdk v0.31.0 h1:/mFCcx+YqG8cWAi9hePDJQxIdtXDClDIDRgZwHkksFk=
+github.com/grafana/grafana-app-sdk v0.31.0/go.mod h1:Xw00NL7qpRLo5r3Gn48Bl1Xn2n4eUDI5pYf/wMufKWs=
+github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250220154326-6e5de80ef295 h1:bOKkAzmkCnK2EN0LGsHoq5HyfXMLKXrr8+q35Fh+XQI=
+github.com/grafana/grafana/pkg/apimachinery v0.0.0-20250220154326-6e5de80ef295/go.mod h1:1iWqntBW91TsiyqneHrqTFV12vd1Tei+f5VY2ovkNAo=
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI=
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340 h1:uGoIog/wiQHI9GAxXO5TJbT0wWKH3O9HhOJW1F9c3fY=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.1-0.20191002090509-6af20e3a5340/go.mod h1:3bDW6wMZJB7tiONtC/1Xpicra6Wp5GgbTbQWCbI5fkc=
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 h1:e9Rjr40Z98/clHv5Yg79Is0NtosR5LXRvdr7o/6NwbA=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1/go.mod h1:tIxuGz/9mpox++sgp9fJjHO0+q1X9/UOWd798aAm22M=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jmespath-community/go-jmespath v1.1.1 h1:bFikPhsi/FdmlZhVgSCd2jj1e7G/rw+zyQfyg5UF+L4=
@@ -113,25 +113,25 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
-github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
-github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
-github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
-github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
+github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg=
+github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
+github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw=
+github.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
-github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
-github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
+github.com/prometheus/client_golang v1.21.0 h1:DIsaGmiaBkSangBgMtWdNfxbMNdku5IK6iNhrEqWvdA=
+github.com/prometheus/client_golang v1.21.0/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
-github.com/prometheus/common v0.61.0 h1:3gv/GThfX0cV2lpO7gkTUwZru38mxevy90Bj8YFSRQQ=
-github.com/prometheus/common v0.61.0/go.mod h1:zr29OCN/2BsJRaFwG8QOBr41D6kkchKbpeNH7pAjb/s=
+github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
+github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
@@ -142,10 +142,10 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js=
github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0=
-github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
-github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
-github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
-github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
+github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
+github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
+github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
@@ -178,24 +178,24 @@ go.etcd.io/etcd/server/v3 v3.5.16 h1:d0/SAdJ3vVsZvF8IFVb1k8zqMZ+heGcNfft71ul9GWE
go.etcd.io/etcd/server/v3 v3.5.16/go.mod h1:ynhyZZpdDp1Gq49jkUg5mfkDWZwXnn3eIqCqtJnrD/s=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
-go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0 h1:PS8wXpbyaDJQ2VDHHncMe9Vct0Zn1fEjpsjrLxGJoSc=
-go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0/go.mod h1:HDBUsEjOuRC0EzKZ1bSaRGZWUBAzo+MhAcUUORSr4D0=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 h1:yd02MEjBdJkG3uabWP9apV+OuWRIXGDuJEUJbOHmCFU=
-go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q=
-go.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw=
-go.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 h1:Vh5HayB/0HHfOQA7Ctx69E/Y/DcQSMPpKANYVMQ7fBA=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0/go.mod h1:cpgtDBaqD/6ok/UG0jT15/uKjAY8mRA53diogHBg3UI=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0 h1:5pojmb1U1AogINhN3SurB+zm/nIcusopeBNp42f45QM=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0/go.mod h1:57gTHJSE5S1tqg+EKsLPlTWhpHMsWlVmer+LA926XiA=
-go.opentelemetry.io/otel/metric v1.33.0 h1:r+JOocAyeRVXD8lZpjdQjzMadVZp2M4WmQ+5WtEnklQ=
-go.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M=
-go.opentelemetry.io/otel/sdk v1.33.0 h1:iax7M131HuAm9QkZotNHEfstof92xM+N8sr3uHXc2IM=
-go.opentelemetry.io/otel/sdk v1.33.0/go.mod h1:A1Q5oi7/9XaMlIWzPSxLRWOI8nG3FnzHJNbiENQuihM=
-go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc=
-go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8=
-go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s=
-go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck=
+go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 h1:rgMkmiGfix9vFJDcDi1PK8WEQP4FLQwLDfhp5ZLpFeE=
+go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0/go.mod h1:ijPqXp5P6IRRByFVVg9DY8P5HkxkHE5ARIa+86aXPf4=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s=
+go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I=
+go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
+go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE=
+go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
+go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
+go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
+go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
+go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU=
+go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ=
+go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
+go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
@@ -207,8 +207,8 @@ go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
-golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
+golang.org/x/crypto v0.35.0 h1:b15kiHdrGCHrP6LvwaQ3c03kgNhhiMgvlhxHQhmg2Xs=
+golang.org/x/crypto v0.35.0/go.mod h1:dy7dXNW32cAb/6/PRuTNsix8T+vJAqvuIy5Bli/x0YQ=
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk=
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -223,11 +223,11 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
-golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
+golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA=
+golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
-golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70=
-golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
+golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=
+golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -237,14 +237,14 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
-golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
-golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
+golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
+golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
+golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
-golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
+golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
+golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -260,17 +260,17 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
-google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38 h1:Q3nlH8iSQSRUwOskjbcSMcF2jiYMNiQYZ0c2KEJLKKU=
-google.golang.org/genproto v0.0.0-20241021214115-324edc3d5d38/go.mod h1:xBI+tzfqGGN2JBeSebfKXFSdBpWVQ7sLW40PTupVRm4=
-google.golang.org/genproto/googleapis/api v0.0.0-20250102185135-69823020774d h1:H8tOf8XM88HvKqLTxe755haY6r1fqqzLbEnfrmLXlSA=
-google.golang.org/genproto/googleapis/api v0.0.0-20250102185135-69823020774d/go.mod h1:2v7Z7gP2ZUOGsaFyxATQSRoBnKygqVq2Cwnvom7QiqY=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d h1:xJJRGY7TJcvIlpSrN3K6LAWgNFUILlO+OMAqtg9aqnw=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d/go.mod h1:3ENsm/5D1mzDyhpzeRi1NR784I0BcofWBoSc5QqqMK4=
+google.golang.org/genproto v0.0.0-20250122153221-138b5a5a4fd4 h1:Pw6WnI9W/LIdRxqK7T6XGugGbHIRl5Q7q3BssH6xk4s=
+google.golang.org/genproto v0.0.0-20250122153221-138b5a5a4fd4/go.mod h1:qbZzneIOXSq+KFAFut9krLfRLZiFLzZL5u2t8SV83EE=
+google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489 h1:fCuMM4fowGzigT89NCIsW57Pk9k2D12MMi2ODn+Nk+o=
+google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489/go.mod h1:iYONQfRdizDB8JJBybql13nArx91jcUk7zCXEsOofM4=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250207221924-e9438ea467c6 h1:2duwAxN2+k0xLNpjnHTXoMUgnv6VPSp5fiqTuwSxjmI=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250207221924-e9438ea467c6/go.mod h1:8BS3B93F/U1juMFq9+EDk+qOT5CO1R9IzXxG3PTqiRk=
google.golang.org/grpc v1.18.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
-google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A=
-google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4=
-google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk=
-google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
+google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
+google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
+google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
@@ -283,16 +283,16 @@ gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYs
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-k8s.io/api v0.32.0 h1:OL9JpbvAU5ny9ga2fb24X8H6xQlVp+aJMFlgtQjR9CE=
-k8s.io/api v0.32.0/go.mod h1:4LEwHZEf6Q/cG96F3dqR965sYOfmPM7rq81BLgsE0p0=
-k8s.io/apimachinery v0.32.0 h1:cFSE7N3rmEEtv4ei5X6DaJPHHX0C+upp+v5lVPiEwpg=
-k8s.io/apimachinery v0.32.0/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
-k8s.io/apiserver v0.32.0 h1:VJ89ZvQZ8p1sLeiWdRJpRD6oLozNZD2+qVSLi+ft5Qs=
-k8s.io/apiserver v0.32.0/go.mod h1:HFh+dM1/BE/Hm4bS4nTXHVfN6Z6tFIZPi649n83b4Ag=
-k8s.io/client-go v0.32.0 h1:DimtMcnN/JIKZcrSrstiwvvZvLjG0aSxy8PxN8IChp8=
-k8s.io/client-go v0.32.0/go.mod h1:boDWvdM1Drk4NJj/VddSLnx59X3OPgwrOo0vGbtq9+8=
-k8s.io/component-base v0.32.0 h1:d6cWHZkCiiep41ObYQS6IcgzOUQUNpywm39KVYaUqzU=
-k8s.io/component-base v0.32.0/go.mod h1:JLG2W5TUxUu5uDyKiH2R/7NnxJo1HlPoRIIbVLkK5eM=
+k8s.io/api v0.32.1 h1:f562zw9cy+GvXzXf0CKlVQ7yHJVYzLfL6JAS4kOAaOc=
+k8s.io/api v0.32.1/go.mod h1:/Yi/BqkuueW1BgpoePYBRdDYfjPF5sgTr5+YqDZra5k=
+k8s.io/apimachinery v0.32.1 h1:683ENpaCBjma4CYqsmZyhEzrGz6cjn1MY/X2jB2hkZs=
+k8s.io/apimachinery v0.32.1/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
+k8s.io/apiserver v0.32.1 h1:oo0OozRos66WFq87Zc5tclUX2r0mymoVHRq8JmR7Aak=
+k8s.io/apiserver v0.32.1/go.mod h1:UcB9tWjBY7aryeI5zAgzVJB/6k7E97bkr1RgqDz0jPw=
+k8s.io/client-go v0.32.1 h1:otM0AxdhdBIaQh7l1Q0jQpmo7WOFIk5FFa4bg6YMdUU=
+k8s.io/client-go v0.32.1/go.mod h1:aTTKZY7MdxUaJ/KiUs8D+GssR9zJZi77ZqtzcGXIiDg=
+k8s.io/component-base v0.32.1 h1:/5IfJ0dHIKBWysGV0yKTFfacZ5yNV1sulPh3ilJjRZk=
+k8s.io/component-base v0.32.1/go.mod h1:j1iMMHi/sqAHeG5z+O9BFNCF698a1u0186zkjMZQ28w=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y=
diff --git a/apps/dashboard/Makefile b/apps/dashboard/Makefile
new file mode 100644
index 00000000000..d95e25e1abd
--- /dev/null
+++ b/apps/dashboard/Makefile
@@ -0,0 +1,18 @@
+.PHONY: generate
+generate:
+ @grafana-app-sdk generate \
+ --source=./kinds/ \
+ --gogenpath=../../pkg/apis \
+ --tsgenpath=../../packages/grafana-schema/src/schema \
+ --grouping=group \
+ --defencoding=none \
+ --genoperatorstate=false \
+ --noschemasinmanifest
+
+ # This is a workaround for SDK codegen not producing correct output for v0alpha1
+ @rm ../../packages/grafana-schema/src/schema/dashboard/v0alpha1/types.spec.gen.ts
+ @cp ./tshack/v0alpha1_spec_gen.ts ../../packages/grafana-schema/src/schema/dashboard/v0alpha1/types.spec.gen.ts
+
+ # Same for v1alpha1
+ @rm ../../packages/grafana-schema/src/schema/dashboard/v1alpha1/types.spec.gen.ts
+ @cp ./tshack/v1alpha1_spec_gen.ts ../../packages/grafana-schema/src/schema/dashboard/v1alpha1/types.spec.gen.ts
diff --git a/apps/dashboard/kinds/cue.mod/module.cue b/apps/dashboard/kinds/cue.mod/module.cue
new file mode 100644
index 00000000000..a3b88f8aa81
--- /dev/null
+++ b/apps/dashboard/kinds/cue.mod/module.cue
@@ -0,0 +1,4 @@
+module: "github.com/grafana/grafana/sdkkinds/dashboard"
+language: {
+ version: "v0.9.0"
+}
diff --git a/apps/dashboard/kinds/dashboard.cue b/apps/dashboard/kinds/dashboard.cue
new file mode 100644
index 00000000000..da09322e0e8
--- /dev/null
+++ b/apps/dashboard/kinds/dashboard.cue
@@ -0,0 +1,68 @@
+package kinds
+
+import (
+ "github.com/grafana/grafana/sdkkinds/dashboard/v0alpha1"
+ "github.com/grafana/grafana/sdkkinds/dashboard/v1alpha1"
+ "github.com/grafana/grafana/sdkkinds/dashboard/v2alpha1"
+)
+
+// Status is the shared status of all dashboard versions.
+DashboardStatus: {
+ // Optional conversion status.
+ conversion?: ConversionStatus
+}
+
+// ConversionStatus is the status of the conversion of the dashboard.
+ConversionStatus: {
+ // Whether from another version has failed.
+ // If true, means that the dashboard is not valid,
+ // and the caller should instead fetch the stored version.
+ failed: bool
+
+ // The version which was stored when the dashboard was created / updated.
+ // Fetching this version should always succeed.
+ storedVersion: string
+
+ // The error message from the conversion.
+ // Empty if the conversion has not failed.
+ error: string
+}
+
+dashboard: {
+ kind: "Dashboard"
+ pluralName: "Dashboards"
+ current: "v0alpha1"
+
+ codegen: {
+ ts: {
+ enabled: true
+ config: {
+ enumsAsUnionTypes: true
+ }
+ }
+ go: {
+ enabled: true
+ }
+ }
+
+ versions: {
+ "v0alpha1": {
+ schema: {
+ spec: v0alpha1.DashboardSpec
+ status: DashboardStatus
+ }
+ }
+ "v1alpha1": {
+ schema: {
+ spec: v1alpha1.DashboardSpec
+ status: DashboardStatus
+ }
+ }
+ "v2alpha1": {
+ schema: {
+ spec: v2alpha1.DashboardSpec
+ status: DashboardStatus
+ }
+ }
+ }
+}
diff --git a/apps/dashboard/kinds/manifest.cue b/apps/dashboard/kinds/manifest.cue
new file mode 100644
index 00000000000..1ec0fb4f21c
--- /dev/null
+++ b/apps/dashboard/kinds/manifest.cue
@@ -0,0 +1,9 @@
+package kinds
+
+manifest: {
+ appName: "dashboard"
+ groupOverride: "dashboard.grafana.app"
+ kinds: [
+ dashboard,
+ ]
+}
diff --git a/apps/dashboard/kinds/v0alpha1/dashboard_spec.cue b/apps/dashboard/kinds/v0alpha1/dashboard_spec.cue
new file mode 100644
index 00000000000..a59f79e97e9
--- /dev/null
+++ b/apps/dashboard/kinds/v0alpha1/dashboard_spec.cue
@@ -0,0 +1,6 @@
+package v0alpha1
+
+// TODO: this outputs nothing.
+// For now, we use unstructured for the spec,
+// but it cannot be produced by the SDK codegen.
+DashboardSpec: [string]: _
diff --git a/apps/dashboard/kinds/v1alpha1/dashboard_spec.cue b/apps/dashboard/kinds/v1alpha1/dashboard_spec.cue
new file mode 100644
index 00000000000..709fb40fd02
--- /dev/null
+++ b/apps/dashboard/kinds/v1alpha1/dashboard_spec.cue
@@ -0,0 +1,6 @@
+package v1alpha1
+
+// TODO: this outputs nothing.
+// For now, we use unstructured for the spec,
+// but it cannot be produced by the SDK codegen.
+DashboardSpec: [string]: _
diff --git a/apps/dashboard/kinds/v2alpha1/dashboard_spec.cue b/apps/dashboard/kinds/v2alpha1/dashboard_spec.cue
new file mode 100644
index 00000000000..a1216596268
--- /dev/null
+++ b/apps/dashboard/kinds/v2alpha1/dashboard_spec.cue
@@ -0,0 +1,923 @@
+package v2alpha1
+
+DashboardSpec: {
+ // Title of dashboard.
+ annotations: [...AnnotationQueryKind]
+
+ // Configuration of dashboard cursor sync behavior.
+ // "Off" for no shared crosshair or tooltip (default).
+ // "Crosshair" for shared crosshair.
+ // "Tooltip" for shared crosshair AND shared tooltip.
+ cursorSync: DashboardCursorSync
+
+ // Description of dashboard.
+ description?: string
+
+ // Whether a dashboard is editable or not.
+ editable?: bool | *true
+
+ elements: [ElementReference.name]: Element
+
+ layout: GridLayoutKind | RowsLayoutKind | ResponsiveGridLayoutKind | TabsLayoutKind
+
+ // Links with references to other dashboards or external websites.
+ links: [...DashboardLink]
+
+ // When set to true, the dashboard will redraw panels at an interval matching the pixel width.
+ // This will keep data "moving left" regardless of the query refresh rate. This setting helps
+ // avoid dashboards presenting stale live data.
+ liveNow?: bool
+
+ // When set to true, the dashboard will load all panels in the dashboard when it's loaded.
+ preload: bool
+
+ // Plugins only. The version of the dashboard installed together with the plugin.
+ // This is used to determine if the dashboard should be updated when the plugin is updated.
+ revision?: uint16
+
+ // Tags associated with dashboard.
+ tags: [...string]
+
+ timeSettings: TimeSettingsSpec
+
+ // Title of dashboard.
+ title: string
+
+ // Configured template variables.
+ variables: [...VariableKind]
+}
+
+// Supported dashboard elements
+Element: PanelKind | LibraryPanelKind // |* more element types in the future
+
+LibraryPanelKind: {
+ kind: "LibraryPanel"
+ spec: LibraryPanelKindSpec
+}
+
+LibraryPanelKindSpec: {
+ // Panel ID for the library panel in the dashboard
+ id: number
+ // Title for the library panel in the dashboard
+ title: string
+
+ libraryPanel: LibraryPanelRef
+}
+
+// A library panel is a reusable panel that you can use in any dashboard.
+// When you make a change to a library panel, that change propagates to all instances of where the panel is used.
+// Library panels streamline reuse of panels across multiple dashboards.
+LibraryPanelRef: {
+ // Library panel name
+ name: string
+ // Library panel uid
+ uid: string
+}
+
+AnnotationPanelFilter: {
+ // Should the specified panels be included or excluded
+ exclude?: bool | *false
+
+ // Panel IDs that should be included or excluded
+ ids: [...uint8]
+}
+
+// "Off" for no shared crosshair or tooltip (default).
+// "Crosshair" for shared crosshair.
+// "Tooltip" for shared crosshair AND shared tooltip.
+DashboardCursorSync: "Off" | "Crosshair" | "Tooltip"
+
+// Links with references to other dashboards or external resources
+DashboardLink: {
+ // Title to display with the link
+ title: string
+ // Link type. Accepted values are dashboards (to refer to another dashboard) and link (to refer to an external resource)
+ // FIXME: The type is generated as `type: DashboardLinkType | dashboardLinkType.Link;` but it should be `type: DashboardLinkType`
+ type: DashboardLinkType
+ // Icon name to be displayed with the link
+ icon: string
+ // Tooltip to display when the user hovers their mouse over it
+ tooltip: string
+ // Link URL. Only required/valid if the type is link
+ url?: string
+ // List of tags to limit the linked dashboards. If empty, all dashboards will be displayed. Only valid if the type is dashboards
+ tags: [...string]
+ // If true, all dashboards links will be displayed in a dropdown. If false, all dashboards links will be displayed side by side. Only valid if the type is dashboards
+ asDropdown: bool | *false
+ // If true, the link will be opened in a new tab
+ targetBlank: bool | *false
+ // If true, includes current template variables values in the link as query params
+ includeVars: bool | *false
+ // If true, includes current time range in the link as query params
+ keepTime: bool | *false
+}
+
+DataSourceRef: {
+ // The plugin type-id
+ type?: string
+
+ // Specific datasource instance
+ uid?: string
+}
+
+// A topic is attached to DataFrame metadata in query results.
+// This specifies where the data should be used.
+DataTopic: "series" | "annotations" | "alertStates" @cog(kind="enum",memberNames="Series|Annotations|AlertStates")
+
+// Transformations allow to manipulate data returned by a query before the system applies a visualization.
+// Using transformations you can: rename fields, join time series data, perform mathematical operations across queries,
+// use the output of one transformation as the input to another transformation, etc.
+DataTransformerConfig: {
+ // Unique identifier of transformer
+ id: string
+ // Disabled transformations are skipped
+ disabled?: bool
+ // Optional frame matcher. When missing it will be applied to all results
+ filter?: MatcherConfig
+ // Where to pull DataFrames from as input to transformation
+ topic?: DataTopic
+ // Options to be passed to the transformer
+ // Valid options depend on the transformer id
+ options: _
+}
+
+DataLink: {
+ title: string
+ url: string
+ targetBlank?: bool
+}
+
+// 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.
+FieldConfigSource: {
+ // Defaults are the options applied to all fields.
+ defaults: FieldConfig
+ // Overrides are the options applied to specific fields overriding the defaults.
+ overrides: [...{
+ matcher: MatcherConfig
+ properties: [...DynamicConfigValue]
+ }]
+}
+
+// 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.
+FieldConfig: {
+ // The display value for this field. This supports template variables blank is auto
+ displayName?: string
+
+ // This can be used by data sources that return and explicit naming structure for values and labels
+ // When this property is configured, this value is used rather than the default naming strategy.
+ displayNameFromDS?: string
+
+ // Human readable field metadata
+ description?: string
+
+ // An explicit path to the field in the datasource. When the frame meta includes a path,
+ // This will default to `${frame.meta.path}/${field.name}
+ //
+ // When defined, this value can be used as an identifier within the datasource scope, and
+ // may be used to update the results
+ path?: string
+
+ // True if data source can write a value to the path. Auth/authz are supported separately
+ writeable?: bool
+
+ // True if data source field supports ad-hoc filters
+ filterable?: bool
+
+ // Unit a field should use. The unit you select is applied to all fields except time.
+ // You can use the units ID availables in Grafana or a custom unit.
+ // Available units in Grafana: https://github.com/grafana/grafana/blob/main/packages/grafana-data/src/valueFormats/categories.ts
+ // As custom unit, you can use the following formats:
+ // `suffix:` for custom unit that should go after value.
+ // `prefix:` for custom unit that should go before value.
+ // `time:` For custom date time formats type for example `time:YYYY-MM-DD`.
+ // `si:` for custom SI units. For example: `si: mF`. This one is a bit more advanced as you can specify both a unit and the source data scale. So if your source data is represented as milli (thousands of) something prefix the unit with that SI scale character.
+ // `count:` for a custom count unit.
+ // `currency:` for custom a currency unit.
+ unit?: string
+
+ // Specify the number of decimals Grafana includes in the rendered value.
+ // If you leave this field blank, Grafana automatically truncates the number of decimals based on the value.
+ // For example 1.1234 will display as 1.12 and 100.456 will display as 100.
+ // To display all decimals, set the unit to `String`.
+ decimals?: number
+
+ // The minimum value used in percentage threshold calculations. Leave blank for auto calculation based on all series and fields.
+ min?: number
+ // The maximum value used in percentage threshold calculations. Leave blank for auto calculation based on all series and fields.
+ max?: number
+
+ // Convert input values into a display string
+ mappings?: [...ValueMapping]
+
+ // Map numeric values to states
+ thresholds?: ThresholdsConfig
+
+ // Panel color configuration
+ color?: FieldColor
+
+ // The behavior when clicking on a result
+ links?: [...]
+
+ // Alternative to empty string
+ noValue?: string
+
+ // custom is specified by the FieldConfig field
+ // in panel plugin schemas.
+ custom?: {...}
+}
+
+DynamicConfigValue: {
+ id: string | *""
+ value?: _
+}
+
+// Matcher is a predicate configuration. Based on the config a set of field(s) or values is filtered in order to apply override / transformation.
+// It comes with in id ( to resolve implementation from registry) and a configuration that’s specific to a particular matcher type.
+MatcherConfig: {
+ // The matcher id. This is used to find the matcher implementation from registry.
+ id: string | *""
+ // The matcher options. This is specific to the matcher implementation.
+ options?: _
+}
+
+Threshold: {
+ value: number
+ color: string
+}
+
+ThresholdsMode: "absolute" | "percentage"
+
+ThresholdsConfig: {
+ mode: ThresholdsMode
+ steps: [...Threshold]
+}
+
+ValueMapping: ValueMap | RangeMap | RegexMap | SpecialValueMap
+
+// Supported value mapping types
+// `value`: Maps text values to a color or different display text and color. For example, you can configure a value mapping so that all instances of the value 10 appear as Perfection! rather than the number.
+// `range`: Maps numerical ranges to a display text and color. For example, if a value is within a certain range, you can configure a range value mapping to display Low or High rather than the number.
+// `regex`: Maps regular expressions to replacement text and a color. For example, if a value is www.example.com, you can configure a regex value mapping so that Grafana displays www and truncates the domain.
+// `special`: Maps special values like Null, NaN (not a number), and boolean values like true and false to a display text and color. See SpecialValueMatch to see the list of special values. For example, you can configure a special value mapping so that null values appear as N/A.
+MappingType: "value" | "range" | "regex" | "special" @cog(kind="enum",memberNames="ValueToText|RangeToText|RegexToText|SpecialValue")
+
+// Maps text values to a color or different display text and color.
+// For example, you can configure a value mapping so that all instances of the value 10 appear as Perfection! rather than the number.
+ValueMap: {
+ // TODO (@radiohead): Something broke in cog / app SDK codegen
+ // And this is no longer producing valid TS / Go output
+ // type: MappingType & "value"
+ type: "value"
+ // Map with : ValueMappingResult. For example: { "10": { text: "Perfection!", color: "green" } }
+ options: [string]: ValueMappingResult
+}
+
+// Maps numerical ranges to a display text and color.
+// For example, if a value is within a certain range, you can configure a range value mapping to display Low or High rather than the number.
+RangeMap: {
+ // TODO (@radiohead): Something broke in cog / app SDK codegen
+ // And this is no longer producing valid TS / Go output
+ // type: MappingType & "range"
+ type: "range"
+ // Range to match against and the result to apply when the value is within the range
+ options: {
+ // Min value of the range. It can be null which means -Infinity
+ from: float64 | null
+ // Max value of the range. It can be null which means +Infinity
+ to: float64 | null
+ // Config to apply when the value is within the range
+ result: ValueMappingResult
+ }
+}
+
+// Maps regular expressions to replacement text and a color.
+// For example, if a value is www.example.com, you can configure a regex value mapping so that Grafana displays www and truncates the domain.
+RegexMap: {
+ // TODO (@radiohead): Something broke in cog / app SDK codegen
+ // And this is no longer producing valid TS / Go output
+ // type: MappingType & "regex"
+ type: "regex"
+ // Regular expression to match against and the result to apply when the value matches the regex
+ options: {
+ // Regular expression to match against
+ pattern: string
+ // Config to apply when the value matches the regex
+ result: ValueMappingResult
+ }
+}
+
+// Maps special values like Null, NaN (not a number), and boolean values like true and false to a display text and color.
+// See SpecialValueMatch to see the list of special values.
+// For example, you can configure a special value mapping so that null values appear as N/A.
+SpecialValueMap: {
+ // TODO (@radiohead): Something broke in cog / app SDK codegen
+ // And this is no longer producing valid TS / Go output
+ // type: MappingType & "special"
+ type: "special"
+ options: {
+ // Special value to match against
+ match: SpecialValueMatch
+ // Config to apply when the value matches the special value
+ result: ValueMappingResult
+ }
+}
+
+// Special value types supported by the `SpecialValueMap`
+SpecialValueMatch: "true" | "false" | "null" | "nan" | "null+nan" | "empty" @cog(kind="enum",memberNames="True|False|Null|NaN|NullAndNaN|Empty")
+
+// Result used as replacement with text and color when the value matches
+ValueMappingResult: {
+ // Text to display when the value matches
+ text?: string
+ // Text to use when the value matches
+ color?: string
+ // Icon to display when the value matches. Only specific visualizations.
+ icon?: string
+ // Position in the mapping array. Only used internally.
+ index?: int32
+}
+
+// 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.
+// Accepted values are:
+// `thresholds`: From thresholds. Informs Grafana to take the color from the matching threshold
+// `palette-classic`: Classic palette. Grafana will assign color by looking up a color in a palette by series index. Useful for Graphs and pie charts and other categorical data visualizations
+// `palette-classic-by-name`: Classic palette (by name). Grafana will assign color by looking up a color in a palette by series name. Useful for Graphs and pie charts and other categorical data visualizations
+// `continuous-GrYlRd`: ontinuous Green-Yellow-Red palette mode
+// `continuous-RdYlGr`: Continuous Red-Yellow-Green palette mode
+// `continuous-BlYlRd`: Continuous Blue-Yellow-Red palette mode
+// `continuous-YlRd`: Continuous Yellow-Red palette mode
+// `continuous-BlPu`: Continuous Blue-Purple palette mode
+// `continuous-YlBl`: Continuous Yellow-Blue palette mode
+// `continuous-blues`: Continuous Blue palette mode
+// `continuous-reds`: Continuous Red palette mode
+// `continuous-greens`: Continuous Green palette mode
+// `continuous-purples`: Continuous Purple palette mode
+// `shades`: Shades of a single color. Specify a single color, useful in an override rule.
+// `fixed`: Fixed color mode. Specify a single color, useful in an override rule.
+FieldColorModeId: "thresholds" | "palette-classic" | "palette-classic-by-name" | "continuous-GrYlRd" | "continuous-RdYlGr" | "continuous-BlYlRd" | "continuous-YlRd" | "continuous-BlPu" | "continuous-YlBl" | "continuous-blues" | "continuous-reds" | "continuous-greens" | "continuous-purples" | "fixed" | "shades"
+
+// Defines how to assign a series color from "by value" color schemes. For example for an aggregated data points like a timeseries, the color can be assigned by the min, max or last value.
+FieldColorSeriesByMode: "min" | "max" | "last"
+
+// Map a field to a color.
+FieldColor: {
+ // The main color scheme mode.
+ mode: FieldColorModeId
+ // The fixed color value for fixed or shades color modes.
+ fixedColor?: string
+ // Some visualizations need to know how to assign a series color from by value color schemes.
+ seriesBy?: FieldColorSeriesByMode
+}
+
+// Dashboard Link type. Accepted values are dashboards (to refer to another dashboard) and link (to refer to an external resource)
+DashboardLinkType: "link" | "dashboards"
+
+// --- Common types ---
+Kind: {
+ kind: string
+ spec: _
+ metadata?: _
+}
+
+// --- Kinds ---
+VizConfigSpec: {
+ pluginVersion: string
+ options: [string]: _
+ fieldConfig: FieldConfigSource
+}
+
+VizConfigKind: {
+ // The kind of a VizConfigKind is the plugin ID
+ kind: string
+ spec: VizConfigSpec
+}
+
+AnnotationQuerySpec: {
+ datasource?: DataSourceRef
+ query?: DataQueryKind
+ enable: bool
+ hide: bool
+ iconColor: string
+ name: string
+ builtIn?: bool | *false
+ filter?: AnnotationPanelFilter
+}
+
+AnnotationQueryKind: {
+ kind: "AnnotationQuery"
+ spec: AnnotationQuerySpec
+}
+
+QueryOptionsSpec: {
+ timeFrom?: string
+ maxDataPoints?: int
+ timeShift?: string
+ queryCachingTTL?: int
+ interval?: string
+ cacheTimeout?: string
+ hideTimeOverride?: bool
+}
+
+DataQueryKind: {
+ // The kind of a DataQueryKind is the datasource type
+ kind: string
+ spec: [string]: _
+}
+
+PanelQuerySpec: {
+ query: DataQueryKind
+ datasource?: DataSourceRef
+
+ refId: string
+ hidden: bool
+}
+
+PanelQueryKind: {
+ kind: "PanelQuery"
+ spec: PanelQuerySpec
+}
+
+TransformationKind: {
+ // The kind of a TransformationKind is the transformation ID
+ kind: string
+ spec: DataTransformerConfig
+}
+
+QueryGroupSpec: {
+ queries: [...PanelQueryKind]
+ transformations: [...TransformationKind]
+ queryOptions: QueryOptionsSpec
+}
+
+QueryGroupKind: {
+ kind: "QueryGroup"
+ spec: QueryGroupSpec
+}
+
+TimeRangeOption: {
+ display: string | *"Last 6 hours"
+ from: string | *"now-6h"
+ to: string | *"now"
+}
+
+// Time configuration
+// It defines the default time config for the time picker, the refresh picker for the specific dashboard.
+TimeSettingsSpec: {
+ // Timezone of dashboard. Accepted values are IANA TZDB zone ID or "browser" or "utc".
+ timezone?: string | *"browser"
+ // Start time range for dashboard.
+ // Accepted values are relative time strings like "now-6h" or absolute time strings like "2020-07-10T08:00:00.000Z".
+ from: string | *"now-6h"
+ // End time range for dashboard.
+ // Accepted values are relative time strings like "now-6h" or absolute time strings like "2020-07-10T08:00:00.000Z".
+ to: string | *"now"
+ // Refresh rate of dashboard. Represented via interval string, e.g. "5s", "1m", "1h", "1d".
+ autoRefresh: string // v1: refresh
+ // Interval options available in the refresh picker dropdown.
+ autoRefreshIntervals: [...string] | *["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"] // v1: timepicker.refresh_intervals
+ // Selectable options available in the time picker dropdown. Has no effect on provisioned dashboard.
+ quickRanges?: [...TimeRangeOption] // v1: timepicker.quick_ranges , not exposed in the UI
+ // Whether timepicker is visible or not.
+ hideTimepicker: bool // v1: timepicker.hidden
+ // Day when the week starts. Expressed by the name of the day in lowercase, e.g. "monday".
+ weekStart?: "saturday" | "monday" | "sunday"
+ // The month that the fiscal year starts on. 0 = January, 11 = December
+ fiscalYearStartMonth: int
+ // Override the now time by entering a time delay. Use this option to accommodate known delays in data aggregation to avoid null values.
+ nowDelay?: string // v1: timepicker.nowDelay
+}
+
+RepeatMode: "variable" // other repeat modes will be added in the future: label, frame
+
+RepeatOptions: {
+ mode: RepeatMode
+ value: string
+ direction?: "h" | "v"
+ maxPerRow?: int
+}
+
+RowRepeatOptions: {
+ mode: RepeatMode
+ value: string
+}
+
+ResponsiveGridRepeatOptions: {
+ mode: RepeatMode
+ value: string
+}
+
+GridLayoutItemSpec: {
+ x: int
+ y: int
+ width: int
+ height: int
+ element: ElementReference // reference to a PanelKind from dashboard.spec.elements Expressed as JSON Schema reference
+ repeat?: RepeatOptions
+}
+
+GridLayoutItemKind: {
+ kind: "GridLayoutItem"
+ spec: GridLayoutItemSpec
+}
+
+GridLayoutRowKind: {
+ kind: "GridLayoutRow"
+ spec: GridLayoutRowSpec
+}
+
+GridLayoutRowSpec: {
+ y: int
+ collapsed: bool
+ title: string
+ elements: [...GridLayoutItemKind] // Grid items in the row will have their Y value be relative to the rows Y value. This means a panel positioned at Y: 0 in a row with Y: 10 will be positioned at Y: 11 (row header has a heigh of 1) in the dashboard.
+ repeat?: RowRepeatOptions
+}
+
+GridLayoutSpec: {
+ items: [...GridLayoutItemKind | GridLayoutRowKind]
+}
+
+GridLayoutKind: {
+ kind: "GridLayout"
+ spec: GridLayoutSpec
+}
+
+RowsLayoutKind: {
+ kind: "RowsLayout"
+ spec: RowsLayoutSpec
+}
+
+RowsLayoutSpec: {
+ rows: [...RowsLayoutRowKind]
+}
+
+RowsLayoutRowKind: {
+ kind: "RowsLayoutRow"
+ spec: RowsLayoutRowSpec
+}
+
+RowsLayoutRowSpec: {
+ title?: string
+ collapsed: bool
+ repeat?: RowRepeatOptions
+ layout: GridLayoutKind | ResponsiveGridLayoutKind | TabsLayoutKind
+}
+
+ResponsiveGridLayoutKind: {
+ kind: "ResponsiveGridLayout"
+ spec: ResponsiveGridLayoutSpec
+}
+
+ResponsiveGridLayoutSpec: {
+ row: string
+ col: string
+ items: [...ResponsiveGridLayoutItemKind]
+}
+
+ResponsiveGridLayoutItemKind: {
+ kind: "ResponsiveGridLayoutItem"
+ spec: ResponsiveGridLayoutItemSpec
+}
+
+ResponsiveGridLayoutItemSpec: {
+ element: ElementReference
+ repeat?: ResponsiveGridRepeatOptions
+}
+
+TabsLayoutKind: {
+ kind: "TabsLayout"
+ spec: TabsLayoutSpec
+}
+
+TabsLayoutSpec: {
+ tabs: [...TabsLayoutTabKind]
+}
+
+TabsLayoutTabKind: {
+ kind: "TabsLayoutTab"
+ spec: TabsLayoutTabSpec
+}
+
+TabsLayoutTabSpec: {
+ title?: string
+ layout: GridLayoutKind | RowsLayoutKind | ResponsiveGridLayoutKind
+}
+
+PanelSpec: {
+ id: number
+ title: string
+ description: string
+ links: [...DataLink]
+ data: QueryGroupKind
+ vizConfig: VizConfigKind
+ transparent?: bool
+}
+
+PanelKind: {
+ kind: "Panel"
+ spec: PanelSpec
+}
+
+ElementReference: {
+ kind: "ElementReference"
+ name: string
+}
+
+// Start FIXME: variables - in CUE PR - this are things that should be added into the cue schema
+// TODO: properties such as `hide`, `skipUrlSync`, `multi` are type boolean, and in the old schema they are conditional,
+// should we make them conditional in the new schema as well? or should we make them required but default to false?
+
+// Variable types
+VariableValue: VariableValueSingle | [...VariableValueSingle]
+
+VariableValueSingle: string | bool | number | CustomVariableValue
+
+// Custom formatter variable
+CustomFormatterVariable: {
+ name: string
+ type: VariableType
+ multi: bool
+ includeAll: bool
+}
+
+// Custom variable value
+CustomVariableValue: {
+ // The format name or function used in the expression
+ formatter: *null | string | VariableCustomFormatterFn
+}
+
+// Custom formatter function
+VariableCustomFormatterFn: {
+ value: _
+ legacyVariableModel: {
+ name: string
+ type: VariableType
+ multi: bool
+ includeAll: bool
+ }
+ legacyDefaultFormatter?: VariableCustomFormatterFn
+}
+
+// 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
+VariableType: "query" | "adhoc" | "groupby" | "constant" | "datasource" | "interval" | "textbox" | "custom" |
+ "system" | "snapshot"
+
+VariableKind: QueryVariableKind | TextVariableKind | ConstantVariableKind | DatasourceVariableKind | IntervalVariableKind | CustomVariableKind | GroupByVariableKind | AdhocVariableKind
+
+// Sort variable options
+// Accepted values are:
+// `disabled`: No sorting
+// `alphabeticalAsc`: Alphabetical ASC
+// `alphabeticalDesc`: Alphabetical DESC
+// `numericalAsc`: Numerical ASC
+// `numericalDesc`: Numerical DESC
+// `alphabeticalCaseInsensitiveAsc`: Alphabetical Case Insensitive ASC
+// `alphabeticalCaseInsensitiveDesc`: Alphabetical Case Insensitive DESC
+// `naturalAsc`: Natural ASC
+// `naturalDesc`: Natural DESC
+// VariableSort enum with default value
+VariableSort: "disabled" | "alphabeticalAsc" | "alphabeticalDesc" | "numericalAsc" | "numericalDesc" | "alphabeticalCaseInsensitiveAsc" | "alphabeticalCaseInsensitiveDesc" | "naturalAsc" | "naturalDesc"
+
+// Options to config when to refresh a variable
+// `never`: Never refresh the variable
+// `onDashboardLoad`: Queries the data source every time the dashboard loads.
+// `onTimeRangeChanged`: Queries the data source when the dashboard time range changes.
+VariableRefresh: *"never" | "onDashboardLoad" | "onTimeRangeChanged"
+
+// Determine if the variable shows on dashboard
+// Accepted values are `dontHide` (show label and value), `hideLabel` (show value only), `hideVariable` (show nothing).
+VariableHide: *"dontHide" | "hideLabel" | "hideVariable"
+
+// FIXME: should we introduce this? --- Variable value option
+VariableValueOption: {
+ label: string
+ value: VariableValueSingle
+ group?: string
+}
+
+// Variable option specification
+VariableOption: {
+ // Whether the option is selected or not
+ selected?: bool
+ // Text to be displayed for the option
+ text: string | [...string]
+ // Value of the option
+ value: string | [...string]
+}
+
+// Query variable specification
+QueryVariableSpec: {
+ name: string | *""
+ current: VariableOption | *{
+ text: ""
+ value: ""
+ }
+ label?: string
+ hide: VariableHide
+ refresh: VariableRefresh
+ skipUrlSync: bool | *false
+ description?: string
+ datasource?: DataSourceRef
+ query: DataQueryKind
+ regex: string | *""
+ sort: VariableSort
+ definition?: string
+ options: [...VariableOption] | *[]
+ multi: bool | *false
+ includeAll: bool | *false
+ allValue?: string
+ placeholder?: string
+}
+
+// Query variable kind
+QueryVariableKind: {
+ kind: "QueryVariable"
+ spec: QueryVariableSpec
+}
+
+// Text variable specification
+TextVariableSpec: {
+ name: string | *""
+ current: VariableOption | *{
+ text: ""
+ value: ""
+ }
+ query: string | *""
+ label?: string
+ hide: VariableHide
+ skipUrlSync: bool | *false
+ description?: string
+}
+
+// Text variable kind
+TextVariableKind: {
+ kind: "TextVariable"
+ spec: TextVariableSpec
+}
+
+// Constant variable specification
+ConstantVariableSpec: {
+ name: string | *""
+ query: string | *""
+ current: VariableOption | *{
+ text: ""
+ value: ""
+ }
+ label?: string
+ hide: VariableHide
+ skipUrlSync: bool | *false
+ description?: string
+}
+
+// Constant variable kind
+ConstantVariableKind: {
+ kind: "ConstantVariable"
+ spec: ConstantVariableSpec
+}
+
+// Datasource variable specification
+DatasourceVariableSpec: {
+ name: string | *""
+ pluginId: string | *""
+ refresh: VariableRefresh
+ regex: string | *""
+ current: VariableOption | *{
+ text: ""
+ value: ""
+ }
+ options: [...VariableOption] | *[]
+ multi: bool | *false
+ includeAll: bool | *false
+ allValue?: string
+ label?: string
+ hide: VariableHide
+ skipUrlSync: bool | *false
+ description?: string
+}
+
+// Datasource variable kind
+DatasourceVariableKind: {
+ kind: "DatasourceVariable"
+ spec: DatasourceVariableSpec
+}
+
+// Interval variable specification
+IntervalVariableSpec: {
+ name: string | *""
+ query: string | *""
+ current: VariableOption | *{
+ text: ""
+ value: ""
+ }
+ options: [...VariableOption] | *[]
+ auto: bool | *false
+ auto_min: string | *""
+ auto_count: int | *0
+ refresh: VariableRefresh
+ label?: string
+ hide: VariableHide
+ skipUrlSync: bool | *false
+ description?: string
+}
+
+// Interval variable kind
+IntervalVariableKind: {
+ kind: "IntervalVariable"
+ spec: IntervalVariableSpec
+}
+
+// Custom variable specification
+CustomVariableSpec: {
+ name: string | *""
+ query: string | *""
+ current: VariableOption
+ options: [...VariableOption] | *[]
+ multi: bool | *false
+ includeAll: bool | *false
+ allValue?: string
+ label?: string
+ hide: VariableHide
+ skipUrlSync: bool | *false
+ description?: string
+}
+
+// Custom variable kind
+CustomVariableKind: {
+ kind: "CustomVariable"
+ spec: CustomVariableSpec
+}
+
+// GroupBy variable specification
+GroupByVariableSpec: {
+ name: string | *""
+ datasource?: DataSourceRef
+ current: VariableOption | *{
+ text: ""
+ value: ""
+ }
+ options: [...VariableOption] | *[]
+ multi: bool | *false
+ label?: string
+ hide: VariableHide
+ skipUrlSync: bool | *false
+ description?: string
+}
+
+// Group variable kind
+GroupByVariableKind: {
+ kind: "GroupByVariable"
+ spec: GroupByVariableSpec
+}
+
+// Adhoc variable specification
+AdhocVariableSpec: {
+ name: string | *""
+ datasource?: DataSourceRef
+ baseFilters: [...AdHocFilterWithLabels] | *[]
+ filters: [...AdHocFilterWithLabels] | *[]
+ defaultKeys: [...MetricFindValue] | *[]
+ label?: string
+ hide: VariableHide
+ skipUrlSync: bool | *false
+ description?: string
+}
+
+// Define the MetricFindValue type
+MetricFindValue: {
+ text: string
+ value?: string | number
+ group?: string
+ expandable?: bool
+}
+
+// Define the AdHocFilterWithLabels type
+AdHocFilterWithLabels: {
+ key: string
+ operator: string
+ value: string
+ values?: [...string]
+ keyLabel?: string
+ valueLabels?: [...string]
+ forceEdit?: bool
+ // @deprecated
+ condition?: string
+}
+
+// Adhoc variable kind
+AdhocVariableKind: {
+ kind: "AdhocVariable"
+ spec: AdhocVariableSpec
+}
diff --git a/apps/dashboard/tshack/v0alpha1_spec_gen.ts b/apps/dashboard/tshack/v0alpha1_spec_gen.ts
new file mode 100644
index 00000000000..3de7e52c72e
--- /dev/null
+++ b/apps/dashboard/tshack/v0alpha1_spec_gen.ts
@@ -0,0 +1,7 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+export interface Spec {
+ [key: string]: any;
+}
+
+export const defaultSpec = (): Spec => ({});
diff --git a/apps/dashboard/tshack/v1alpha1_spec_gen.ts b/apps/dashboard/tshack/v1alpha1_spec_gen.ts
new file mode 100644
index 00000000000..3de7e52c72e
--- /dev/null
+++ b/apps/dashboard/tshack/v1alpha1_spec_gen.ts
@@ -0,0 +1,7 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+export interface Spec {
+ [key: string]: any;
+}
+
+export const defaultSpec = (): Spec => ({});
diff --git a/apps/investigation/Makefile b/apps/investigation/Makefile
deleted file mode 100644
index b4ea1f97c89..00000000000
--- a/apps/investigation/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-.PHONY: generate
-generate:
- @grafana-app-sdk generate -g ./pkg/apis --kindgrouping=group --postprocess --crdencoding none
diff --git a/apps/investigation/kinds/cue.mod/module.cue b/apps/investigation/kinds/cue.mod/module.cue
deleted file mode 100644
index 80ce68f4833..00000000000
--- a/apps/investigation/kinds/cue.mod/module.cue
+++ /dev/null
@@ -1,2 +0,0 @@
-module: "github.com/grafana/grafana/apps/investigation/kinds"
-language: version: "v0.8.2"
diff --git a/apps/investigation/kinds/investigation.cue b/apps/investigation/kinds/investigation.cue
deleted file mode 100644
index 64d4b9b3105..00000000000
--- a/apps/investigation/kinds/investigation.cue
+++ /dev/null
@@ -1,96 +0,0 @@
-package kinds
-
-// This is our Investigation definition, which contains metadata about the kind, and the kind's schema
-investigation: {
- group: "investigation"
- kind: "Investigation"
- pluralName: "Investigations"
- scope: "Namespaced"
-
- apiResource: {
- groupOverride: "investigation.grafana.app"
- }
-
- codegen: {
- frontend: false
- backend: true
- }
-
- current: "v1alpha1"
- versions: {
- "v1alpha1": {
- version: "v1alpha1"
- schema: {
- // spec is the schema of our resource. The spec should include all the user-ediable information for the kind.
- spec: #InvestigationSpec
- }
- }
- }
-}
-
-#InvestigationSpec: {
- title: string
- status: "open" | "closed"
- items: [...#InvestigationItem]
-}
-
-// InvestigationItem is an item in an investigation.
-#InvestigationItem: {
- id: string
- title: string
- // type is the type of the item "timeseries", "heatmap", "log-table" (not an enum to allow for future extensions).
- type: string
- // url is the URL to the item.
- url: string
- // origin is where the item was created from.
- origin: string // "explore-metrics", "explore-logs", "explore-traces" (not an enum to allow for future extensions)
- // iconPath (optional) is the path to the icon for the item.
- iconPath?: string
- // timeRange (optional) is the time range of the item.
- timeRange: #AbsoluteTimeRange
- // note (optional) is a comment on the item.
- note?: [...#Comment]
- // queryType is the type of the query used to generate this item.
- queryType: "logs" | "metrics"
- // dataQuery contains the query used to generate this item.
- dataQuery: #DataQueryLogs | #DataQueryMetrics
-}
-
-// DataQueryLogs is a data query for logs.
-#DataQueryLogs: {
- // refId is the reference ID of the query.
- refId: string
- // datasource is the datasource of the query.
- datasource: #DatasourceRef
- // expr is the expression of the query.
- expr: string
- // maxLines (optional) is used to limit the number of log rows returned.
- maxLines?: int64
-}
-
-// DataQueryMetrics is a data query for metrics.
-#DataQueryMetrics: {
- refId: string
- datasource: #DatasourceRef
- expr: string
-}
-
-// Comment is a comment on an investigation item.
-#Comment: {
- authorUserID: string
- bodyMarkdown: string
-}
-
-// DatasourceRef is a reference to a datasource.
-#DatasourceRef: {
- uid: string
- type: string
- apiVersion: string
- name: string
-}
-
-// AbsoluteTimeRange is a time range specified by absolute timestamps.
-#AbsoluteTimeRange: {
- from: number
- to: number
-}
diff --git a/apps/investigation/pkg/apis/investigation/v1alpha1/investigation_metadata_gen.go b/apps/investigation/pkg/apis/investigation/v1alpha1/investigation_metadata_gen.go
deleted file mode 100644
index 8a8e44d35ac..00000000000
--- a/apps/investigation/pkg/apis/investigation/v1alpha1/investigation_metadata_gen.go
+++ /dev/null
@@ -1,32 +0,0 @@
-package v1alpha1
-
-import (
- "time"
-)
-
-// InvestigationMetadata defines model for InvestigationMetadata.
-type InvestigationMetadata struct {
- CreatedBy string `json:"createdBy"`
- CreationTimestamp time.Time `json:"creationTimestamp"`
- DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"`
- Finalizers []string `json:"finalizers"`
- Generation int64 `json:"generation"`
- Labels map[string]string `json:"labels"`
- ResourceVersion string `json:"resourceVersion"`
- Uid string `json:"uid"`
- UpdateTimestamp time.Time `json:"updateTimestamp"`
- UpdatedBy string `json:"updatedBy"`
-}
-
-// _kubeObjectMetadata is metadata found in a kubernetes object's metadata field.
-// It is not exhaustive and only includes fields which may be relevant to a kind's implementation,
-// As it is also intended to be generic enough to function with any API Server.
-type InvestigationKubeObjectMetadata struct {
- CreationTimestamp time.Time `json:"creationTimestamp"`
- DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"`
- Finalizers []string `json:"finalizers"`
- Generation int64 `json:"generation"`
- Labels map[string]string `json:"labels"`
- ResourceVersion string `json:"resourceVersion"`
- Uid string `json:"uid"`
-}
diff --git a/apps/investigation/pkg/apis/investigation/v1alpha1/investigation_spec_gen.go b/apps/investigation/pkg/apis/investigation/v1alpha1/investigation_spec_gen.go
deleted file mode 100644
index 1ed1173238b..00000000000
--- a/apps/investigation/pkg/apis/investigation/v1alpha1/investigation_spec_gen.go
+++ /dev/null
@@ -1,107 +0,0 @@
-package v1alpha1
-
-// Defines values for InvestigationInvestigationItemQueryType.
-const (
- InvestigationInvestigationItemQueryTypeLogs InvestigationInvestigationItemQueryType = "logs"
- InvestigationInvestigationItemQueryTypeMetrics InvestigationInvestigationItemQueryType = "metrics"
-)
-
-// Defines values for InvestigationSpecStatus.
-const (
- InvestigationSpecStatusClosed InvestigationSpecStatus = "closed"
- InvestigationSpecStatusOpen InvestigationSpecStatus = "open"
-)
-
-// AbsoluteTimeRange is a time range specified by absolute timestamps.
-// +k8s:openapi-gen=true
-type InvestigationAbsoluteTimeRange struct {
- From float32 `json:"from"`
- To float32 `json:"to"`
-}
-
-// Comment is a comment on an investigation item.
-// +k8s:openapi-gen=true
-type InvestigationComment struct {
- AuthorUserID string `json:"authorUserID"`
- BodyMarkdown string `json:"bodyMarkdown"`
-}
-
-// DataQueryLogs is a data query for logs.
-// +k8s:openapi-gen=true
-type InvestigationDataQueryLogs struct {
- // DatasourceRef is a reference to a datasource.
- Datasource InvestigationDatasourceRef `json:"datasource"`
-
- // expr is the expression of the query.
- Expr string `json:"expr"`
-
- // maxLines (optional) is used to limit the number of log rows returned.
- MaxLines *int64 `json:"maxLines,omitempty"`
-
- // refId is the reference ID of the query.
- RefId string `json:"refId"`
-}
-
-// DataQueryMetrics is a data query for metrics.
-// +k8s:openapi-gen=true
-type InvestigationDataQueryMetrics struct {
- // DatasourceRef is a reference to a datasource.
- Datasource InvestigationDatasourceRef `json:"datasource"`
- Expr string `json:"expr"`
- RefId string `json:"refId"`
-}
-
-// DatasourceRef is a reference to a datasource.
-// +k8s:openapi-gen=true
-type InvestigationDatasourceRef struct {
- ApiVersion string `json:"apiVersion"`
- Name string `json:"name"`
- Type string `json:"type"`
- Uid string `json:"uid"`
-}
-
-// InvestigationItem is an item in an investigation.
-// +k8s:openapi-gen=true
-type InvestigationInvestigationItem struct {
- // dataQuery contains the query used to generate this item.
- DataQuery interface{} `json:"dataQuery"`
-
- // iconPath (optional) is the path to the icon for the item.
- IconPath *string `json:"iconPath,omitempty"`
- Id string `json:"id"`
-
- // note (optional) is a comment on the item.
- Note []InvestigationComment `json:"note,omitempty"`
-
- // origin is where the item was created from.
- Origin string `json:"origin"`
-
- // queryType is the type of the query used to generate this item.
- QueryType InvestigationInvestigationItemQueryType `json:"queryType"`
-
- // AbsoluteTimeRange is a time range specified by absolute timestamps.
- TimeRange InvestigationAbsoluteTimeRange `json:"timeRange"`
- Title string `json:"title"`
-
- // type is the type of the item "timeseries", "heatmap", "log-table" (not an enum to allow for future extensions).
- Type string `json:"type"`
-
- // url is the URL to the item.
- Url string `json:"url"`
-}
-
-// InvestigationInvestigationItemQueryType queryType is the type of the query used to generate this item.
-// +k8s:openapi-gen=true
-type InvestigationInvestigationItemQueryType string
-
-// InvestigationSpec defines model for InvestigationSpec.
-// +k8s:openapi-gen=true
-type InvestigationSpec struct {
- Items []InvestigationInvestigationItem `json:"items"`
- Status InvestigationSpecStatus `json:"status"`
- Title string `json:"title"`
-}
-
-// InvestigationSpecStatus defines model for InvestigationSpec.Status.
-// +k8s:openapi-gen=true
-type InvestigationSpecStatus string
diff --git a/apps/investigation/pkg/apis/investigation/v1alpha1/investigation_status_gen.go b/apps/investigation/pkg/apis/investigation/v1alpha1/investigation_status_gen.go
deleted file mode 100644
index 3f0870f9c04..00000000000
--- a/apps/investigation/pkg/apis/investigation/v1alpha1/investigation_status_gen.go
+++ /dev/null
@@ -1,70 +0,0 @@
-package v1alpha1
-
-// Defines values for InvestigationOperatorStateState.
-const (
- InvestigationOperatorStateStateFailed InvestigationOperatorStateState = "failed"
- InvestigationOperatorStateStateInProgress InvestigationOperatorStateState = "in_progress"
- InvestigationOperatorStateStateSuccess InvestigationOperatorStateState = "success"
-)
-
-// Defines values for InvestigationstatusOperatorStateState.
-const (
- InvestigationstatusOperatorStateStateFailed InvestigationstatusOperatorStateState = "failed"
- InvestigationstatusOperatorStateStateInProgress InvestigationstatusOperatorStateState = "in_progress"
- InvestigationstatusOperatorStateStateSuccess InvestigationstatusOperatorStateState = "success"
-)
-
-// InvestigationOperatorState defines model for InvestigationOperatorState.
-// +k8s:openapi-gen=true
-type InvestigationOperatorState struct {
- // descriptiveState is an optional more descriptive state field which has no requirements on format
- DescriptiveState *string `json:"descriptiveState,omitempty"`
-
- // details contains any extra information that is operator-specific
- Details map[string]interface{} `json:"details,omitempty"`
-
- // lastEvaluation is the ResourceVersion last evaluated
- LastEvaluation string `json:"lastEvaluation"`
-
- // state describes the state of the lastEvaluation.
- // It is limited to three possible states for machine evaluation.
- State InvestigationOperatorStateState `json:"state"`
-}
-
-// InvestigationOperatorStateState state describes the state of the lastEvaluation.
-// It is limited to three possible states for machine evaluation.
-// +k8s:openapi-gen=true
-type InvestigationOperatorStateState string
-
-// InvestigationStatus defines model for InvestigationStatus.
-// +k8s:openapi-gen=true
-type InvestigationStatus struct {
- // additionalFields is reserved for future use
- AdditionalFields map[string]interface{} `json:"additionalFields,omitempty"`
-
- // operatorStates is a map of operator ID to operator state evaluations.
- // Any operator which consumes this kind SHOULD add its state evaluation information to this field.
- OperatorStates map[string]InvestigationstatusOperatorState `json:"operatorStates,omitempty"`
-}
-
-// InvestigationstatusOperatorState defines model for Investigationstatus.#OperatorState.
-// +k8s:openapi-gen=true
-type InvestigationstatusOperatorState struct {
- // descriptiveState is an optional more descriptive state field which has no requirements on format
- DescriptiveState *string `json:"descriptiveState,omitempty"`
-
- // details contains any extra information that is operator-specific
- Details map[string]interface{} `json:"details,omitempty"`
-
- // lastEvaluation is the ResourceVersion last evaluated
- LastEvaluation string `json:"lastEvaluation"`
-
- // state describes the state of the lastEvaluation.
- // It is limited to three possible states for machine evaluation.
- State InvestigationstatusOperatorStateState `json:"state"`
-}
-
-// InvestigationstatusOperatorStateState state describes the state of the lastEvaluation.
-// It is limited to three possible states for machine evaluation.
-// +k8s:openapi-gen=true
-type InvestigationstatusOperatorStateState string
diff --git a/apps/investigation/pkg/apis/investigation/v1alpha1/zz_openapi_gen.go b/apps/investigation/pkg/apis/investigation/v1alpha1/zz_openapi_gen.go
deleted file mode 100644
index 356c42c01fc..00000000000
--- a/apps/investigation/pkg/apis/investigation/v1alpha1/zz_openapi_gen.go
+++ /dev/null
@@ -1,593 +0,0 @@
-//go:build !ignore_autogenerated
-// +build !ignore_autogenerated
-
-// Code generated by grafana-app-sdk. DO NOT EDIT.
-
-package v1alpha1
-
-import (
- common "k8s.io/kube-openapi/pkg/common"
- spec "k8s.io/kube-openapi/pkg/validation/spec"
-)
-
-func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
- return map[string]common.OpenAPIDefinition{
- "github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.Investigation": schema_pkg_apis_investigation_v1alpha1_Investigation(ref),
- "github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationAbsoluteTimeRange": schema_pkg_apis_investigation_v1alpha1_InvestigationAbsoluteTimeRange(ref),
- "github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationComment": schema_pkg_apis_investigation_v1alpha1_InvestigationComment(ref),
- "github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationDataQueryLogs": schema_pkg_apis_investigation_v1alpha1_InvestigationDataQueryLogs(ref),
- "github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationDataQueryMetrics": schema_pkg_apis_investigation_v1alpha1_InvestigationDataQueryMetrics(ref),
- "github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationDatasourceRef": schema_pkg_apis_investigation_v1alpha1_InvestigationDatasourceRef(ref),
- "github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationInvestigationItem": schema_pkg_apis_investigation_v1alpha1_InvestigationInvestigationItem(ref),
- "github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationList": schema_pkg_apis_investigation_v1alpha1_InvestigationList(ref),
- "github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationOperatorState": schema_pkg_apis_investigation_v1alpha1_InvestigationOperatorState(ref),
- "github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationSpec": schema_pkg_apis_investigation_v1alpha1_InvestigationSpec(ref),
- "github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationStatus": schema_pkg_apis_investigation_v1alpha1_InvestigationStatus(ref),
- "github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationstatusOperatorState": schema_pkg_apis_investigation_v1alpha1_InvestigationstatusOperatorState(ref),
- }
-}
-
-func schema_pkg_apis_investigation_v1alpha1_Investigation(ref common.ReferenceCallback) common.OpenAPIDefinition {
- return common.OpenAPIDefinition{
- Schema: spec.Schema{
- SchemaProps: spec.SchemaProps{
- Type: []string{"object"},
- Properties: map[string]spec.Schema{
- "kind": {
- SchemaProps: spec.SchemaProps{
- Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
- Type: []string{"string"},
- Format: "",
- },
- },
- "apiVersion": {
- SchemaProps: spec.SchemaProps{
- Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
- Type: []string{"string"},
- Format: "",
- },
- },
- "metadata": {
- SchemaProps: spec.SchemaProps{
- Default: map[string]interface{}{},
- Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"),
- },
- },
- "spec": {
- SchemaProps: spec.SchemaProps{
- Default: map[string]interface{}{},
- Ref: ref("github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationSpec"),
- },
- },
- "status": {
- SchemaProps: spec.SchemaProps{
- Default: map[string]interface{}{},
- Ref: ref("github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationStatus"),
- },
- },
- },
- Required: []string{"metadata", "spec", "status"},
- },
- },
- Dependencies: []string{
- "github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationSpec", "github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
- }
-}
-
-func schema_pkg_apis_investigation_v1alpha1_InvestigationAbsoluteTimeRange(ref common.ReferenceCallback) common.OpenAPIDefinition {
- return common.OpenAPIDefinition{
- Schema: spec.Schema{
- SchemaProps: spec.SchemaProps{
- Description: "AbsoluteTimeRange is a time range specified by absolute timestamps.",
- Type: []string{"object"},
- Properties: map[string]spec.Schema{
- "from": {
- SchemaProps: spec.SchemaProps{
- Default: 0,
- Type: []string{"number"},
- Format: "float",
- },
- },
- "to": {
- SchemaProps: spec.SchemaProps{
- Default: 0,
- Type: []string{"number"},
- Format: "float",
- },
- },
- },
- Required: []string{"from", "to"},
- },
- },
- }
-}
-
-func schema_pkg_apis_investigation_v1alpha1_InvestigationComment(ref common.ReferenceCallback) common.OpenAPIDefinition {
- return common.OpenAPIDefinition{
- Schema: spec.Schema{
- SchemaProps: spec.SchemaProps{
- Description: "Comment is a comment on an investigation item.",
- Type: []string{"object"},
- Properties: map[string]spec.Schema{
- "authorUserID": {
- SchemaProps: spec.SchemaProps{
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- "bodyMarkdown": {
- SchemaProps: spec.SchemaProps{
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- },
- Required: []string{"authorUserID", "bodyMarkdown"},
- },
- },
- }
-}
-
-func schema_pkg_apis_investigation_v1alpha1_InvestigationDataQueryLogs(ref common.ReferenceCallback) common.OpenAPIDefinition {
- return common.OpenAPIDefinition{
- Schema: spec.Schema{
- SchemaProps: spec.SchemaProps{
- Description: "DataQueryLogs is a data query for logs.",
- Type: []string{"object"},
- Properties: map[string]spec.Schema{
- "datasource": {
- SchemaProps: spec.SchemaProps{
- Description: "DatasourceRef is a reference to a datasource.",
- Default: map[string]interface{}{},
- Ref: ref("github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationDatasourceRef"),
- },
- },
- "expr": {
- SchemaProps: spec.SchemaProps{
- Description: "expr is the expression of the query.",
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- "maxLines": {
- SchemaProps: spec.SchemaProps{
- Description: "maxLines (optional) is used to limit the number of log rows returned.",
- Type: []string{"integer"},
- Format: "int64",
- },
- },
- "refId": {
- SchemaProps: spec.SchemaProps{
- Description: "refId is the reference ID of the query.",
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- },
- Required: []string{"datasource", "expr", "refId"},
- },
- },
- Dependencies: []string{
- "github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationDatasourceRef"},
- }
-}
-
-func schema_pkg_apis_investigation_v1alpha1_InvestigationDataQueryMetrics(ref common.ReferenceCallback) common.OpenAPIDefinition {
- return common.OpenAPIDefinition{
- Schema: spec.Schema{
- SchemaProps: spec.SchemaProps{
- Description: "DataQueryMetrics is a data query for metrics.",
- Type: []string{"object"},
- Properties: map[string]spec.Schema{
- "datasource": {
- SchemaProps: spec.SchemaProps{
- Description: "DatasourceRef is a reference to a datasource.",
- Default: map[string]interface{}{},
- Ref: ref("github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationDatasourceRef"),
- },
- },
- "expr": {
- SchemaProps: spec.SchemaProps{
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- "refId": {
- SchemaProps: spec.SchemaProps{
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- },
- Required: []string{"datasource", "expr", "refId"},
- },
- },
- Dependencies: []string{
- "github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationDatasourceRef"},
- }
-}
-
-func schema_pkg_apis_investigation_v1alpha1_InvestigationDatasourceRef(ref common.ReferenceCallback) common.OpenAPIDefinition {
- return common.OpenAPIDefinition{
- Schema: spec.Schema{
- SchemaProps: spec.SchemaProps{
- Description: "DatasourceRef is a reference to a datasource.",
- Type: []string{"object"},
- Properties: map[string]spec.Schema{
- "apiVersion": {
- SchemaProps: spec.SchemaProps{
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- "name": {
- SchemaProps: spec.SchemaProps{
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- "type": {
- SchemaProps: spec.SchemaProps{
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- "uid": {
- SchemaProps: spec.SchemaProps{
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- },
- Required: []string{"apiVersion", "name", "type", "uid"},
- },
- },
- }
-}
-
-func schema_pkg_apis_investigation_v1alpha1_InvestigationInvestigationItem(ref common.ReferenceCallback) common.OpenAPIDefinition {
- return common.OpenAPIDefinition{
- Schema: spec.Schema{
- SchemaProps: spec.SchemaProps{
- Description: "InvestigationItem is an item in an investigation.",
- Type: []string{"object"},
- Properties: map[string]spec.Schema{
- "dataQuery": {
- SchemaProps: spec.SchemaProps{
- Description: "dataQuery contains the query used to generate this item.",
- Type: []string{"object"},
- Format: "",
- },
- },
- "iconPath": {
- SchemaProps: spec.SchemaProps{
- Description: "iconPath (optional) is the path to the icon for the item.",
- Type: []string{"string"},
- Format: "",
- },
- },
- "id": {
- SchemaProps: spec.SchemaProps{
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- "note": {
- SchemaProps: spec.SchemaProps{
- Description: "note (optional) is a comment on the item.",
- Type: []string{"array"},
- Items: &spec.SchemaOrArray{
- Schema: &spec.Schema{
- SchemaProps: spec.SchemaProps{
- Default: map[string]interface{}{},
- Ref: ref("github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationComment"),
- },
- },
- },
- },
- },
- "origin": {
- SchemaProps: spec.SchemaProps{
- Description: "origin is where the item was created from.",
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- "queryType": {
- SchemaProps: spec.SchemaProps{
- Description: "queryType is the type of the query used to generate this item.",
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- "timeRange": {
- SchemaProps: spec.SchemaProps{
- Description: "AbsoluteTimeRange is a time range specified by absolute timestamps.",
- Default: map[string]interface{}{},
- Ref: ref("github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationAbsoluteTimeRange"),
- },
- },
- "title": {
- SchemaProps: spec.SchemaProps{
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- "type": {
- SchemaProps: spec.SchemaProps{
- Description: "type is the type of the item \"timeseries\", \"heatmap\", \"log-table\" (not an enum to allow for future extensions).",
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- "url": {
- SchemaProps: spec.SchemaProps{
- Description: "url is the URL to the item.",
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- },
- Required: []string{"dataQuery", "id", "origin", "queryType", "timeRange", "title", "type", "url"},
- },
- },
- Dependencies: []string{
- "github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationAbsoluteTimeRange", "github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationComment"},
- }
-}
-
-func schema_pkg_apis_investigation_v1alpha1_InvestigationList(ref common.ReferenceCallback) common.OpenAPIDefinition {
- return common.OpenAPIDefinition{
- Schema: spec.Schema{
- SchemaProps: spec.SchemaProps{
- Type: []string{"object"},
- Properties: map[string]spec.Schema{
- "kind": {
- SchemaProps: spec.SchemaProps{
- Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
- Type: []string{"string"},
- Format: "",
- },
- },
- "apiVersion": {
- SchemaProps: spec.SchemaProps{
- Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
- Type: []string{"string"},
- Format: "",
- },
- },
- "metadata": {
- SchemaProps: spec.SchemaProps{
- Default: map[string]interface{}{},
- Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"),
- },
- },
- "items": {
- SchemaProps: spec.SchemaProps{
- Type: []string{"array"},
- Items: &spec.SchemaOrArray{
- Schema: &spec.Schema{
- SchemaProps: spec.SchemaProps{
- Default: map[string]interface{}{},
- Ref: ref("github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.Investigation"),
- },
- },
- },
- },
- },
- },
- Required: []string{"metadata", "items"},
- },
- },
- Dependencies: []string{
- "github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.Investigation", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
- }
-}
-
-func schema_pkg_apis_investigation_v1alpha1_InvestigationOperatorState(ref common.ReferenceCallback) common.OpenAPIDefinition {
- return common.OpenAPIDefinition{
- Schema: spec.Schema{
- SchemaProps: spec.SchemaProps{
- Description: "InvestigationOperatorState defines model for InvestigationOperatorState.",
- Type: []string{"object"},
- Properties: map[string]spec.Schema{
- "descriptiveState": {
- SchemaProps: spec.SchemaProps{
- Description: "descriptiveState is an optional more descriptive state field which has no requirements on format",
- Type: []string{"string"},
- Format: "",
- },
- },
- "details": {
- SchemaProps: spec.SchemaProps{
- Description: "details contains any extra information that is operator-specific",
- Type: []string{"object"},
- AdditionalProperties: &spec.SchemaOrBool{
- Allows: true,
- Schema: &spec.Schema{
- SchemaProps: spec.SchemaProps{
- Type: []string{"object"},
- Format: "",
- },
- },
- },
- },
- },
- "lastEvaluation": {
- SchemaProps: spec.SchemaProps{
- Description: "lastEvaluation is the ResourceVersion last evaluated",
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- "state": {
- SchemaProps: spec.SchemaProps{
- Description: "state describes the state of the lastEvaluation. It is limited to three possible states for machine evaluation.",
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- },
- Required: []string{"lastEvaluation", "state"},
- },
- },
- }
-}
-
-func schema_pkg_apis_investigation_v1alpha1_InvestigationSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
- return common.OpenAPIDefinition{
- Schema: spec.Schema{
- SchemaProps: spec.SchemaProps{
- Description: "InvestigationSpec defines model for InvestigationSpec.",
- Type: []string{"object"},
- Properties: map[string]spec.Schema{
- "items": {
- SchemaProps: spec.SchemaProps{
- Type: []string{"array"},
- Items: &spec.SchemaOrArray{
- Schema: &spec.Schema{
- SchemaProps: spec.SchemaProps{
- Default: map[string]interface{}{},
- Ref: ref("github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationInvestigationItem"),
- },
- },
- },
- },
- },
- "status": {
- SchemaProps: spec.SchemaProps{
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- "title": {
- SchemaProps: spec.SchemaProps{
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- },
- Required: []string{"items", "status", "title"},
- },
- },
- Dependencies: []string{
- "github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationInvestigationItem"},
- }
-}
-
-func schema_pkg_apis_investigation_v1alpha1_InvestigationStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
- return common.OpenAPIDefinition{
- Schema: spec.Schema{
- SchemaProps: spec.SchemaProps{
- Description: "InvestigationStatus defines model for InvestigationStatus.",
- Type: []string{"object"},
- Properties: map[string]spec.Schema{
- "additionalFields": {
- SchemaProps: spec.SchemaProps{
- Description: "additionalFields is reserved for future use",
- Type: []string{"object"},
- AdditionalProperties: &spec.SchemaOrBool{
- Allows: true,
- Schema: &spec.Schema{
- SchemaProps: spec.SchemaProps{
- Type: []string{"object"},
- Format: "",
- },
- },
- },
- },
- },
- "operatorStates": {
- SchemaProps: spec.SchemaProps{
- Description: "operatorStates is a map of operator ID to operator state evaluations. Any operator which consumes this kind SHOULD add its state evaluation information to this field.",
- Type: []string{"object"},
- AdditionalProperties: &spec.SchemaOrBool{
- Allows: true,
- Schema: &spec.Schema{
- SchemaProps: spec.SchemaProps{
- Default: map[string]interface{}{},
- Ref: ref("github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationstatusOperatorState"),
- },
- },
- },
- },
- },
- },
- },
- },
- Dependencies: []string{
- "github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1.InvestigationstatusOperatorState"},
- }
-}
-
-func schema_pkg_apis_investigation_v1alpha1_InvestigationstatusOperatorState(ref common.ReferenceCallback) common.OpenAPIDefinition {
- return common.OpenAPIDefinition{
- Schema: spec.Schema{
- SchemaProps: spec.SchemaProps{
- Description: "InvestigationstatusOperatorState defines model for Investigationstatus.#OperatorState.",
- Type: []string{"object"},
- Properties: map[string]spec.Schema{
- "descriptiveState": {
- SchemaProps: spec.SchemaProps{
- Description: "descriptiveState is an optional more descriptive state field which has no requirements on format",
- Type: []string{"string"},
- Format: "",
- },
- },
- "details": {
- SchemaProps: spec.SchemaProps{
- Description: "details contains any extra information that is operator-specific",
- Type: []string{"object"},
- AdditionalProperties: &spec.SchemaOrBool{
- Allows: true,
- Schema: &spec.Schema{
- SchemaProps: spec.SchemaProps{
- Type: []string{"object"},
- Format: "",
- },
- },
- },
- },
- },
- "lastEvaluation": {
- SchemaProps: spec.SchemaProps{
- Description: "lastEvaluation is the ResourceVersion last evaluated",
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- "state": {
- SchemaProps: spec.SchemaProps{
- Description: "state describes the state of the lastEvaluation. It is limited to three possible states for machine evaluation.",
- Default: "",
- Type: []string{"string"},
- Format: "",
- },
- },
- },
- Required: []string{"lastEvaluation", "state"},
- },
- },
- }
-}
diff --git a/apps/investigation/pkg/apis/manifest.go b/apps/investigation/pkg/apis/manifest.go
deleted file mode 100644
index 2812059e14a..00000000000
--- a/apps/investigation/pkg/apis/manifest.go
+++ /dev/null
@@ -1,50 +0,0 @@
-//
-// This file is generated by grafana-app-sdk
-// DO NOT EDIT
-//
-
-package apis
-
-import (
- "encoding/json"
-
- "github.com/grafana/grafana-app-sdk/app"
-)
-
-var (
- rawSchemaInvestigationv1alpha1 = []byte(`{"spec":{"description":"spec is the schema of our resource. The spec should include all the user-ediable information for the kind.","properties":{"items":{"items":{"properties":{"dataQuery":{"description":"dataQuery contains the query used to generate this item.","oneOf":[{"allOf":[{"required":["refId","datasource","expr"]},{"not":{"anyOf":[{"required":["refId","datasource","expr"]}]}}]},{"allOf":[{"required":["refId","datasource","expr"]},{"not":{"anyOf":[{"required":["refId","datasource","expr"]}]}}]}],"properties":{"datasource":{"description":"datasource is the datasource of the query.","properties":{"apiVersion":{"type":"string"},"name":{"type":"string"},"type":{"type":"string"},"uid":{"type":"string"}},"required":["uid","type","apiVersion","name"],"type":"object"},"expr":{"description":"expr is the expression of the query.","type":"string"},"maxLines":{"description":"maxLines (optional) is used to limit the number of log rows returned.","format":"int64","type":"integer"},"refId":{"description":"refId is the reference ID of the query.","type":"string"}},"type":"object"},"iconPath":{"description":"iconPath (optional) is the path to the icon for the item.","type":"string"},"id":{"type":"string"},"note":{"description":"note (optional) is a comment on the item.","items":{"properties":{"authorUserID":{"type":"string"},"bodyMarkdown":{"type":"string"}},"required":["authorUserID","bodyMarkdown"],"type":"object"},"type":"array"},"origin":{"description":"origin is where the item was created from.","type":"string"},"queryType":{"description":"queryType is the type of the query used to generate this item.","enum":["logs","metrics"],"type":"string"},"timeRange":{"description":"timeRange (optional) is the time range of the item.","properties":{"from":{"type":"number"},"to":{"type":"number"}},"required":["from","to"],"type":"object"},"title":{"type":"string"},"type":{"description":"type is the type of the item \"timeseries\", \"heatmap\", \"log-table\" (not an enum to allow for future extensions).","type":"string"},"url":{"description":"url is the URL to the item.","type":"string"}},"required":["id","title","type","url","origin","timeRange","queryType","dataQuery"],"type":"object"},"type":"array"},"status":{"enum":["open","closed"],"type":"string"},"title":{"type":"string"}},"required":["title","status","items"],"type":"object"},"status":{"properties":{"additionalFields":{"description":"additionalFields is reserved for future use","type":"object","x-kubernetes-preserve-unknown-fields":true},"operatorStates":{"additionalProperties":{"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"description":"details contains any extra information that is operator-specific","type":"object","x-kubernetes-preserve-unknown-fields":true},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object","x-kubernetes-preserve-unknown-fields":true}}`)
- versionSchemaInvestigationv1alpha1 app.VersionSchema
- _ = json.Unmarshal(rawSchemaInvestigationv1alpha1, &versionSchemaInvestigationv1alpha1)
-)
-
-var appManifestData = app.ManifestData{
- AppName: "investigation",
- Group: "investigation.grafana.app",
- Kinds: []app.ManifestKind{
- {
- Kind: "Investigation",
- Scope: "Namespaced",
- Conversion: false,
- Versions: []app.ManifestKindVersion{
- {
- Name: "v1alpha1",
- Schema: &versionSchemaInvestigationv1alpha1,
- },
- },
- },
- },
-}
-
-func jsonToMap(j string) map[string]any {
- m := make(map[string]any)
- json.Unmarshal([]byte(j), &j)
- return m
-}
-
-func LocalManifest() app.Manifest {
- return app.NewEmbeddedManifest(appManifestData)
-}
-
-func RemoteManifest() app.Manifest {
- return app.NewAPIServerManifest("investigation")
-}
diff --git a/apps/investigations/Makefile b/apps/investigations/Makefile
new file mode 100644
index 00000000000..7a5f1c99365
--- /dev/null
+++ b/apps/investigations/Makefile
@@ -0,0 +1,3 @@
+.PHONY: generate
+generate:
+ @grafana-app-sdk generate -g ./pkg/apis --grouping=group --postprocess --defencoding=none
diff --git a/apps/investigations/example.json b/apps/investigations/example.json
new file mode 100644
index 00000000000..0a390fb074f
--- /dev/null
+++ b/apps/investigations/example.json
@@ -0,0 +1,152 @@
+[
+ {
+ "id": "896312ce-65b0-4b50-ade1-e7f04fa22c66",
+ "title": "Thursday morning investigation",
+ "hasCustomName": false,
+ "isFavorite": false,
+ "collectables": [
+ {
+ "origin": "Explore Logs",
+ "type": "timeseries",
+ "queries": [
+ {
+ "refId": "LABEL_BREAKDOWN_VALUES",
+ "queryType": "range",
+ "editorMode": "code",
+ "supportingQueryType": "grafana-lokiexplore-app",
+ "legendFormat": "{{detected_level}}",
+ "expr": "sum(count_over_time({service_name=\"web_app_1\"} | detected_level != \"\"[$__auto])) by (detected_level)"
+ }
+ ],
+ "timeRange": {
+ "to": "2025-02-13T11:31:20.536Z",
+ "from": "2025-02-13T11:16:20.536Z",
+ "raw": {
+ "from": "now-15m",
+ "to": "now"
+ }
+ },
+ "datasource": {
+ "uid": "fe9k7u07b1a0wc"
+ },
+ "url": "http://localhost:3000/a/grafana-lokiexplore-app/explore/service/web_app_1/labels?patterns=%5B%5D&from=now-15m&to=now&var-ds=fe9k7u07b1a0wc&var-filters=service_name%7C%3D%7Cweb_app_1&var-fields=&var-levels=&var-metadata=&var-patterns=&var-lineFilterV2=&var-lineFilters=&urlColumns=%5B%5D&visualizationType=%22logs%22&displayedFields=%5B%5D&timezone=browser&var-all-fields=&var-labelBy=$__all",
+ "id": "LABEL_BREAKDOWN_VALUES_detected_level",
+ "title": "detected_level",
+ "logoPath": "public/plugins/grafana-lokiexplore-app/img/img/logo.svg",
+ "createdAt": "2025-02-13T11:31:23.637Z"
+ }
+ ],
+ "createdAt": "2025-02-13T11:31:23.636Z",
+ "updatedAt": "2025-02-13T11:31:23.637Z",
+ "viewMode": {
+ "mode": "compact",
+ "showComments": true,
+ "showTooltips": false
+ }
+ },
+ {
+ "id": "e9cf1958-d0ed-46b7-b597-9052c7648656",
+ "title": "Thursday morning investigation",
+ "hasCustomName": false,
+ "isFavorite": false,
+ "collectables": [
+ {
+ "origin": "Explore Logs",
+ "type": "timeseries",
+ "queries": [
+ {
+ "refId": "LABEL_BREAKDOWN_VALUES",
+ "queryType": "range",
+ "editorMode": "code",
+ "supportingQueryType": "grafana-lokiexplore-app",
+ "legendFormat": "{{detected_level}}",
+ "expr": "sum(count_over_time({service_name=\"web_app_1\"} | detected_level != \"\"[$__auto])) by (detected_level)"
+ }
+ ],
+ "timeRange": {
+ "to": "2025-02-13T11:31:20.536Z",
+ "from": "2025-02-13T11:16:20.536Z",
+ "raw": {
+ "from": "now-15m",
+ "to": "now"
+ }
+ },
+ "datasource": {
+ "uid": "fe9k7u07b1a0wc"
+ },
+ "url": "http://localhost:3000/a/grafana-lokiexplore-app/explore/service/web_app_1/labels?patterns=%5B%5D&from=now-15m&to=now&var-ds=fe9k7u07b1a0wc&var-filters=service_name%7C%3D%7Cweb_app_1&var-fields=&var-levels=&var-metadata=&var-patterns=&var-lineFilterV2=&var-lineFilters=&urlColumns=%5B%5D&visualizationType=%22logs%22&displayedFields=%5B%5D&timezone=browser&var-all-fields=&var-labelBy=$__all",
+ "id": "LABEL_BREAKDOWN_VALUES_detected_level",
+ "title": "detected_level",
+ "logoPath": "public/plugins/grafana-lokiexplore-app/img/img/logo.svg",
+ "createdAt": "2025-02-13T11:31:23.638Z"
+ },
+ {
+ "origin": "Explore Logs",
+ "type": "timeseries",
+ "queries": [
+ {
+ "refId": "LABEL_BREAKDOWN_VALUES",
+ "queryType": "range",
+ "editorMode": "code",
+ "supportingQueryType": "grafana-lokiexplore-app",
+ "legendFormat": "{{service_name}}",
+ "expr": "sum(count_over_time({service_name=\"web_app_1\",service_name != \"\"} [$__auto])) by (service_name)"
+ }
+ ],
+ "timeRange": {
+ "to": "2025-02-13T11:31:20.536Z",
+ "from": "2025-02-13T11:16:20.536Z",
+ "raw": {
+ "from": "now-15m",
+ "to": "now"
+ }
+ },
+ "datasource": {
+ "uid": "fe9k7u07b1a0wc"
+ },
+ "url": "http://localhost:3000/a/grafana-lokiexplore-app/explore/service/web_app_1/labels?patterns=%5B%5D&from=now-15m&to=now&var-ds=fe9k7u07b1a0wc&var-filters=service_name%7C%3D%7Cweb_app_1&var-fields=&var-levels=&var-metadata=&var-patterns=&var-lineFilterV2=&var-lineFilters=&urlColumns=%5B%5D&visualizationType=%22logs%22&displayedFields=%5B%5D&timezone=browser&var-all-fields=&var-labelBy=$__all",
+ "id": "LABEL_BREAKDOWN_VALUES_service_name",
+ "title": "service_name",
+ "logoPath": "public/plugins/grafana-lokiexplore-app/img/img/logo.svg",
+ "createdAt": "2025-02-13T11:31:41.507Z"
+ },
+ {
+ "origin": "Explore Logs",
+ "type": "timeseries",
+ "queries": [
+ {
+ "refId": "LABEL_BREAKDOWN_VALUES",
+ "queryType": "range",
+ "editorMode": "code",
+ "supportingQueryType": "grafana-lokiexplore-app",
+ "legendFormat": "{{service}}",
+ "expr": "sum(count_over_time({service_name=\"web_app_1\",service != \"\"} [$__auto])) by (service)"
+ }
+ ],
+ "timeRange": {
+ "to": "2025-02-13T11:31:20.536Z",
+ "from": "2025-02-13T11:16:20.536Z",
+ "raw": {
+ "from": "now-15m",
+ "to": "now"
+ }
+ },
+ "datasource": {
+ "uid": "fe9k7u07b1a0wc"
+ },
+ "url": "http://localhost:3000/a/grafana-lokiexplore-app/explore/service/web_app_1/labels?patterns=%5B%5D&from=now-15m&to=now&var-ds=fe9k7u07b1a0wc&var-filters=service_name%7C%3D%7Cweb_app_1&var-fields=&var-levels=&var-metadata=&var-patterns=&var-lineFilterV2=&var-lineFilters=&urlColumns=%5B%5D&visualizationType=%22logs%22&displayedFields=%5B%5D&timezone=browser&var-all-fields=&var-labelBy=$__all",
+ "id": "LABEL_BREAKDOWN_VALUES_service",
+ "title": "service",
+ "logoPath": "public/plugins/grafana-lokiexplore-app/img/img/logo.svg",
+ "createdAt": "2025-02-13T11:31:43.698Z"
+ }
+ ],
+ "createdAt": "2025-02-13T11:31:23.637Z",
+ "updatedAt": "2025-02-13T11:31:43.698Z",
+ "viewMode": {
+ "mode": "compact",
+ "showComments": true,
+ "showTooltips": false
+ }
+ }
+]
diff --git a/apps/investigation/go.mod b/apps/investigations/go.mod
similarity index 60%
rename from apps/investigation/go.mod
rename to apps/investigations/go.mod
index de0d3fa2621..645f323e800 100644
--- a/apps/investigation/go.mod
+++ b/apps/investigations/go.mod
@@ -1,10 +1,10 @@
-module github.com/grafana/grafana/apps/investigation
+module github.com/grafana/grafana/apps/investigations
-go 1.23.4
+go 1.23.7
require (
- github.com/grafana/grafana-app-sdk v0.30.0
- k8s.io/apimachinery v0.32.0
+ github.com/grafana/grafana-app-sdk v0.31.0
+ k8s.io/apimachinery v0.32.1
k8s.io/klog/v2 v2.130.1
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f
)
@@ -18,7 +18,7 @@ require (
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
- github.com/getkin/kin-openapi v0.128.0 // indirect
+ github.com/getkin/kin-openapi v0.129.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
@@ -27,15 +27,14 @@ require (
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
- github.com/google/go-cmp v0.6.0 // indirect
+ github.com/google/go-cmp v0.7.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
github.com/google/uuid v1.6.0 // indirect
- github.com/grafana/grafana-app-sdk/logging v0.29.0 // indirect
- github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 // indirect
+ github.com/grafana/grafana-app-sdk/logging v0.30.0 // indirect
+ github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
- github.com/invopop/yaml v0.3.1 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.11 // indirect
@@ -44,40 +43,44 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
+ github.com/oasdiff/yaml v0.0.0-20241210131133-6b86fb107d80 // indirect
+ github.com/oasdiff/yaml3 v0.0.0-20241210130736-a94c01f36349 // indirect
+ github.com/onsi/ginkgo/v2 v2.22.0 // indirect
+ github.com/onsi/gomega v1.36.1 // indirect
github.com/perimeterx/marshmallow v1.1.5 // indirect
- github.com/prometheus/client_golang v1.20.5 // indirect
+ github.com/prometheus/client_golang v1.21.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
- github.com/prometheus/common v0.61.0 // indirect
+ github.com/prometheus/common v0.62.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/puzpuzpuz/xsync/v2 v2.5.1 // indirect
- github.com/spf13/pflag v1.0.5 // indirect
+ github.com/spf13/pflag v1.0.6 // indirect
github.com/x448/float16 v0.8.4 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
- go.opentelemetry.io/otel v1.33.0 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0 // indirect
- go.opentelemetry.io/otel/metric v1.33.0 // indirect
- go.opentelemetry.io/otel/sdk v1.33.0 // indirect
- go.opentelemetry.io/otel/trace v1.33.0 // indirect
+ go.opentelemetry.io/otel v1.34.0 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 // indirect
+ go.opentelemetry.io/otel/metric v1.34.0 // indirect
+ go.opentelemetry.io/otel/sdk v1.34.0 // indirect
+ go.opentelemetry.io/otel/trace v1.34.0 // indirect
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
- golang.org/x/net v0.34.0 // indirect
- golang.org/x/oauth2 v0.25.0 // indirect
- golang.org/x/sync v0.10.0 // indirect
- golang.org/x/sys v0.29.0 // indirect
- golang.org/x/term v0.28.0 // indirect
- golang.org/x/text v0.21.0 // indirect
+ golang.org/x/net v0.36.0 // indirect
+ golang.org/x/oauth2 v0.27.0 // indirect
+ golang.org/x/sync v0.11.0 // indirect
+ golang.org/x/sys v0.30.0 // indirect
+ golang.org/x/term v0.29.0 // indirect
+ golang.org/x/text v0.22.0 // indirect
golang.org/x/time v0.9.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
- google.golang.org/genproto/googleapis/api v0.0.0-20250102185135-69823020774d // indirect
- google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d // indirect
- google.golang.org/grpc v1.69.4 // indirect
- google.golang.org/protobuf v1.36.1 // indirect
+ google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20250207221924-e9438ea467c6 // indirect
+ google.golang.org/grpc v1.70.0 // indirect
+ google.golang.org/protobuf v1.36.5 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
- k8s.io/api v0.32.0 // indirect
- k8s.io/apiextensions-apiserver v0.32.0 // indirect
- k8s.io/client-go v0.32.0 // indirect
+ k8s.io/api v0.32.1 // indirect
+ k8s.io/apiextensions-apiserver v0.32.1 // indirect
+ k8s.io/client-go v0.32.1 // indirect
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.5.0 // indirect
diff --git a/apps/investigation/go.sum b/apps/investigations/go.sum
similarity index 72%
rename from apps/investigation/go.sum
rename to apps/investigations/go.sum
index 858c73dd4b4..88d0fa45e79 100644
--- a/apps/investigation/go.sum
+++ b/apps/investigations/go.sum
@@ -16,8 +16,8 @@ github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCv
github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
-github.com/getkin/kin-openapi v0.128.0 h1:jqq3D9vC9pPq1dGcOCv7yOp1DaEe7c/T1vzcLbITSp4=
-github.com/getkin/kin-openapi v0.128.0/go.mod h1:OZrfXzUfGrNbsKj+xmFBx6E5c6yH3At/tAKSc2UszXM=
+github.com/getkin/kin-openapi v0.129.0 h1:QGYTNcmyP5X0AtFQ2Dkou9DGBJsUETeLH9rFrJXZh30=
+github.com/getkin/kin-openapi v0.129.0/go.mod h1:gmWI+b/J45xqpyK5wJmRRZse5wefA5H0RDMK46kLUtI=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
@@ -40,8 +40,8 @@ github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
-github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
-github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
+github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -49,19 +49,17 @@ github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/Z
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/grafana/grafana-app-sdk v0.30.0 h1:Hqn2pETu2mQ4RpWkZYEQfu01P7xd1Z1Gj+HX/8aB0tw=
-github.com/grafana/grafana-app-sdk v0.30.0/go.mod h1:jhfqNIovb+Mes2vdMf9iMCWQkp1GTNtyNuExONtiNuk=
-github.com/grafana/grafana-app-sdk/logging v0.29.0 h1:mgbXaAf33aFwqwGVeaX30l8rkeAJH0iACgX5Rn6YkN4=
-github.com/grafana/grafana-app-sdk/logging v0.29.0/go.mod h1:xy6ZyVXl50Z3DBDLybvBPphbykPhuVNed/VNmen9DQM=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ=
+github.com/grafana/grafana-app-sdk v0.31.0 h1:/mFCcx+YqG8cWAi9hePDJQxIdtXDClDIDRgZwHkksFk=
+github.com/grafana/grafana-app-sdk v0.31.0/go.mod h1:Xw00NL7qpRLo5r3Gn48Bl1Xn2n4eUDI5pYf/wMufKWs=
+github.com/grafana/grafana-app-sdk/logging v0.30.0 h1:K/P/bm7Cp7Di4tqIJ3EQz2+842JozQGRaz62r95ApME=
+github.com/grafana/grafana-app-sdk/logging v0.30.0/go.mod h1:xy6ZyVXl50Z3DBDLybvBPphbykPhuVNed/VNmen9DQM=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 h1:e9Rjr40Z98/clHv5Yg79Is0NtosR5LXRvdr7o/6NwbA=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1/go.mod h1:tIxuGz/9mpox++sgp9fJjHO0+q1X9/UOWd798aAm22M=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
-github.com/invopop/yaml v0.3.1 h1:f0+ZpmhfBSS4MhG+4HYseMdJhoeeopbSKbq5Rpeelso=
-github.com/invopop/yaml v0.3.1/go.mod h1:PMOp3nn4/12yEZUFfmOuNHJsZToEEOwoWsT+D81KkeA=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
@@ -87,10 +85,14 @@ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
-github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
-github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
-github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
-github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
+github.com/oasdiff/yaml v0.0.0-20241210131133-6b86fb107d80 h1:nZspmSkneBbtxU9TopEAE0CY+SBJLxO8LPUlw2vG4pU=
+github.com/oasdiff/yaml v0.0.0-20241210131133-6b86fb107d80/go.mod h1:7tFDb+Y51LcDpn26GccuUgQXUk6t0CXZsivKjyimYX8=
+github.com/oasdiff/yaml3 v0.0.0-20241210130736-a94c01f36349 h1:t05Ww3DxZutOqbMN+7OIuqDwXbhl32HiZGpLy26BAPc=
+github.com/oasdiff/yaml3 v0.0.0-20241210130736-a94c01f36349/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o=
+github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg=
+github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
+github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw=
+github.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s=
github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -98,20 +100,20 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
-github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
+github.com/prometheus/client_golang v1.21.0 h1:DIsaGmiaBkSangBgMtWdNfxbMNdku5IK6iNhrEqWvdA=
+github.com/prometheus/client_golang v1.21.0/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
-github.com/prometheus/common v0.61.0 h1:3gv/GThfX0cV2lpO7gkTUwZru38mxevy90Bj8YFSRQQ=
-github.com/prometheus/common v0.61.0/go.mod h1:zr29OCN/2BsJRaFwG8QOBr41D6kkchKbpeNH7pAjb/s=
+github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
+github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/puzpuzpuz/xsync/v2 v2.5.1 h1:mVGYAvzDSu52+zaGyNjC+24Xw2bQi3kTr4QJ6N9pIIU=
github.com/puzpuzpuz/xsync/v2 v2.5.1/go.mod h1:gD2H2krq/w52MfPLE+Uy64TzJDVY7lP2znR9qmR35kU=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
-github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
-github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
+github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
@@ -124,22 +126,22 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
-go.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw=
-go.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 h1:Vh5HayB/0HHfOQA7Ctx69E/Y/DcQSMPpKANYVMQ7fBA=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0/go.mod h1:cpgtDBaqD/6ok/UG0jT15/uKjAY8mRA53diogHBg3UI=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0 h1:5pojmb1U1AogINhN3SurB+zm/nIcusopeBNp42f45QM=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0/go.mod h1:57gTHJSE5S1tqg+EKsLPlTWhpHMsWlVmer+LA926XiA=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0 h1:wpMfgF8E1rkrT1Z6meFh1NDtownE9Ii3n3X2GJYjsaU=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0/go.mod h1:wAy0T/dUbs468uOlkT31xjvqQgEVXv58BRFWEgn5v/0=
-go.opentelemetry.io/otel/metric v1.33.0 h1:r+JOocAyeRVXD8lZpjdQjzMadVZp2M4WmQ+5WtEnklQ=
-go.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M=
-go.opentelemetry.io/otel/sdk v1.33.0 h1:iax7M131HuAm9QkZotNHEfstof92xM+N8sr3uHXc2IM=
-go.opentelemetry.io/otel/sdk v1.33.0/go.mod h1:A1Q5oi7/9XaMlIWzPSxLRWOI8nG3FnzHJNbiENQuihM=
-go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc=
-go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8=
-go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s=
-go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck=
+go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
+go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 h1:BEj3SPM81McUZHYjRS5pEgNgnmzGJ5tRpU5krWnV8Bs=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0/go.mod h1:9cKLGBDzI/F3NoHLQGm4ZrYdIHsvGt6ej6hUowxY0J4=
+go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
+go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
+go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
+go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
+go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU=
+go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ=
+go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
+go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
@@ -153,26 +155,26 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
-golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
-golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70=
-golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
+golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA=
+golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I=
+golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=
+golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
-golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
+golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
-golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
-golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
+golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
+golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
+golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
-golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
+golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
+golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -187,14 +189,14 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw=
gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
-google.golang.org/genproto/googleapis/api v0.0.0-20250102185135-69823020774d h1:H8tOf8XM88HvKqLTxe755haY6r1fqqzLbEnfrmLXlSA=
-google.golang.org/genproto/googleapis/api v0.0.0-20250102185135-69823020774d/go.mod h1:2v7Z7gP2ZUOGsaFyxATQSRoBnKygqVq2Cwnvom7QiqY=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d h1:xJJRGY7TJcvIlpSrN3K6LAWgNFUILlO+OMAqtg9aqnw=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d/go.mod h1:3ENsm/5D1mzDyhpzeRi1NR784I0BcofWBoSc5QqqMK4=
-google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A=
-google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4=
-google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk=
-google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489 h1:fCuMM4fowGzigT89NCIsW57Pk9k2D12MMi2ODn+Nk+o=
+google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489/go.mod h1:iYONQfRdizDB8JJBybql13nArx91jcUk7zCXEsOofM4=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250207221924-e9438ea467c6 h1:2duwAxN2+k0xLNpjnHTXoMUgnv6VPSp5fiqTuwSxjmI=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250207221924-e9438ea467c6/go.mod h1:8BS3B93F/U1juMFq9+EDk+qOT5CO1R9IzXxG3PTqiRk=
+google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
+google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
+google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
+google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
@@ -204,14 +206,14 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-k8s.io/api v0.32.0 h1:OL9JpbvAU5ny9ga2fb24X8H6xQlVp+aJMFlgtQjR9CE=
-k8s.io/api v0.32.0/go.mod h1:4LEwHZEf6Q/cG96F3dqR965sYOfmPM7rq81BLgsE0p0=
-k8s.io/apiextensions-apiserver v0.32.0 h1:S0Xlqt51qzzqjKPxfgX1xh4HBZE+p8KKBq+k2SWNOE0=
-k8s.io/apiextensions-apiserver v0.32.0/go.mod h1:86hblMvN5yxMvZrZFX2OhIHAuFIMJIZ19bTvzkP+Fmw=
-k8s.io/apimachinery v0.32.0 h1:cFSE7N3rmEEtv4ei5X6DaJPHHX0C+upp+v5lVPiEwpg=
-k8s.io/apimachinery v0.32.0/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
-k8s.io/client-go v0.32.0 h1:DimtMcnN/JIKZcrSrstiwvvZvLjG0aSxy8PxN8IChp8=
-k8s.io/client-go v0.32.0/go.mod h1:boDWvdM1Drk4NJj/VddSLnx59X3OPgwrOo0vGbtq9+8=
+k8s.io/api v0.32.1 h1:f562zw9cy+GvXzXf0CKlVQ7yHJVYzLfL6JAS4kOAaOc=
+k8s.io/api v0.32.1/go.mod h1:/Yi/BqkuueW1BgpoePYBRdDYfjPF5sgTr5+YqDZra5k=
+k8s.io/apiextensions-apiserver v0.32.1 h1:hjkALhRUeCariC8DiVmb5jj0VjIc1N0DREP32+6UXZw=
+k8s.io/apiextensions-apiserver v0.32.1/go.mod h1:sxWIGuGiYov7Io1fAS2X06NjMIk5CbRHc2StSmbaQto=
+k8s.io/apimachinery v0.32.1 h1:683ENpaCBjma4CYqsmZyhEzrGz6cjn1MY/X2jB2hkZs=
+k8s.io/apimachinery v0.32.1/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
+k8s.io/client-go v0.32.1 h1:otM0AxdhdBIaQh7l1Q0jQpmo7WOFIk5FFa4bg6YMdUU=
+k8s.io/client-go v0.32.1/go.mod h1:aTTKZY7MdxUaJ/KiUs8D+GssR9zJZi77ZqtzcGXIiDg=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y=
diff --git a/apps/investigations/kinds/collectable.cue b/apps/investigations/kinds/collectable.cue
new file mode 100644
index 00000000000..6844c0a8cae
--- /dev/null
+++ b/apps/investigations/kinds/collectable.cue
@@ -0,0 +1,51 @@
+package investigations
+
+// Collectable represents an item collected during investigation
+#Collectable: {
+ id: string
+ createdAt: string
+
+ title: string
+ origin: string
+ type: string
+ queries: [...#Query] // +listType=atomic
+ timeRange: #TimeRange
+ datasource: #DatasourceRef
+ url: string
+ logoPath?: string
+
+ note: string
+ noteUpdatedAt: string
+}
+
+#CollectableSummary: {
+ id: string
+ title: string
+ logoPath: string
+ origin: string
+}
+
+// Query represents a data query
+#Query: {
+ refId: string
+ queryType: string
+ editorMode: string
+ supportingQueryType: string
+ legendFormat: string
+ expr: string
+}
+
+// TimeRange represents a time range with both absolute and relative values
+#TimeRange: {
+ from: string
+ to: string
+ raw: {
+ from: string
+ to: string
+ }
+}
+
+// DatasourceRef is a reference to a datasource
+#DatasourceRef: {
+ uid: string
+}
diff --git a/apps/investigations/kinds/cue.mod/module.cue b/apps/investigations/kinds/cue.mod/module.cue
new file mode 100644
index 00000000000..55fe474ed5f
--- /dev/null
+++ b/apps/investigations/kinds/cue.mod/module.cue
@@ -0,0 +1 @@
+module: "github.com/grafana/grafana/apps/investigations"
diff --git a/apps/investigations/kinds/investigation.cue b/apps/investigations/kinds/investigation.cue
new file mode 100644
index 00000000000..f1e9a69027f
--- /dev/null
+++ b/apps/investigations/kinds/investigation.cue
@@ -0,0 +1,64 @@
+package investigations
+
+// This is our Investigation definition, which contains metadata about the kind, and the kind's schema
+investigation: {
+ kind: "Investigation"
+ group: "investigations.grafana.app"
+ apiResource: {
+ groupOverride: "investigations.grafana.app"
+ }
+ pluralName: "Investigations"
+ current: "v0alpha1"
+ versions: {
+ "v0alpha1": {
+ codegen: {
+ frontend: true
+ backend: true
+ options: {
+ generateObjectMeta: true
+ generateClient: true
+ k8sLike: true
+ package: "github.com/grafana/grafana/apps/investigations"
+ }
+ }
+ schema: {
+ // spec is the schema of our resource
+ spec: {
+ title: string
+ createdByProfile: #Person
+ hasCustomName: bool
+ isFavorite: bool
+ overviewNote: string
+ overviewNoteUpdatedAt: string
+ collectables: [...#Collectable] // +listType=atomic
+ viewMode: #ViewMode
+ }
+ }
+ }
+ }
+}
+
+// Type definition for investigation summaries
+#InvestigationSummary: {
+ title: string
+ createdByProfile: #Person
+ hasCustomName: bool
+ isFavorite: bool
+ overviewNote: string
+ overviewNoteUpdatedAt: string
+ viewMode: #ViewMode
+ collectableSummaries: [...#CollectableSummary] // +listType=atomic
+}
+
+// Person represents a user profile with basic information
+#Person: {
+ uid: string // Unique identifier for the user
+ name: string // Display name of the user
+ gravatarUrl: string // URL to user's Gravatar image
+}
+
+#ViewMode: {
+ mode: "compact" | "full"
+ showComments: bool
+ showTooltips: bool
+}
diff --git a/apps/investigations/kinds/investigationindex.cue b/apps/investigations/kinds/investigationindex.cue
new file mode 100644
index 00000000000..447e156be4f
--- /dev/null
+++ b/apps/investigations/kinds/investigationindex.cue
@@ -0,0 +1,37 @@
+package investigations
+
+investigationIndex: {
+ kind: "InvestigationIndex"
+ group: "investigations.grafana.app"
+ apiResource: {
+ groupOverride: "investigations.grafana.app"
+ }
+ pluralName: "InvestigationIndexes"
+ current: "v0alpha1"
+ versions: {
+ "v0alpha1": {
+ codegen: {
+ frontend: true
+ backend: true
+ options: {
+ generateObjectMeta: true
+ generateClient: true
+ k8sLike: true
+ package: "github.com/grafana/grafana/apps/investigations"
+ }
+ }
+ schema: {
+ spec: {
+ // Title of the index, e.g. 'Favorites' or 'My Investigations'
+ title: string
+
+ // The Person who owns this investigation index
+ owner: #Person
+
+ // Array of investigation summaries
+ investigationSummaries: [...#InvestigationSummary] // +listType=atomic
+ }
+ }
+ }
+ }
+}
diff --git a/apps/investigations/kinds/manifest.cue b/apps/investigations/kinds/manifest.cue
new file mode 100644
index 00000000000..d9e93b00061
--- /dev/null
+++ b/apps/investigations/kinds/manifest.cue
@@ -0,0 +1,10 @@
+package investigations
+
+manifest: {
+ appName: "investigations"
+ groupOverride: "investigations.grafana.app"
+ kinds: [
+ investigation,
+ investigationIndex,
+ ]
+}
diff --git a/apps/investigations/pkg/apis/investigations/v0alpha1/constants.go b/apps/investigations/pkg/apis/investigations/v0alpha1/constants.go
new file mode 100644
index 00000000000..288c15885ce
--- /dev/null
+++ b/apps/investigations/pkg/apis/investigations/v0alpha1/constants.go
@@ -0,0 +1,18 @@
+package v0alpha1
+
+import "k8s.io/apimachinery/pkg/runtime/schema"
+
+const (
+ // Group is the API group used by all kinds in this package
+ Group = "investigations.grafana.app"
+ // Version is the API version used by all kinds in this package
+ Version = "v0alpha1"
+)
+
+var (
+ // GroupVersion is a schema.GroupVersion consisting of the Group and Version constants for this package
+ GroupVersion = schema.GroupVersion{
+ Group: Group,
+ Version: Version,
+ }
+)
diff --git a/apps/investigation/pkg/apis/investigation/v1alpha1/investigation_codec_gen.go b/apps/investigations/pkg/apis/investigations/v0alpha1/investigation_codec_gen.go
similarity index 97%
rename from apps/investigation/pkg/apis/investigation/v1alpha1/investigation_codec_gen.go
rename to apps/investigations/pkg/apis/investigations/v0alpha1/investigation_codec_gen.go
index 73e2232d045..6bde81b50d3 100644
--- a/apps/investigation/pkg/apis/investigation/v1alpha1/investigation_codec_gen.go
+++ b/apps/investigations/pkg/apis/investigations/v0alpha1/investigation_codec_gen.go
@@ -2,7 +2,7 @@
// Code generated by grafana-app-sdk. DO NOT EDIT.
//
-package v1alpha1
+package v0alpha1
import (
"encoding/json"
diff --git a/apps/investigations/pkg/apis/investigations/v0alpha1/investigation_metadata_gen.go b/apps/investigations/pkg/apis/investigations/v0alpha1/investigation_metadata_gen.go
new file mode 100644
index 00000000000..e0d2756f194
--- /dev/null
+++ b/apps/investigations/pkg/apis/investigations/v0alpha1/investigation_metadata_gen.go
@@ -0,0 +1,28 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+package v0alpha1
+
+import (
+ time "time"
+)
+
+// metadata contains embedded CommonMetadata and can be extended with custom string fields
+// TODO: use CommonMetadata instead of redefining here; currently needs to be defined here
+// without external reference as using the CommonMetadata reference breaks thema codegen.
+type InvestigationMetadata struct {
+ UpdateTimestamp time.Time `json:"updateTimestamp"`
+ CreatedBy string `json:"createdBy"`
+ Uid string `json:"uid"`
+ CreationTimestamp time.Time `json:"creationTimestamp"`
+ DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"`
+ Finalizers []string `json:"finalizers"`
+ ResourceVersion string `json:"resourceVersion"`
+ Generation int64 `json:"generation"`
+ UpdatedBy string `json:"updatedBy"`
+ Labels map[string]string `json:"labels"`
+}
+
+// NewInvestigationMetadata creates a new InvestigationMetadata object.
+func NewInvestigationMetadata() *InvestigationMetadata {
+ return &InvestigationMetadata{}
+}
diff --git a/apps/investigation/pkg/apis/investigation/v1alpha1/investigation_object_gen.go b/apps/investigations/pkg/apis/investigations/v0alpha1/investigation_object_gen.go
similarity index 94%
rename from apps/investigation/pkg/apis/investigation/v1alpha1/investigation_object_gen.go
rename to apps/investigations/pkg/apis/investigations/v0alpha1/investigation_object_gen.go
index c97fc75eec1..21c8d760fe6 100644
--- a/apps/investigation/pkg/apis/investigation/v1alpha1/investigation_object_gen.go
+++ b/apps/investigations/pkg/apis/investigations/v0alpha1/investigation_object_gen.go
@@ -2,7 +2,7 @@
// Code generated by grafana-app-sdk. DO NOT EDIT.
//
-package v1alpha1
+package v0alpha1
import (
"fmt"
@@ -16,10 +16,10 @@ import (
// +k8s:openapi-gen=true
type Investigation struct {
- metav1.TypeMeta `json:",inline"`
- metav1.ObjectMeta `json:"metadata"`
- Spec InvestigationSpec `json:"spec"`
- InvestigationStatus InvestigationStatus `json:"status"`
+ metav1.TypeMeta `json:",inline" yaml:",inline"`
+ metav1.ObjectMeta `json:"metadata" yaml:"metadata"`
+ Spec InvestigationSpec `json:"spec" yaml:"spec"`
+ InvestigationStatus InvestigationStatus `json:"status" yaml:"status"`
}
func (o *Investigation) GetSpec() any {
@@ -224,9 +224,9 @@ var _ resource.Object = &Investigation{}
// +k8s:openapi-gen=true
type InvestigationList struct {
- metav1.TypeMeta `json:",inline"`
- metav1.ListMeta `json:"metadata"`
- Items []Investigation `json:"items"`
+ metav1.TypeMeta `json:",inline" yaml:",inline"`
+ metav1.ListMeta `json:"metadata" yaml:"metadata"`
+ Items []Investigation `json:"items" yaml:"items"`
}
func (o *InvestigationList) DeepCopyObject() runtime.Object {
diff --git a/apps/investigation/pkg/apis/investigation/v1alpha1/investigation_schema_gen.go b/apps/investigations/pkg/apis/investigations/v0alpha1/investigation_schema_gen.go
similarity index 81%
rename from apps/investigation/pkg/apis/investigation/v1alpha1/investigation_schema_gen.go
rename to apps/investigations/pkg/apis/investigations/v0alpha1/investigation_schema_gen.go
index c20995f0981..2a1f03c884a 100644
--- a/apps/investigation/pkg/apis/investigation/v1alpha1/investigation_schema_gen.go
+++ b/apps/investigations/pkg/apis/investigations/v0alpha1/investigation_schema_gen.go
@@ -2,7 +2,7 @@
// Code generated by grafana-app-sdk. DO NOT EDIT.
//
-package v1alpha1
+package v0alpha1
import (
"github.com/grafana/grafana-app-sdk/resource"
@@ -10,7 +10,7 @@ import (
// schema is unexported to prevent accidental overwrites
var (
- schemaInvestigation = resource.NewSimpleSchema("investigation.grafana.app", "v1alpha1", &Investigation{}, &InvestigationList{}, resource.WithKind("Investigation"),
+ schemaInvestigation = resource.NewSimpleSchema("investigations.grafana.app", "v0alpha1", &Investigation{}, &InvestigationList{}, resource.WithKind("Investigation"),
resource.WithPlural("investigations"), resource.WithScope(resource.NamespacedScope))
kindInvestigation = resource.Kind{
Schema: schemaInvestigation,
diff --git a/apps/investigations/pkg/apis/investigations/v0alpha1/investigation_spec_gen.go b/apps/investigations/pkg/apis/investigations/v0alpha1/investigation_spec_gen.go
new file mode 100644
index 00000000000..3bca90e4579
--- /dev/null
+++ b/apps/investigations/pkg/apis/investigations/v0alpha1/investigation_spec_gen.go
@@ -0,0 +1,140 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+package v0alpha1
+
+// Person represents a user profile with basic information
+// +k8s:openapi-gen=true
+type InvestigationPerson struct {
+ // Unique identifier for the user
+ Uid string `json:"uid"`
+ // Display name of the user
+ Name string `json:"name"`
+ // URL to user's Gravatar image
+ GravatarUrl string `json:"gravatarUrl"`
+}
+
+// NewInvestigationPerson creates a new InvestigationPerson object.
+func NewInvestigationPerson() *InvestigationPerson {
+ return &InvestigationPerson{}
+}
+
+// Collectable represents an item collected during investigation
+// +k8s:openapi-gen=true
+type InvestigationCollectable struct {
+ Id string `json:"id"`
+ CreatedAt string `json:"createdAt"`
+ Title string `json:"title"`
+ Origin string `json:"origin"`
+ Type string `json:"type"`
+ // +listType=atomic
+ Queries []InvestigationQuery `json:"queries"`
+ TimeRange InvestigationTimeRange `json:"timeRange"`
+ Datasource InvestigationDatasourceRef `json:"datasource"`
+ Url string `json:"url"`
+ LogoPath *string `json:"logoPath,omitempty"`
+ Note string `json:"note"`
+ NoteUpdatedAt string `json:"noteUpdatedAt"`
+}
+
+// NewInvestigationCollectable creates a new InvestigationCollectable object.
+func NewInvestigationCollectable() *InvestigationCollectable {
+ return &InvestigationCollectable{
+ TimeRange: *NewInvestigationTimeRange(),
+ Datasource: *NewInvestigationDatasourceRef(),
+ }
+}
+
+// Query represents a data query
+// +k8s:openapi-gen=true
+type InvestigationQuery struct {
+ RefId string `json:"refId"`
+ QueryType string `json:"queryType"`
+ EditorMode string `json:"editorMode"`
+ SupportingQueryType string `json:"supportingQueryType"`
+ LegendFormat string `json:"legendFormat"`
+ Expr string `json:"expr"`
+}
+
+// NewInvestigationQuery creates a new InvestigationQuery object.
+func NewInvestigationQuery() *InvestigationQuery {
+ return &InvestigationQuery{}
+}
+
+// TimeRange represents a time range with both absolute and relative values
+// +k8s:openapi-gen=true
+type InvestigationTimeRange struct {
+ From string `json:"from"`
+ To string `json:"to"`
+ Raw InvestigationV0alpha1TimeRangeRaw `json:"raw"`
+}
+
+// NewInvestigationTimeRange creates a new InvestigationTimeRange object.
+func NewInvestigationTimeRange() *InvestigationTimeRange {
+ return &InvestigationTimeRange{
+ Raw: *NewInvestigationV0alpha1TimeRangeRaw(),
+ }
+}
+
+// DatasourceRef is a reference to a datasource
+// +k8s:openapi-gen=true
+type InvestigationDatasourceRef struct {
+ Uid string `json:"uid"`
+}
+
+// NewInvestigationDatasourceRef creates a new InvestigationDatasourceRef object.
+func NewInvestigationDatasourceRef() *InvestigationDatasourceRef {
+ return &InvestigationDatasourceRef{}
+}
+
+// +k8s:openapi-gen=true
+type InvestigationViewMode struct {
+ Mode InvestigationViewModeMode `json:"mode"`
+ ShowComments bool `json:"showComments"`
+ ShowTooltips bool `json:"showTooltips"`
+}
+
+// NewInvestigationViewMode creates a new InvestigationViewMode object.
+func NewInvestigationViewMode() *InvestigationViewMode {
+ return &InvestigationViewMode{}
+}
+
+// spec is the schema of our resource
+// +k8s:openapi-gen=true
+type InvestigationSpec struct {
+ Title string `json:"title"`
+ CreatedByProfile InvestigationPerson `json:"createdByProfile"`
+ HasCustomName bool `json:"hasCustomName"`
+ IsFavorite bool `json:"isFavorite"`
+ OverviewNote string `json:"overviewNote"`
+ OverviewNoteUpdatedAt string `json:"overviewNoteUpdatedAt"`
+ // +listType=atomic
+ Collectables []InvestigationCollectable `json:"collectables"`
+ ViewMode InvestigationViewMode `json:"viewMode"`
+}
+
+// NewInvestigationSpec creates a new InvestigationSpec object.
+func NewInvestigationSpec() *InvestigationSpec {
+ return &InvestigationSpec{
+ CreatedByProfile: *NewInvestigationPerson(),
+ ViewMode: *NewInvestigationViewMode(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type InvestigationV0alpha1TimeRangeRaw struct {
+ From string `json:"from"`
+ To string `json:"to"`
+}
+
+// NewInvestigationV0alpha1TimeRangeRaw creates a new InvestigationV0alpha1TimeRangeRaw object.
+func NewInvestigationV0alpha1TimeRangeRaw() *InvestigationV0alpha1TimeRangeRaw {
+ return &InvestigationV0alpha1TimeRangeRaw{}
+}
+
+// +k8s:openapi-gen=true
+type InvestigationViewModeMode string
+
+const (
+ InvestigationViewModeModeCompact InvestigationViewModeMode = "compact"
+ InvestigationViewModeModeFull InvestigationViewModeMode = "full"
+)
diff --git a/apps/investigations/pkg/apis/investigations/v0alpha1/investigation_status_gen.go b/apps/investigations/pkg/apis/investigations/v0alpha1/investigation_status_gen.go
new file mode 100644
index 00000000000..c70224b96e4
--- /dev/null
+++ b/apps/investigations/pkg/apis/investigations/v0alpha1/investigation_status_gen.go
@@ -0,0 +1,44 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+package v0alpha1
+
+// +k8s:openapi-gen=true
+type InvestigationstatusOperatorState struct {
+ // lastEvaluation is the ResourceVersion last evaluated
+ LastEvaluation string `json:"lastEvaluation"`
+ // state describes the state of the lastEvaluation.
+ // It is limited to three possible states for machine evaluation.
+ State InvestigationStatusOperatorStateState `json:"state"`
+ // descriptiveState is an optional more descriptive state field which has no requirements on format
+ DescriptiveState *string `json:"descriptiveState,omitempty"`
+ // details contains any extra information that is operator-specific
+ Details map[string]interface{} `json:"details,omitempty"`
+}
+
+// NewInvestigationstatusOperatorState creates a new InvestigationstatusOperatorState object.
+func NewInvestigationstatusOperatorState() *InvestigationstatusOperatorState {
+ return &InvestigationstatusOperatorState{}
+}
+
+// +k8s:openapi-gen=true
+type InvestigationStatus struct {
+ // operatorStates is a map of operator ID to operator state evaluations.
+ // Any operator which consumes this kind SHOULD add its state evaluation information to this field.
+ OperatorStates map[string]InvestigationstatusOperatorState `json:"operatorStates,omitempty"`
+ // additionalFields is reserved for future use
+ AdditionalFields map[string]interface{} `json:"additionalFields,omitempty"`
+}
+
+// NewInvestigationStatus creates a new InvestigationStatus object.
+func NewInvestigationStatus() *InvestigationStatus {
+ return &InvestigationStatus{}
+}
+
+// +k8s:openapi-gen=true
+type InvestigationStatusOperatorStateState string
+
+const (
+ InvestigationStatusOperatorStateStateSuccess InvestigationStatusOperatorStateState = "success"
+ InvestigationStatusOperatorStateStateInProgress InvestigationStatusOperatorStateState = "in_progress"
+ InvestigationStatusOperatorStateStateFailed InvestigationStatusOperatorStateState = "failed"
+)
diff --git a/apps/investigations/pkg/apis/investigations/v0alpha1/investigationindex_codec_gen.go b/apps/investigations/pkg/apis/investigations/v0alpha1/investigationindex_codec_gen.go
new file mode 100644
index 00000000000..0496ce4af6f
--- /dev/null
+++ b/apps/investigations/pkg/apis/investigations/v0alpha1/investigationindex_codec_gen.go
@@ -0,0 +1,28 @@
+//
+// Code generated by grafana-app-sdk. DO NOT EDIT.
+//
+
+package v0alpha1
+
+import (
+ "encoding/json"
+ "io"
+
+ "github.com/grafana/grafana-app-sdk/resource"
+)
+
+// InvestigationIndexJSONCodec is an implementation of resource.Codec for kubernetes JSON encoding
+type InvestigationIndexJSONCodec struct{}
+
+// Read reads JSON-encoded bytes from `reader` and unmarshals them into `into`
+func (*InvestigationIndexJSONCodec) Read(reader io.Reader, into resource.Object) error {
+ return json.NewDecoder(reader).Decode(into)
+}
+
+// Write writes JSON-encoded bytes into `writer` marshaled from `from`
+func (*InvestigationIndexJSONCodec) Write(writer io.Writer, from resource.Object) error {
+ return json.NewEncoder(writer).Encode(from)
+}
+
+// Interface compliance checks
+var _ resource.Codec = &InvestigationIndexJSONCodec{}
diff --git a/apps/investigations/pkg/apis/investigations/v0alpha1/investigationindex_metadata_gen.go b/apps/investigations/pkg/apis/investigations/v0alpha1/investigationindex_metadata_gen.go
new file mode 100644
index 00000000000..67e97598a93
--- /dev/null
+++ b/apps/investigations/pkg/apis/investigations/v0alpha1/investigationindex_metadata_gen.go
@@ -0,0 +1,28 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+package v0alpha1
+
+import (
+ time "time"
+)
+
+// metadata contains embedded CommonMetadata and can be extended with custom string fields
+// TODO: use CommonMetadata instead of redefining here; currently needs to be defined here
+// without external reference as using the CommonMetadata reference breaks thema codegen.
+type InvestigationIndexMetadata struct {
+ UpdateTimestamp time.Time `json:"updateTimestamp"`
+ CreatedBy string `json:"createdBy"`
+ Uid string `json:"uid"`
+ CreationTimestamp time.Time `json:"creationTimestamp"`
+ DeletionTimestamp *time.Time `json:"deletionTimestamp,omitempty"`
+ Finalizers []string `json:"finalizers"`
+ ResourceVersion string `json:"resourceVersion"`
+ Generation int64 `json:"generation"`
+ UpdatedBy string `json:"updatedBy"`
+ Labels map[string]string `json:"labels"`
+}
+
+// NewInvestigationIndexMetadata creates a new InvestigationIndexMetadata object.
+func NewInvestigationIndexMetadata() *InvestigationIndexMetadata {
+ return &InvestigationIndexMetadata{}
+}
diff --git a/apps/investigations/pkg/apis/investigations/v0alpha1/investigationindex_object_gen.go b/apps/investigations/pkg/apis/investigations/v0alpha1/investigationindex_object_gen.go
new file mode 100644
index 00000000000..cc3c33964ed
--- /dev/null
+++ b/apps/investigations/pkg/apis/investigations/v0alpha1/investigationindex_object_gen.go
@@ -0,0 +1,266 @@
+//
+// Code generated by grafana-app-sdk. DO NOT EDIT.
+//
+
+package v0alpha1
+
+import (
+ "fmt"
+ "github.com/grafana/grafana-app-sdk/resource"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/apimachinery/pkg/runtime/schema"
+ "k8s.io/apimachinery/pkg/types"
+ "time"
+)
+
+// +k8s:openapi-gen=true
+type InvestigationIndex struct {
+ metav1.TypeMeta `json:",inline" yaml:",inline"`
+ metav1.ObjectMeta `json:"metadata" yaml:"metadata"`
+ Spec InvestigationIndexSpec `json:"spec" yaml:"spec"`
+ InvestigationIndexStatus InvestigationIndexStatus `json:"status" yaml:"status"`
+}
+
+func (o *InvestigationIndex) GetSpec() any {
+ return o.Spec
+}
+
+func (o *InvestigationIndex) SetSpec(spec any) error {
+ cast, ok := spec.(InvestigationIndexSpec)
+ if !ok {
+ return fmt.Errorf("cannot set spec type %#v, not of type Spec", spec)
+ }
+ o.Spec = cast
+ return nil
+}
+
+func (o *InvestigationIndex) GetSubresources() map[string]any {
+ return map[string]any{
+ "status": o.InvestigationIndexStatus,
+ }
+}
+
+func (o *InvestigationIndex) GetSubresource(name string) (any, bool) {
+ switch name {
+ case "status":
+ return o.InvestigationIndexStatus, true
+ default:
+ return nil, false
+ }
+}
+
+func (o *InvestigationIndex) SetSubresource(name string, value any) error {
+ switch name {
+ case "status":
+ cast, ok := value.(InvestigationIndexStatus)
+ if !ok {
+ return fmt.Errorf("cannot set status type %#v, not of type InvestigationIndexStatus", value)
+ }
+ o.InvestigationIndexStatus = cast
+ return nil
+ default:
+ return fmt.Errorf("subresource '%s' does not exist", name)
+ }
+}
+
+func (o *InvestigationIndex) GetStaticMetadata() resource.StaticMetadata {
+ gvk := o.GroupVersionKind()
+ return resource.StaticMetadata{
+ Name: o.ObjectMeta.Name,
+ Namespace: o.ObjectMeta.Namespace,
+ Group: gvk.Group,
+ Version: gvk.Version,
+ Kind: gvk.Kind,
+ }
+}
+
+func (o *InvestigationIndex) SetStaticMetadata(metadata resource.StaticMetadata) {
+ o.Name = metadata.Name
+ o.Namespace = metadata.Namespace
+ o.SetGroupVersionKind(schema.GroupVersionKind{
+ Group: metadata.Group,
+ Version: metadata.Version,
+ Kind: metadata.Kind,
+ })
+}
+
+func (o *InvestigationIndex) GetCommonMetadata() resource.CommonMetadata {
+ dt := o.DeletionTimestamp
+ var deletionTimestamp *time.Time
+ if dt != nil {
+ deletionTimestamp = &dt.Time
+ }
+ // Legacy ExtraFields support
+ extraFields := make(map[string]any)
+ if o.Annotations != nil {
+ extraFields["annotations"] = o.Annotations
+ }
+ if o.ManagedFields != nil {
+ extraFields["managedFields"] = o.ManagedFields
+ }
+ if o.OwnerReferences != nil {
+ extraFields["ownerReferences"] = o.OwnerReferences
+ }
+ return resource.CommonMetadata{
+ UID: string(o.UID),
+ ResourceVersion: o.ResourceVersion,
+ Generation: o.Generation,
+ Labels: o.Labels,
+ CreationTimestamp: o.CreationTimestamp.Time,
+ DeletionTimestamp: deletionTimestamp,
+ Finalizers: o.Finalizers,
+ UpdateTimestamp: o.GetUpdateTimestamp(),
+ CreatedBy: o.GetCreatedBy(),
+ UpdatedBy: o.GetUpdatedBy(),
+ ExtraFields: extraFields,
+ }
+}
+
+func (o *InvestigationIndex) SetCommonMetadata(metadata resource.CommonMetadata) {
+ o.UID = types.UID(metadata.UID)
+ o.ResourceVersion = metadata.ResourceVersion
+ o.Generation = metadata.Generation
+ o.Labels = metadata.Labels
+ o.CreationTimestamp = metav1.NewTime(metadata.CreationTimestamp)
+ if metadata.DeletionTimestamp != nil {
+ dt := metav1.NewTime(*metadata.DeletionTimestamp)
+ o.DeletionTimestamp = &dt
+ } else {
+ o.DeletionTimestamp = nil
+ }
+ o.Finalizers = metadata.Finalizers
+ if o.Annotations == nil {
+ o.Annotations = make(map[string]string)
+ }
+ if !metadata.UpdateTimestamp.IsZero() {
+ o.SetUpdateTimestamp(metadata.UpdateTimestamp)
+ }
+ if metadata.CreatedBy != "" {
+ o.SetCreatedBy(metadata.CreatedBy)
+ }
+ if metadata.UpdatedBy != "" {
+ o.SetUpdatedBy(metadata.UpdatedBy)
+ }
+ // Legacy support for setting Annotations, ManagedFields, and OwnerReferences via ExtraFields
+ if metadata.ExtraFields != nil {
+ if annotations, ok := metadata.ExtraFields["annotations"]; ok {
+ if cast, ok := annotations.(map[string]string); ok {
+ o.Annotations = cast
+ }
+ }
+ if managedFields, ok := metadata.ExtraFields["managedFields"]; ok {
+ if cast, ok := managedFields.([]metav1.ManagedFieldsEntry); ok {
+ o.ManagedFields = cast
+ }
+ }
+ if ownerReferences, ok := metadata.ExtraFields["ownerReferences"]; ok {
+ if cast, ok := ownerReferences.([]metav1.OwnerReference); ok {
+ o.OwnerReferences = cast
+ }
+ }
+ }
+}
+
+func (o *InvestigationIndex) GetCreatedBy() string {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ return o.ObjectMeta.Annotations["grafana.com/createdBy"]
+}
+
+func (o *InvestigationIndex) SetCreatedBy(createdBy string) {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ o.ObjectMeta.Annotations["grafana.com/createdBy"] = createdBy
+}
+
+func (o *InvestigationIndex) GetUpdateTimestamp() time.Time {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ parsed, _ := time.Parse(time.RFC3339, o.ObjectMeta.Annotations["grafana.com/updateTimestamp"])
+ return parsed
+}
+
+func (o *InvestigationIndex) SetUpdateTimestamp(updateTimestamp time.Time) {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ o.ObjectMeta.Annotations["grafana.com/updateTimestamp"] = updateTimestamp.Format(time.RFC3339)
+}
+
+func (o *InvestigationIndex) GetUpdatedBy() string {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ return o.ObjectMeta.Annotations["grafana.com/updatedBy"]
+}
+
+func (o *InvestigationIndex) SetUpdatedBy(updatedBy string) {
+ if o.ObjectMeta.Annotations == nil {
+ o.ObjectMeta.Annotations = make(map[string]string)
+ }
+
+ o.ObjectMeta.Annotations["grafana.com/updatedBy"] = updatedBy
+}
+
+func (o *InvestigationIndex) Copy() resource.Object {
+ return resource.CopyObject(o)
+}
+
+func (o *InvestigationIndex) DeepCopyObject() runtime.Object {
+ return o.Copy()
+}
+
+// Interface compliance compile-time check
+var _ resource.Object = &InvestigationIndex{}
+
+// +k8s:openapi-gen=true
+type InvestigationIndexList struct {
+ metav1.TypeMeta `json:",inline" yaml:",inline"`
+ metav1.ListMeta `json:"metadata" yaml:"metadata"`
+ Items []InvestigationIndex `json:"items" yaml:"items"`
+}
+
+func (o *InvestigationIndexList) DeepCopyObject() runtime.Object {
+ return o.Copy()
+}
+
+func (o *InvestigationIndexList) Copy() resource.ListObject {
+ cpy := &InvestigationIndexList{
+ TypeMeta: o.TypeMeta,
+ Items: make([]InvestigationIndex, len(o.Items)),
+ }
+ o.ListMeta.DeepCopyInto(&cpy.ListMeta)
+ for i := 0; i < len(o.Items); i++ {
+ if item, ok := o.Items[i].Copy().(*InvestigationIndex); ok {
+ cpy.Items[i] = *item
+ }
+ }
+ return cpy
+}
+
+func (o *InvestigationIndexList) GetItems() []resource.Object {
+ items := make([]resource.Object, len(o.Items))
+ for i := 0; i < len(o.Items); i++ {
+ items[i] = &o.Items[i]
+ }
+ return items
+}
+
+func (o *InvestigationIndexList) SetItems(items []resource.Object) {
+ o.Items = make([]InvestigationIndex, len(items))
+ for i := 0; i < len(items); i++ {
+ o.Items[i] = *items[i].(*InvestigationIndex)
+ }
+}
+
+// Interface compliance compile-time check
+var _ resource.ListObject = &InvestigationIndexList{}
diff --git a/apps/investigations/pkg/apis/investigations/v0alpha1/investigationindex_schema_gen.go b/apps/investigations/pkg/apis/investigations/v0alpha1/investigationindex_schema_gen.go
new file mode 100644
index 00000000000..3a0041dc6b8
--- /dev/null
+++ b/apps/investigations/pkg/apis/investigations/v0alpha1/investigationindex_schema_gen.go
@@ -0,0 +1,34 @@
+//
+// Code generated by grafana-app-sdk. DO NOT EDIT.
+//
+
+package v0alpha1
+
+import (
+ "github.com/grafana/grafana-app-sdk/resource"
+)
+
+// schema is unexported to prevent accidental overwrites
+var (
+ schemaInvestigationIndex = resource.NewSimpleSchema("investigations.grafana.app", "v0alpha1", &InvestigationIndex{}, &InvestigationIndexList{}, resource.WithKind("InvestigationIndex"),
+ resource.WithPlural("investigationindexes"), resource.WithScope(resource.NamespacedScope))
+ kindInvestigationIndex = resource.Kind{
+ Schema: schemaInvestigationIndex,
+ Codecs: map[resource.KindEncoding]resource.Codec{
+ resource.KindEncodingJSON: &InvestigationIndexJSONCodec{},
+ },
+ }
+)
+
+// Kind returns a resource.Kind for this Schema with a JSON codec
+func InvestigationIndexKind() resource.Kind {
+ return kindInvestigationIndex
+}
+
+// Schema returns a resource.SimpleSchema representation of InvestigationIndex
+func InvestigationIndexSchema() *resource.SimpleSchema {
+ return schemaInvestigationIndex
+}
+
+// Interface compliance checks
+var _ resource.Schema = kindInvestigationIndex
diff --git a/apps/investigations/pkg/apis/investigations/v0alpha1/investigationindex_spec_gen.go b/apps/investigations/pkg/apis/investigations/v0alpha1/investigationindex_spec_gen.go
new file mode 100644
index 00000000000..4180a63a326
--- /dev/null
+++ b/apps/investigations/pkg/apis/investigations/v0alpha1/investigationindex_spec_gen.go
@@ -0,0 +1,92 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+package v0alpha1
+
+// Person represents a user profile with basic information
+// +k8s:openapi-gen=true
+type InvestigationIndexPerson struct {
+ // Unique identifier for the user
+ Uid string `json:"uid"`
+ // Display name of the user
+ Name string `json:"name"`
+ // URL to user's Gravatar image
+ GravatarUrl string `json:"gravatarUrl"`
+}
+
+// NewInvestigationIndexPerson creates a new InvestigationIndexPerson object.
+func NewInvestigationIndexPerson() *InvestigationIndexPerson {
+ return &InvestigationIndexPerson{}
+}
+
+// Type definition for investigation summaries
+// +k8s:openapi-gen=true
+type InvestigationIndexInvestigationSummary struct {
+ Title string `json:"title"`
+ CreatedByProfile InvestigationIndexPerson `json:"createdByProfile"`
+ HasCustomName bool `json:"hasCustomName"`
+ IsFavorite bool `json:"isFavorite"`
+ OverviewNote string `json:"overviewNote"`
+ OverviewNoteUpdatedAt string `json:"overviewNoteUpdatedAt"`
+ ViewMode InvestigationIndexViewMode `json:"viewMode"`
+ // +listType=atomic
+ CollectableSummaries []InvestigationIndexCollectableSummary `json:"collectableSummaries"`
+}
+
+// NewInvestigationIndexInvestigationSummary creates a new InvestigationIndexInvestigationSummary object.
+func NewInvestigationIndexInvestigationSummary() *InvestigationIndexInvestigationSummary {
+ return &InvestigationIndexInvestigationSummary{
+ CreatedByProfile: *NewInvestigationIndexPerson(),
+ ViewMode: *NewInvestigationIndexViewMode(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type InvestigationIndexViewMode struct {
+ Mode InvestigationIndexViewModeMode `json:"mode"`
+ ShowComments bool `json:"showComments"`
+ ShowTooltips bool `json:"showTooltips"`
+}
+
+// NewInvestigationIndexViewMode creates a new InvestigationIndexViewMode object.
+func NewInvestigationIndexViewMode() *InvestigationIndexViewMode {
+ return &InvestigationIndexViewMode{}
+}
+
+// +k8s:openapi-gen=true
+type InvestigationIndexCollectableSummary struct {
+ Id string `json:"id"`
+ Title string `json:"title"`
+ LogoPath string `json:"logoPath"`
+ Origin string `json:"origin"`
+}
+
+// NewInvestigationIndexCollectableSummary creates a new InvestigationIndexCollectableSummary object.
+func NewInvestigationIndexCollectableSummary() *InvestigationIndexCollectableSummary {
+ return &InvestigationIndexCollectableSummary{}
+}
+
+// +k8s:openapi-gen=true
+type InvestigationIndexSpec struct {
+ // Title of the index, e.g. 'Favorites' or 'My Investigations'
+ Title string `json:"title"`
+ // The Person who owns this investigation index
+ Owner InvestigationIndexPerson `json:"owner"`
+ // Array of investigation summaries
+ // +listType=atomic
+ InvestigationSummaries []InvestigationIndexInvestigationSummary `json:"investigationSummaries"`
+}
+
+// NewInvestigationIndexSpec creates a new InvestigationIndexSpec object.
+func NewInvestigationIndexSpec() *InvestigationIndexSpec {
+ return &InvestigationIndexSpec{
+ Owner: *NewInvestigationIndexPerson(),
+ }
+}
+
+// +k8s:openapi-gen=true
+type InvestigationIndexViewModeMode string
+
+const (
+ InvestigationIndexViewModeModeCompact InvestigationIndexViewModeMode = "compact"
+ InvestigationIndexViewModeModeFull InvestigationIndexViewModeMode = "full"
+)
diff --git a/apps/investigations/pkg/apis/investigations/v0alpha1/investigationindex_status_gen.go b/apps/investigations/pkg/apis/investigations/v0alpha1/investigationindex_status_gen.go
new file mode 100644
index 00000000000..455d39bdb48
--- /dev/null
+++ b/apps/investigations/pkg/apis/investigations/v0alpha1/investigationindex_status_gen.go
@@ -0,0 +1,44 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+package v0alpha1
+
+// +k8s:openapi-gen=true
+type InvestigationIndexstatusOperatorState struct {
+ // lastEvaluation is the ResourceVersion last evaluated
+ LastEvaluation string `json:"lastEvaluation"`
+ // state describes the state of the lastEvaluation.
+ // It is limited to three possible states for machine evaluation.
+ State InvestigationIndexStatusOperatorStateState `json:"state"`
+ // descriptiveState is an optional more descriptive state field which has no requirements on format
+ DescriptiveState *string `json:"descriptiveState,omitempty"`
+ // details contains any extra information that is operator-specific
+ Details map[string]interface{} `json:"details,omitempty"`
+}
+
+// NewInvestigationIndexstatusOperatorState creates a new InvestigationIndexstatusOperatorState object.
+func NewInvestigationIndexstatusOperatorState() *InvestigationIndexstatusOperatorState {
+ return &InvestigationIndexstatusOperatorState{}
+}
+
+// +k8s:openapi-gen=true
+type InvestigationIndexStatus struct {
+ // operatorStates is a map of operator ID to operator state evaluations.
+ // Any operator which consumes this kind SHOULD add its state evaluation information to this field.
+ OperatorStates map[string]InvestigationIndexstatusOperatorState `json:"operatorStates,omitempty"`
+ // additionalFields is reserved for future use
+ AdditionalFields map[string]interface{} `json:"additionalFields,omitempty"`
+}
+
+// NewInvestigationIndexStatus creates a new InvestigationIndexStatus object.
+func NewInvestigationIndexStatus() *InvestigationIndexStatus {
+ return &InvestigationIndexStatus{}
+}
+
+// +k8s:openapi-gen=true
+type InvestigationIndexStatusOperatorStateState string
+
+const (
+ InvestigationIndexStatusOperatorStateStateSuccess InvestigationIndexStatusOperatorStateState = "success"
+ InvestigationIndexStatusOperatorStateStateInProgress InvestigationIndexStatusOperatorStateState = "in_progress"
+ InvestigationIndexStatusOperatorStateStateFailed InvestigationIndexStatusOperatorStateState = "failed"
+)
diff --git a/apps/investigations/pkg/apis/investigations/v0alpha1/zz_openapi_gen.go b/apps/investigations/pkg/apis/investigations/v0alpha1/zz_openapi_gen.go
new file mode 100644
index 00000000000..36648cfcd11
--- /dev/null
+++ b/apps/investigations/pkg/apis/investigations/v0alpha1/zz_openapi_gen.go
@@ -0,0 +1,1061 @@
+//go:build !ignore_autogenerated
+// +build !ignore_autogenerated
+
+// Code generated by grafana-app-sdk. DO NOT EDIT.
+
+package v0alpha1
+
+import (
+ common "k8s.io/kube-openapi/pkg/common"
+ spec "k8s.io/kube-openapi/pkg/validation/spec"
+)
+
+func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition {
+ return map[string]common.OpenAPIDefinition{
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.Investigation": schema_pkg_apis_investigations_v0alpha1_Investigation(ref),
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationCollectable": schema_pkg_apis_investigations_v0alpha1_InvestigationCollectable(ref),
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationDatasourceRef": schema_pkg_apis_investigations_v0alpha1_InvestigationDatasourceRef(ref),
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationIndex": schema_pkg_apis_investigations_v0alpha1_InvestigationIndex(ref),
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationIndexCollectableSummary": schema_pkg_apis_investigations_v0alpha1_InvestigationIndexCollectableSummary(ref),
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationIndexInvestigationSummary": schema_pkg_apis_investigations_v0alpha1_InvestigationIndexInvestigationSummary(ref),
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationIndexList": schema_pkg_apis_investigations_v0alpha1_InvestigationIndexList(ref),
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationIndexPerson": schema_pkg_apis_investigations_v0alpha1_InvestigationIndexPerson(ref),
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationIndexSpec": schema_pkg_apis_investigations_v0alpha1_InvestigationIndexSpec(ref),
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationIndexStatus": schema_pkg_apis_investigations_v0alpha1_InvestigationIndexStatus(ref),
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationIndexViewMode": schema_pkg_apis_investigations_v0alpha1_InvestigationIndexViewMode(ref),
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationIndexstatusOperatorState": schema_pkg_apis_investigations_v0alpha1_InvestigationIndexstatusOperatorState(ref),
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationList": schema_pkg_apis_investigations_v0alpha1_InvestigationList(ref),
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationPerson": schema_pkg_apis_investigations_v0alpha1_InvestigationPerson(ref),
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationQuery": schema_pkg_apis_investigations_v0alpha1_InvestigationQuery(ref),
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationSpec": schema_pkg_apis_investigations_v0alpha1_InvestigationSpec(ref),
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationStatus": schema_pkg_apis_investigations_v0alpha1_InvestigationStatus(ref),
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationTimeRange": schema_pkg_apis_investigations_v0alpha1_InvestigationTimeRange(ref),
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationV0alpha1TimeRangeRaw": schema_pkg_apis_investigations_v0alpha1_InvestigationV0alpha1TimeRangeRaw(ref),
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationViewMode": schema_pkg_apis_investigations_v0alpha1_InvestigationViewMode(ref),
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationstatusOperatorState": schema_pkg_apis_investigations_v0alpha1_InvestigationstatusOperatorState(ref),
+ }
+}
+
+func schema_pkg_apis_investigations_v0alpha1_Investigation(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "apiVersion": {
+ SchemaProps: spec.SchemaProps{
+ Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "metadata": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"),
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationSpec"),
+ },
+ },
+ "status": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationStatus"),
+ },
+ },
+ },
+ Required: []string{"metadata", "spec", "status"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationSpec", "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
+ }
+}
+
+func schema_pkg_apis_investigations_v0alpha1_InvestigationCollectable(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Collectable represents an item collected during investigation",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "id": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "createdAt": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "title": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "origin": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "type": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "queries": {
+ VendorExtensible: spec.VendorExtensible{
+ Extensions: spec.Extensions{
+ "x-kubernetes-list-type": "atomic",
+ },
+ },
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationQuery"),
+ },
+ },
+ },
+ },
+ },
+ "timeRange": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationTimeRange"),
+ },
+ },
+ "datasource": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationDatasourceRef"),
+ },
+ },
+ "url": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "logoPath": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "note": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "noteUpdatedAt": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"id", "createdAt", "title", "origin", "type", "queries", "timeRange", "datasource", "url", "note", "noteUpdatedAt"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationDatasourceRef", "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationQuery", "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationTimeRange"},
+ }
+}
+
+func schema_pkg_apis_investigations_v0alpha1_InvestigationDatasourceRef(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "DatasourceRef is a reference to a datasource",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "uid": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"uid"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_investigations_v0alpha1_InvestigationIndex(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "apiVersion": {
+ SchemaProps: spec.SchemaProps{
+ Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "metadata": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"),
+ },
+ },
+ "spec": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationIndexSpec"),
+ },
+ },
+ "status": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationIndexStatus"),
+ },
+ },
+ },
+ Required: []string{"metadata", "spec", "status"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationIndexSpec", "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationIndexStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"},
+ }
+}
+
+func schema_pkg_apis_investigations_v0alpha1_InvestigationIndexCollectableSummary(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "id": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "title": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "logoPath": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "origin": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"id", "title", "logoPath", "origin"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_investigations_v0alpha1_InvestigationIndexInvestigationSummary(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Type definition for investigation summaries",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "title": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "createdByProfile": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationIndexPerson"),
+ },
+ },
+ "hasCustomName": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "isFavorite": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "overviewNote": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "overviewNoteUpdatedAt": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "viewMode": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationIndexViewMode"),
+ },
+ },
+ "collectableSummaries": {
+ VendorExtensible: spec.VendorExtensible{
+ Extensions: spec.Extensions{
+ "x-kubernetes-list-type": "atomic",
+ },
+ },
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationIndexCollectableSummary"),
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"title", "createdByProfile", "hasCustomName", "isFavorite", "overviewNote", "overviewNoteUpdatedAt", "viewMode", "collectableSummaries"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationIndexCollectableSummary", "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationIndexPerson", "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationIndexViewMode"},
+ }
+}
+
+func schema_pkg_apis_investigations_v0alpha1_InvestigationIndexList(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "apiVersion": {
+ SchemaProps: spec.SchemaProps{
+ Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "metadata": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"),
+ },
+ },
+ "items": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationIndex"),
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"metadata", "items"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationIndex", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
+ }
+}
+
+func schema_pkg_apis_investigations_v0alpha1_InvestigationIndexPerson(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Person represents a user profile with basic information",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "uid": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Unique identifier for the user",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "name": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Display name of the user",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "gravatarUrl": {
+ SchemaProps: spec.SchemaProps{
+ Description: "URL to user's Gravatar image",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"uid", "name", "gravatarUrl"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_investigations_v0alpha1_InvestigationIndexSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "title": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Title of the index, e.g. 'Favorites' or 'My Investigations'",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "owner": {
+ SchemaProps: spec.SchemaProps{
+ Description: "The Person who owns this investigation index",
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationIndexPerson"),
+ },
+ },
+ "investigationSummaries": {
+ VendorExtensible: spec.VendorExtensible{
+ Extensions: spec.Extensions{
+ "x-kubernetes-list-type": "atomic",
+ },
+ },
+ SchemaProps: spec.SchemaProps{
+ Description: "Array of investigation summaries",
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationIndexInvestigationSummary"),
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"title", "owner", "investigationSummaries"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationIndexInvestigationSummary", "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationIndexPerson"},
+ }
+}
+
+func schema_pkg_apis_investigations_v0alpha1_InvestigationIndexStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "operatorStates": {
+ SchemaProps: spec.SchemaProps{
+ Description: "operatorStates is a map of operator ID to operator state evaluations. Any operator which consumes this kind SHOULD add its state evaluation information to this field.",
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationIndexstatusOperatorState"),
+ },
+ },
+ },
+ },
+ },
+ "additionalFields": {
+ SchemaProps: spec.SchemaProps{
+ Description: "additionalFields is reserved for future use",
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationIndexstatusOperatorState"},
+ }
+}
+
+func schema_pkg_apis_investigations_v0alpha1_InvestigationIndexViewMode(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "mode": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "showComments": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "showTooltips": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"mode", "showComments", "showTooltips"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_investigations_v0alpha1_InvestigationIndexstatusOperatorState(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "lastEvaluation": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastEvaluation is the ResourceVersion last evaluated",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "state": {
+ SchemaProps: spec.SchemaProps{
+ Description: "state describes the state of the lastEvaluation. It is limited to three possible states for machine evaluation.",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "descriptiveState": {
+ SchemaProps: spec.SchemaProps{
+ Description: "descriptiveState is an optional more descriptive state field which has no requirements on format",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "details": {
+ SchemaProps: spec.SchemaProps{
+ Description: "details contains any extra information that is operator-specific",
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"lastEvaluation", "state"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_investigations_v0alpha1_InvestigationList(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "kind": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "apiVersion": {
+ SchemaProps: spec.SchemaProps{
+ Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "metadata": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"),
+ },
+ },
+ "items": {
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.Investigation"),
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"metadata", "items"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.Investigation", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"},
+ }
+}
+
+func schema_pkg_apis_investigations_v0alpha1_InvestigationPerson(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Person represents a user profile with basic information",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "uid": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Unique identifier for the user",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "name": {
+ SchemaProps: spec.SchemaProps{
+ Description: "Display name of the user",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "gravatarUrl": {
+ SchemaProps: spec.SchemaProps{
+ Description: "URL to user's Gravatar image",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"uid", "name", "gravatarUrl"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_investigations_v0alpha1_InvestigationQuery(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "Query represents a data query",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "refId": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "queryType": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "editorMode": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "supportingQueryType": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "legendFormat": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "expr": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"refId", "queryType", "editorMode", "supportingQueryType", "legendFormat", "expr"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_investigations_v0alpha1_InvestigationSpec(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "spec is the schema of our resource",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "title": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "createdByProfile": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationPerson"),
+ },
+ },
+ "hasCustomName": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "isFavorite": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "overviewNote": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "overviewNoteUpdatedAt": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "collectables": {
+ VendorExtensible: spec.VendorExtensible{
+ Extensions: spec.Extensions{
+ "x-kubernetes-list-type": "atomic",
+ },
+ },
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"array"},
+ Items: &spec.SchemaOrArray{
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationCollectable"),
+ },
+ },
+ },
+ },
+ },
+ "viewMode": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationViewMode"),
+ },
+ },
+ },
+ Required: []string{"title", "createdByProfile", "hasCustomName", "isFavorite", "overviewNote", "overviewNoteUpdatedAt", "collectables", "viewMode"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationCollectable", "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationPerson", "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationViewMode"},
+ }
+}
+
+func schema_pkg_apis_investigations_v0alpha1_InvestigationStatus(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "operatorStates": {
+ SchemaProps: spec.SchemaProps{
+ Description: "operatorStates is a map of operator ID to operator state evaluations. Any operator which consumes this kind SHOULD add its state evaluation information to this field.",
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationstatusOperatorState"),
+ },
+ },
+ },
+ },
+ },
+ "additionalFields": {
+ SchemaProps: spec.SchemaProps{
+ Description: "additionalFields is reserved for future use",
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationstatusOperatorState"},
+ }
+}
+
+func schema_pkg_apis_investigations_v0alpha1_InvestigationTimeRange(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Description: "TimeRange represents a time range with both absolute and relative values",
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "from": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "to": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "raw": {
+ SchemaProps: spec.SchemaProps{
+ Default: map[string]interface{}{},
+ Ref: ref("github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationV0alpha1TimeRangeRaw"),
+ },
+ },
+ },
+ Required: []string{"from", "to", "raw"},
+ },
+ },
+ Dependencies: []string{
+ "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1.InvestigationV0alpha1TimeRangeRaw"},
+ }
+}
+
+func schema_pkg_apis_investigations_v0alpha1_InvestigationV0alpha1TimeRangeRaw(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "from": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "to": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"from", "to"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_investigations_v0alpha1_InvestigationViewMode(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "mode": {
+ SchemaProps: spec.SchemaProps{
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "showComments": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ "showTooltips": {
+ SchemaProps: spec.SchemaProps{
+ Default: false,
+ Type: []string{"boolean"},
+ Format: "",
+ },
+ },
+ },
+ Required: []string{"mode", "showComments", "showTooltips"},
+ },
+ },
+ }
+}
+
+func schema_pkg_apis_investigations_v0alpha1_InvestigationstatusOperatorState(ref common.ReferenceCallback) common.OpenAPIDefinition {
+ return common.OpenAPIDefinition{
+ Schema: spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Properties: map[string]spec.Schema{
+ "lastEvaluation": {
+ SchemaProps: spec.SchemaProps{
+ Description: "lastEvaluation is the ResourceVersion last evaluated",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "state": {
+ SchemaProps: spec.SchemaProps{
+ Description: "state describes the state of the lastEvaluation. It is limited to three possible states for machine evaluation.",
+ Default: "",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "descriptiveState": {
+ SchemaProps: spec.SchemaProps{
+ Description: "descriptiveState is an optional more descriptive state field which has no requirements on format",
+ Type: []string{"string"},
+ Format: "",
+ },
+ },
+ "details": {
+ SchemaProps: spec.SchemaProps{
+ Description: "details contains any extra information that is operator-specific",
+ Type: []string{"object"},
+ AdditionalProperties: &spec.SchemaOrBool{
+ Allows: true,
+ Schema: &spec.Schema{
+ SchemaProps: spec.SchemaProps{
+ Type: []string{"object"},
+ Format: "",
+ },
+ },
+ },
+ },
+ },
+ },
+ Required: []string{"lastEvaluation", "state"},
+ },
+ },
+ }
+}
diff --git a/apps/investigations/pkg/apis/investigations_manifest.go b/apps/investigations/pkg/apis/investigations_manifest.go
new file mode 100644
index 00000000000..eed596424bc
--- /dev/null
+++ b/apps/investigations/pkg/apis/investigations_manifest.go
@@ -0,0 +1,65 @@
+//
+// This file is generated by grafana-app-sdk
+// DO NOT EDIT
+//
+
+package apis
+
+import (
+ "encoding/json"
+
+ "github.com/grafana/grafana-app-sdk/app"
+)
+
+var (
+ rawSchemaInvestigationv0alpha1 = []byte(`{"spec":{"description":"spec is the schema of our resource","properties":{"collectables":{"items":{"properties":{"createdAt":{"type":"string"},"datasource":{"properties":{"uid":{"type":"string"}},"required":["uid"],"type":"object"},"id":{"type":"string"},"logoPath":{"type":"string"},"note":{"type":"string"},"noteUpdatedAt":{"type":"string"},"origin":{"type":"string"},"queries":{"items":{"properties":{"editorMode":{"type":"string"},"expr":{"type":"string"},"legendFormat":{"type":"string"},"queryType":{"type":"string"},"refId":{"type":"string"},"supportingQueryType":{"type":"string"}},"required":["refId","queryType","editorMode","supportingQueryType","legendFormat","expr"],"type":"object"},"type":"array"},"timeRange":{"properties":{"from":{"type":"string"},"raw":{"properties":{"from":{"type":"string"},"to":{"type":"string"}},"required":["from","to"],"type":"object"},"to":{"type":"string"}},"required":["from","to","raw"],"type":"object"},"title":{"type":"string"},"type":{"type":"string"},"url":{"type":"string"}},"required":["id","createdAt","title","origin","type","queries","timeRange","datasource","url","note","noteUpdatedAt"],"type":"object"},"type":"array"},"createdByProfile":{"properties":{"gravatarUrl":{"type":"string"},"name":{"type":"string"},"uid":{"type":"string"}},"required":["uid","name","gravatarUrl"],"type":"object"},"hasCustomName":{"type":"boolean"},"isFavorite":{"type":"boolean"},"overviewNote":{"type":"string"},"overviewNoteUpdatedAt":{"type":"string"},"title":{"type":"string"},"viewMode":{"properties":{"mode":{"enum":["compact","full"],"type":"string"},"showComments":{"type":"boolean"},"showTooltips":{"type":"boolean"}},"required":["mode","showComments","showTooltips"],"type":"object"}},"required":["title","createdByProfile","hasCustomName","isFavorite","overviewNote","overviewNoteUpdatedAt","collectables","viewMode"],"type":"object"},"status":{"properties":{"additionalFields":{"description":"additionalFields is reserved for future use","type":"object","x-kubernetes-preserve-unknown-fields":true},"operatorStates":{"additionalProperties":{"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"description":"details contains any extra information that is operator-specific","type":"object","x-kubernetes-preserve-unknown-fields":true},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object","x-kubernetes-preserve-unknown-fields":true}}`)
+ versionSchemaInvestigationv0alpha1 app.VersionSchema
+ _ = json.Unmarshal(rawSchemaInvestigationv0alpha1, &versionSchemaInvestigationv0alpha1)
+ rawSchemaInvestigationIndexv0alpha1 = []byte(`{"spec":{"properties":{"investigationSummaries":{"description":"Array of investigation summaries","items":{"properties":{"collectableSummaries":{"items":{"properties":{"id":{"type":"string"},"logoPath":{"type":"string"},"origin":{"type":"string"},"title":{"type":"string"}},"required":["id","title","logoPath","origin"],"type":"object"},"type":"array"},"createdByProfile":{"properties":{"gravatarUrl":{"type":"string"},"name":{"type":"string"},"uid":{"type":"string"}},"required":["uid","name","gravatarUrl"],"type":"object"},"hasCustomName":{"type":"boolean"},"isFavorite":{"type":"boolean"},"overviewNote":{"type":"string"},"overviewNoteUpdatedAt":{"type":"string"},"title":{"type":"string"},"viewMode":{"properties":{"mode":{"enum":["compact","full"],"type":"string"},"showComments":{"type":"boolean"},"showTooltips":{"type":"boolean"}},"required":["mode","showComments","showTooltips"],"type":"object"}},"required":["title","createdByProfile","hasCustomName","isFavorite","overviewNote","overviewNoteUpdatedAt","viewMode","collectableSummaries"],"type":"object"},"type":"array"},"owner":{"description":"The Person who owns this investigation index","properties":{"gravatarUrl":{"type":"string"},"name":{"type":"string"},"uid":{"type":"string"}},"required":["uid","name","gravatarUrl"],"type":"object"},"title":{"description":"Title of the index, e.g. 'Favorites' or 'My Investigations'","type":"string"}},"required":["title","owner","investigationSummaries"],"type":"object"},"status":{"properties":{"additionalFields":{"description":"additionalFields is reserved for future use","type":"object","x-kubernetes-preserve-unknown-fields":true},"operatorStates":{"additionalProperties":{"properties":{"descriptiveState":{"description":"descriptiveState is an optional more descriptive state field which has no requirements on format","type":"string"},"details":{"description":"details contains any extra information that is operator-specific","type":"object","x-kubernetes-preserve-unknown-fields":true},"lastEvaluation":{"description":"lastEvaluation is the ResourceVersion last evaluated","type":"string"},"state":{"description":"state describes the state of the lastEvaluation.\nIt is limited to three possible states for machine evaluation.","enum":["success","in_progress","failed"],"type":"string"}},"required":["lastEvaluation","state"],"type":"object"},"description":"operatorStates is a map of operator ID to operator state evaluations.\nAny operator which consumes this kind SHOULD add its state evaluation information to this field.","type":"object"}},"type":"object","x-kubernetes-preserve-unknown-fields":true}}`)
+ versionSchemaInvestigationIndexv0alpha1 app.VersionSchema
+ _ = json.Unmarshal(rawSchemaInvestigationIndexv0alpha1, &versionSchemaInvestigationIndexv0alpha1)
+)
+
+var appManifestData = app.ManifestData{
+ AppName: "investigations",
+ Group: "investigations.grafana.app",
+ Kinds: []app.ManifestKind{
+ {
+ Kind: "Investigation",
+ Scope: "Namespaced",
+ Conversion: false,
+ Versions: []app.ManifestKindVersion{
+ {
+ Name: "v0alpha1",
+ Schema: &versionSchemaInvestigationv0alpha1,
+ },
+ },
+ },
+
+ {
+ Kind: "InvestigationIndex",
+ Scope: "Namespaced",
+ Conversion: false,
+ Versions: []app.ManifestKindVersion{
+ {
+ Name: "v0alpha1",
+ Schema: &versionSchemaInvestigationIndexv0alpha1,
+ },
+ },
+ },
+ },
+}
+
+func jsonToMap(j string) map[string]any {
+ m := make(map[string]any)
+ json.Unmarshal([]byte(j), &j)
+ return m
+}
+
+func LocalManifest() app.Manifest {
+ return app.NewEmbeddedManifest(appManifestData)
+}
+
+func RemoteManifest() app.Manifest {
+ return app.NewAPIServerManifest("investigations")
+}
diff --git a/apps/investigation/pkg/app/app.go b/apps/investigations/pkg/app/investigations_app.go
similarity index 66%
rename from apps/investigation/pkg/app/app.go
rename to apps/investigations/pkg/app/investigations_app.go
index 539b7241540..8ec35c1ed19 100644
--- a/apps/investigation/pkg/app/app.go
+++ b/apps/investigations/pkg/app/investigations_app.go
@@ -9,7 +9,7 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/klog/v2"
- investigationv1alpha1 "github.com/grafana/grafana/apps/investigation/pkg/apis/investigation/v1alpha1"
+ investigationsv0alpha1 "github.com/grafana/grafana/apps/investigations/pkg/apis/investigations/v0alpha1"
)
func New(cfg app.Config) (app.App, error) {
@@ -24,7 +24,10 @@ func New(cfg app.Config) (app.App, error) {
},
ManagedKinds: []simple.AppManagedKind{
{
- Kind: investigationv1alpha1.InvestigationKind(),
+ Kind: investigationsv0alpha1.InvestigationKind(),
+ },
+ {
+ Kind: investigationsv0alpha1.InvestigationIndexKind(),
},
},
}
@@ -44,10 +47,13 @@ func New(cfg app.Config) (app.App, error) {
func GetKinds() map[schema.GroupVersion][]resource.Kind {
gv := schema.GroupVersion{
- Group: investigationv1alpha1.InvestigationKind().Group(),
- Version: investigationv1alpha1.InvestigationKind().Version(),
+ Group: investigationsv0alpha1.InvestigationKind().Group(),
+ Version: investigationsv0alpha1.InvestigationKind().Version(),
}
return map[schema.GroupVersion][]resource.Kind{
- gv: {investigationv1alpha1.InvestigationKind()},
+ gv: {
+ investigationsv0alpha1.InvestigationKind(),
+ investigationsv0alpha1.InvestigationIndexKind(),
+ },
}
}
diff --git a/apps/investigations/plugin/src/generated/investigation/v0alpha1/investigation_object_gen.ts b/apps/investigations/plugin/src/generated/investigation/v0alpha1/investigation_object_gen.ts
new file mode 100644
index 00000000000..b355ebaca05
--- /dev/null
+++ b/apps/investigations/plugin/src/generated/investigation/v0alpha1/investigation_object_gen.ts
@@ -0,0 +1,49 @@
+/*
+ * This file was generated by grafana-app-sdk. DO NOT EDIT.
+ */
+import { Spec } from './types.spec.gen';
+import { Status } from './types.status.gen';
+
+export interface Metadata {
+ name: string;
+ namespace: string;
+ generateName?: string;
+ selfLink?: string;
+ uid?: string;
+ resourceVersion?: string;
+ generation?: number;
+ creationTimestamp?: string;
+ deletionTimestamp?: string;
+ deletionGracePeriodSeconds?: number;
+ labels?: Record;
+ annotations?: Record;
+ ownerReferences?: OwnerReference[];
+ finalizers?: string[];
+ managedFields?: ManagedFieldsEntry[];
+}
+
+export interface OwnerReference {
+ apiVersion: string;
+ kind: string;
+ name: string;
+ uid: string;
+ controller?: boolean;
+ blockOwnerDeletion?: boolean;
+}
+
+export interface ManagedFieldsEntry {
+ manager?: string;
+ operation?: string;
+ apiVersion?: string;
+ time?: string;
+ fieldsType?: string;
+ subresource?: string;
+}
+
+export interface Investigation {
+ kind: string;
+ apiVersion: string;
+ metadata: Metadata;
+ spec: Spec;
+ status: Status;
+}
diff --git a/apps/investigations/plugin/src/generated/investigation/v0alpha1/types.metadata.gen.ts b/apps/investigations/plugin/src/generated/investigation/v0alpha1/types.metadata.gen.ts
new file mode 100644
index 00000000000..4377f3c1d08
--- /dev/null
+++ b/apps/investigations/plugin/src/generated/investigation/v0alpha1/types.metadata.gen.ts
@@ -0,0 +1,30 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+// metadata contains embedded CommonMetadata and can be extended with custom string fields
+// TODO: use CommonMetadata instead of redefining here; currently needs to be defined here
+// without external reference as using the CommonMetadata reference breaks thema codegen.
+export interface Metadata {
+ updateTimestamp: string;
+ createdBy: string;
+ uid: string;
+ creationTimestamp: string;
+ deletionTimestamp?: string;
+ finalizers: string[];
+ resourceVersion: string;
+ generation: number;
+ updatedBy: string;
+ labels: Record;
+}
+
+export const defaultMetadata = (): Metadata => ({
+ updateTimestamp: "",
+ createdBy: "",
+ uid: "",
+ creationTimestamp: "",
+ finalizers: [],
+ resourceVersion: "",
+ generation: 0,
+ updatedBy: "",
+ labels: {},
+});
+
diff --git a/apps/investigations/plugin/src/generated/investigation/v0alpha1/types.spec.gen.ts b/apps/investigations/plugin/src/generated/investigation/v0alpha1/types.spec.gen.ts
new file mode 100644
index 00000000000..c2a128284bc
--- /dev/null
+++ b/apps/investigations/plugin/src/generated/investigation/v0alpha1/types.spec.gen.ts
@@ -0,0 +1,132 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+// Person represents a user profile with basic information
+export interface Person {
+ // Unique identifier for the user
+ uid: string;
+ // Display name of the user
+ name: string;
+ // URL to user's Gravatar image
+ gravatarUrl: string;
+}
+
+export const defaultPerson = (): Person => ({
+ uid: "",
+ name: "",
+ gravatarUrl: "",
+});
+
+// Collectable represents an item collected during investigation
+export interface Collectable {
+ id: string;
+ createdAt: string;
+ title: string;
+ origin: string;
+ type: string;
+ // +listType=atomic
+ queries: Query[];
+ timeRange: TimeRange;
+ datasource: DatasourceRef;
+ url: string;
+ logoPath?: string;
+ note: string;
+ noteUpdatedAt: string;
+}
+
+export const defaultCollectable = (): Collectable => ({
+ id: "",
+ createdAt: "",
+ title: "",
+ origin: "",
+ type: "",
+ queries: [],
+ timeRange: defaultTimeRange(),
+ datasource: defaultDatasourceRef(),
+ url: "",
+ note: "",
+ noteUpdatedAt: "",
+});
+
+// Query represents a data query
+export interface Query {
+ refId: string;
+ queryType: string;
+ editorMode: string;
+ supportingQueryType: string;
+ legendFormat: string;
+ expr: string;
+}
+
+export const defaultQuery = (): Query => ({
+ refId: "",
+ queryType: "",
+ editorMode: "",
+ supportingQueryType: "",
+ legendFormat: "",
+ expr: "",
+});
+
+// TimeRange represents a time range with both absolute and relative values
+export interface TimeRange {
+ from: string;
+ to: string;
+ raw: {
+ from: string;
+ to: string;
+ };
+}
+
+export const defaultTimeRange = (): TimeRange => ({
+ from: "",
+ to: "",
+ raw: {
+ from: "",
+ to: "",
+},
+});
+
+// DatasourceRef is a reference to a datasource
+export interface DatasourceRef {
+ uid: string;
+}
+
+export const defaultDatasourceRef = (): DatasourceRef => ({
+ uid: "",
+});
+
+export interface ViewMode {
+ mode: "compact" | "full";
+ showComments: boolean;
+ showTooltips: boolean;
+}
+
+export const defaultViewMode = (): ViewMode => ({
+ mode: "compact",
+ showComments: false,
+ showTooltips: false,
+});
+
+// spec is the schema of our resource
+export interface Spec {
+ title: string;
+ createdByProfile: Person;
+ hasCustomName: boolean;
+ isFavorite: boolean;
+ overviewNote: string;
+ overviewNoteUpdatedAt: string;
+ // +listType=atomic
+ collectables: Collectable[];
+ viewMode: ViewMode;
+}
+
+export const defaultSpec = (): Spec => ({
+ title: "",
+ createdByProfile: defaultPerson(),
+ hasCustomName: false,
+ isFavorite: false,
+ overviewNote: "",
+ overviewNoteUpdatedAt: "",
+ collectables: [],
+ viewMode: defaultViewMode(),
+});
+
diff --git a/apps/investigations/plugin/src/generated/investigation/v0alpha1/types.status.gen.ts b/apps/investigations/plugin/src/generated/investigation/v0alpha1/types.status.gen.ts
new file mode 100644
index 00000000000..01be8df7961
--- /dev/null
+++ b/apps/investigations/plugin/src/generated/investigation/v0alpha1/types.status.gen.ts
@@ -0,0 +1,30 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+export interface OperatorState {
+ // lastEvaluation is the ResourceVersion last evaluated
+ lastEvaluation: string;
+ // state describes the state of the lastEvaluation.
+ // It is limited to three possible states for machine evaluation.
+ state: "success" | "in_progress" | "failed";
+ // descriptiveState is an optional more descriptive state field which has no requirements on format
+ descriptiveState?: string;
+ // details contains any extra information that is operator-specific
+ details?: Record;
+}
+
+export const defaultOperatorState = (): OperatorState => ({
+ lastEvaluation: "",
+ state: "success",
+});
+
+export interface Status {
+ // operatorStates is a map of operator ID to operator state evaluations.
+ // Any operator which consumes this kind SHOULD add its state evaluation information to this field.
+ operatorStates?: Record;
+ // additionalFields is reserved for future use
+ additionalFields?: Record;
+}
+
+export const defaultStatus = (): Status => ({
+});
+
diff --git a/apps/investigations/plugin/src/generated/investigationindex/v0alpha1/investigationindex_object_gen.ts b/apps/investigations/plugin/src/generated/investigationindex/v0alpha1/investigationindex_object_gen.ts
new file mode 100644
index 00000000000..399b25f3878
--- /dev/null
+++ b/apps/investigations/plugin/src/generated/investigationindex/v0alpha1/investigationindex_object_gen.ts
@@ -0,0 +1,49 @@
+/*
+ * This file was generated by grafana-app-sdk. DO NOT EDIT.
+ */
+import { Spec } from './types.spec.gen';
+import { Status } from './types.status.gen';
+
+export interface Metadata {
+ name: string;
+ namespace: string;
+ generateName?: string;
+ selfLink?: string;
+ uid?: string;
+ resourceVersion?: string;
+ generation?: number;
+ creationTimestamp?: string;
+ deletionTimestamp?: string;
+ deletionGracePeriodSeconds?: number;
+ labels?: Record;
+ annotations?: Record;
+ ownerReferences?: OwnerReference[];
+ finalizers?: string[];
+ managedFields?: ManagedFieldsEntry[];
+}
+
+export interface OwnerReference {
+ apiVersion: string;
+ kind: string;
+ name: string;
+ uid: string;
+ controller?: boolean;
+ blockOwnerDeletion?: boolean;
+}
+
+export interface ManagedFieldsEntry {
+ manager?: string;
+ operation?: string;
+ apiVersion?: string;
+ time?: string;
+ fieldsType?: string;
+ subresource?: string;
+}
+
+export interface InvestigationIndex {
+ kind: string;
+ apiVersion: string;
+ metadata: Metadata;
+ spec: Spec;
+ status: Status;
+}
diff --git a/apps/investigations/plugin/src/generated/investigationindex/v0alpha1/types.metadata.gen.ts b/apps/investigations/plugin/src/generated/investigationindex/v0alpha1/types.metadata.gen.ts
new file mode 100644
index 00000000000..4377f3c1d08
--- /dev/null
+++ b/apps/investigations/plugin/src/generated/investigationindex/v0alpha1/types.metadata.gen.ts
@@ -0,0 +1,30 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+// metadata contains embedded CommonMetadata and can be extended with custom string fields
+// TODO: use CommonMetadata instead of redefining here; currently needs to be defined here
+// without external reference as using the CommonMetadata reference breaks thema codegen.
+export interface Metadata {
+ updateTimestamp: string;
+ createdBy: string;
+ uid: string;
+ creationTimestamp: string;
+ deletionTimestamp?: string;
+ finalizers: string[];
+ resourceVersion: string;
+ generation: number;
+ updatedBy: string;
+ labels: Record;
+}
+
+export const defaultMetadata = (): Metadata => ({
+ updateTimestamp: "",
+ createdBy: "",
+ uid: "",
+ creationTimestamp: "",
+ finalizers: [],
+ resourceVersion: "",
+ generation: 0,
+ updatedBy: "",
+ labels: {},
+});
+
diff --git a/apps/investigations/plugin/src/generated/investigationindex/v0alpha1/types.spec.gen.ts b/apps/investigations/plugin/src/generated/investigationindex/v0alpha1/types.spec.gen.ts
new file mode 100644
index 00000000000..f0d2f25d96b
--- /dev/null
+++ b/apps/investigations/plugin/src/generated/investigationindex/v0alpha1/types.spec.gen.ts
@@ -0,0 +1,84 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+// Person represents a user profile with basic information
+export interface Person {
+ // Unique identifier for the user
+ uid: string;
+ // Display name of the user
+ name: string;
+ // URL to user's Gravatar image
+ gravatarUrl: string;
+}
+
+export const defaultPerson = (): Person => ({
+ uid: "",
+ name: "",
+ gravatarUrl: "",
+});
+
+// Type definition for investigation summaries
+export interface InvestigationSummary {
+ title: string;
+ createdByProfile: Person;
+ hasCustomName: boolean;
+ isFavorite: boolean;
+ overviewNote: string;
+ overviewNoteUpdatedAt: string;
+ viewMode: ViewMode;
+ // +listType=atomic
+ collectableSummaries: CollectableSummary[];
+}
+
+export const defaultInvestigationSummary = (): InvestigationSummary => ({
+ title: "",
+ createdByProfile: defaultPerson(),
+ hasCustomName: false,
+ isFavorite: false,
+ overviewNote: "",
+ overviewNoteUpdatedAt: "",
+ viewMode: defaultViewMode(),
+ collectableSummaries: [],
+});
+
+export interface ViewMode {
+ mode: "compact" | "full";
+ showComments: boolean;
+ showTooltips: boolean;
+}
+
+export const defaultViewMode = (): ViewMode => ({
+ mode: "compact",
+ showComments: false,
+ showTooltips: false,
+});
+
+export interface CollectableSummary {
+ id: string;
+ title: string;
+ logoPath: string;
+ origin: string;
+}
+
+export const defaultCollectableSummary = (): CollectableSummary => ({
+ id: "",
+ title: "",
+ logoPath: "",
+ origin: "",
+});
+
+export interface Spec {
+ // Title of the index, e.g. 'Favorites' or 'My Investigations'
+ title: string;
+ // The Person who owns this investigation index
+ owner: Person;
+ // Array of investigation summaries
+ // +listType=atomic
+ investigationSummaries: InvestigationSummary[];
+}
+
+export const defaultSpec = (): Spec => ({
+ title: "",
+ owner: defaultPerson(),
+ investigationSummaries: [],
+});
+
diff --git a/apps/investigations/plugin/src/generated/investigationindex/v0alpha1/types.status.gen.ts b/apps/investigations/plugin/src/generated/investigationindex/v0alpha1/types.status.gen.ts
new file mode 100644
index 00000000000..01be8df7961
--- /dev/null
+++ b/apps/investigations/plugin/src/generated/investigationindex/v0alpha1/types.status.gen.ts
@@ -0,0 +1,30 @@
+// Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+export interface OperatorState {
+ // lastEvaluation is the ResourceVersion last evaluated
+ lastEvaluation: string;
+ // state describes the state of the lastEvaluation.
+ // It is limited to three possible states for machine evaluation.
+ state: "success" | "in_progress" | "failed";
+ // descriptiveState is an optional more descriptive state field which has no requirements on format
+ descriptiveState?: string;
+ // details contains any extra information that is operator-specific
+ details?: Record;
+}
+
+export const defaultOperatorState = (): OperatorState => ({
+ lastEvaluation: "",
+ state: "success",
+});
+
+export interface Status {
+ // operatorStates is a map of operator ID to operator state evaluations.
+ // Any operator which consumes this kind SHOULD add its state evaluation information to this field.
+ operatorStates?: Record;
+ // additionalFields is reserved for future use
+ additionalFields?: Record;
+}
+
+export const defaultStatus = (): Status => ({
+});
+
diff --git a/apps/playlist/Makefile b/apps/playlist/Makefile
index 926f5a2840f..7a5f1c99365 100644
--- a/apps/playlist/Makefile
+++ b/apps/playlist/Makefile
@@ -1,8 +1,3 @@
.PHONY: generate
generate:
- @grafana-app-sdk generate -g ./pkg/apis --grouping=group --postprocess
- # HACK: Clean up generated CRD files.
- # TODO: The SDK currently omits generating the manifest Go file with `--defencoding=none`,
- # which we would normally use here to skip generating the CRD files.
- # This needs to be addressed.
- @rm -rf definitions
+ @grafana-app-sdk generate -g ./pkg/apis --grouping=group --postprocess --defencoding=none
diff --git a/apps/playlist/go.mod b/apps/playlist/go.mod
index f7304ea395c..6214b9ae328 100644
--- a/apps/playlist/go.mod
+++ b/apps/playlist/go.mod
@@ -1,11 +1,11 @@
module github.com/grafana/grafana/apps/playlist
-go 1.23.4
+go 1.23.7
require (
- github.com/grafana/grafana-app-sdk v0.30.0
- k8s.io/apimachinery v0.32.0
- k8s.io/client-go v0.32.0
+ github.com/grafana/grafana-app-sdk v0.31.0
+ k8s.io/apimachinery v0.32.1
+ k8s.io/client-go v0.32.1
k8s.io/klog/v2 v2.130.1
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f
)
@@ -19,7 +19,7 @@ require (
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
- github.com/getkin/kin-openapi v0.128.0 // indirect
+ github.com/getkin/kin-openapi v0.129.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
@@ -28,15 +28,14 @@ require (
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
- github.com/google/go-cmp v0.6.0 // indirect
+ github.com/google/go-cmp v0.7.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
github.com/google/uuid v1.6.0 // indirect
- github.com/grafana/grafana-app-sdk/logging v0.29.0 // indirect
- github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 // indirect
+ github.com/grafana/grafana-app-sdk/logging v0.30.0 // indirect
+ github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
- github.com/invopop/yaml v0.3.1 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.11 // indirect
@@ -45,39 +44,43 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
+ github.com/oasdiff/yaml v0.0.0-20241210131133-6b86fb107d80 // indirect
+ github.com/oasdiff/yaml3 v0.0.0-20241210130736-a94c01f36349 // indirect
+ github.com/onsi/ginkgo/v2 v2.22.0 // indirect
+ github.com/onsi/gomega v1.36.1 // indirect
github.com/perimeterx/marshmallow v1.1.5 // indirect
- github.com/prometheus/client_golang v1.20.5 // indirect
+ github.com/prometheus/client_golang v1.21.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
- github.com/prometheus/common v0.61.0 // indirect
+ github.com/prometheus/common v0.62.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/puzpuzpuz/xsync/v2 v2.5.1 // indirect
- github.com/spf13/pflag v1.0.5 // indirect
+ github.com/spf13/pflag v1.0.6 // indirect
github.com/x448/float16 v0.8.4 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
- go.opentelemetry.io/otel v1.33.0 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0 // indirect
- go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0 // indirect
- go.opentelemetry.io/otel/metric v1.33.0 // indirect
- go.opentelemetry.io/otel/sdk v1.33.0 // indirect
- go.opentelemetry.io/otel/trace v1.33.0 // indirect
+ go.opentelemetry.io/otel v1.34.0 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 // indirect
+ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 // indirect
+ go.opentelemetry.io/otel/metric v1.34.0 // indirect
+ go.opentelemetry.io/otel/sdk v1.34.0 // indirect
+ go.opentelemetry.io/otel/trace v1.34.0 // indirect
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
- golang.org/x/net v0.34.0 // indirect
- golang.org/x/oauth2 v0.25.0 // indirect
- golang.org/x/sync v0.10.0 // indirect
- golang.org/x/sys v0.29.0 // indirect
- golang.org/x/term v0.28.0 // indirect
- golang.org/x/text v0.21.0 // indirect
+ golang.org/x/net v0.36.0 // indirect
+ golang.org/x/oauth2 v0.27.0 // indirect
+ golang.org/x/sync v0.11.0 // indirect
+ golang.org/x/sys v0.30.0 // indirect
+ golang.org/x/term v0.29.0 // indirect
+ golang.org/x/text v0.22.0 // indirect
golang.org/x/time v0.9.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
- google.golang.org/genproto/googleapis/api v0.0.0-20250102185135-69823020774d // indirect
- google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d // indirect
- google.golang.org/grpc v1.69.4 // indirect
- google.golang.org/protobuf v1.36.1 // indirect
+ google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489 // indirect
+ google.golang.org/genproto/googleapis/rpc v0.0.0-20250207221924-e9438ea467c6 // indirect
+ google.golang.org/grpc v1.70.0 // indirect
+ google.golang.org/protobuf v1.36.5 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
- k8s.io/api v0.32.0 // indirect
- k8s.io/apiextensions-apiserver v0.32.0 // indirect
+ k8s.io/api v0.32.1 // indirect
+ k8s.io/apiextensions-apiserver v0.32.1 // indirect
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.5.0 // indirect
diff --git a/apps/playlist/go.sum b/apps/playlist/go.sum
index 858c73dd4b4..88d0fa45e79 100644
--- a/apps/playlist/go.sum
+++ b/apps/playlist/go.sum
@@ -16,8 +16,8 @@ github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCv
github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
-github.com/getkin/kin-openapi v0.128.0 h1:jqq3D9vC9pPq1dGcOCv7yOp1DaEe7c/T1vzcLbITSp4=
-github.com/getkin/kin-openapi v0.128.0/go.mod h1:OZrfXzUfGrNbsKj+xmFBx6E5c6yH3At/tAKSc2UszXM=
+github.com/getkin/kin-openapi v0.129.0 h1:QGYTNcmyP5X0AtFQ2Dkou9DGBJsUETeLH9rFrJXZh30=
+github.com/getkin/kin-openapi v0.129.0/go.mod h1:gmWI+b/J45xqpyK5wJmRRZse5wefA5H0RDMK46kLUtI=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
@@ -40,8 +40,8 @@ github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
-github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
-github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
+github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
@@ -49,19 +49,17 @@ github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/Z
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/grafana/grafana-app-sdk v0.30.0 h1:Hqn2pETu2mQ4RpWkZYEQfu01P7xd1Z1Gj+HX/8aB0tw=
-github.com/grafana/grafana-app-sdk v0.30.0/go.mod h1:jhfqNIovb+Mes2vdMf9iMCWQkp1GTNtyNuExONtiNuk=
-github.com/grafana/grafana-app-sdk/logging v0.29.0 h1:mgbXaAf33aFwqwGVeaX30l8rkeAJH0iACgX5Rn6YkN4=
-github.com/grafana/grafana-app-sdk/logging v0.29.0/go.mod h1:xy6ZyVXl50Z3DBDLybvBPphbykPhuVNed/VNmen9DQM=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 h1:VNqngBF40hVlDloBruUehVYC3ArSgIyScOAyMRqBxRg=
-github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1/go.mod h1:RBRO7fro65R6tjKzYgLAFo0t1QEXY1Dp+i/bvpRiqiQ=
+github.com/grafana/grafana-app-sdk v0.31.0 h1:/mFCcx+YqG8cWAi9hePDJQxIdtXDClDIDRgZwHkksFk=
+github.com/grafana/grafana-app-sdk v0.31.0/go.mod h1:Xw00NL7qpRLo5r3Gn48Bl1Xn2n4eUDI5pYf/wMufKWs=
+github.com/grafana/grafana-app-sdk/logging v0.30.0 h1:K/P/bm7Cp7Di4tqIJ3EQz2+842JozQGRaz62r95ApME=
+github.com/grafana/grafana-app-sdk/logging v0.30.0/go.mod h1:xy6ZyVXl50Z3DBDLybvBPphbykPhuVNed/VNmen9DQM=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 h1:e9Rjr40Z98/clHv5Yg79Is0NtosR5LXRvdr7o/6NwbA=
+github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1/go.mod h1:tIxuGz/9mpox++sgp9fJjHO0+q1X9/UOWd798aAm22M=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
-github.com/invopop/yaml v0.3.1 h1:f0+ZpmhfBSS4MhG+4HYseMdJhoeeopbSKbq5Rpeelso=
-github.com/invopop/yaml v0.3.1/go.mod h1:PMOp3nn4/12yEZUFfmOuNHJsZToEEOwoWsT+D81KkeA=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
@@ -87,10 +85,14 @@ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
-github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
-github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
-github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
-github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
+github.com/oasdiff/yaml v0.0.0-20241210131133-6b86fb107d80 h1:nZspmSkneBbtxU9TopEAE0CY+SBJLxO8LPUlw2vG4pU=
+github.com/oasdiff/yaml v0.0.0-20241210131133-6b86fb107d80/go.mod h1:7tFDb+Y51LcDpn26GccuUgQXUk6t0CXZsivKjyimYX8=
+github.com/oasdiff/yaml3 v0.0.0-20241210130736-a94c01f36349 h1:t05Ww3DxZutOqbMN+7OIuqDwXbhl32HiZGpLy26BAPc=
+github.com/oasdiff/yaml3 v0.0.0-20241210130736-a94c01f36349/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o=
+github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg=
+github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
+github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw=
+github.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s=
github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -98,20 +100,20 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
-github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
+github.com/prometheus/client_golang v1.21.0 h1:DIsaGmiaBkSangBgMtWdNfxbMNdku5IK6iNhrEqWvdA=
+github.com/prometheus/client_golang v1.21.0/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
-github.com/prometheus/common v0.61.0 h1:3gv/GThfX0cV2lpO7gkTUwZru38mxevy90Bj8YFSRQQ=
-github.com/prometheus/common v0.61.0/go.mod h1:zr29OCN/2BsJRaFwG8QOBr41D6kkchKbpeNH7pAjb/s=
+github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
+github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/puzpuzpuz/xsync/v2 v2.5.1 h1:mVGYAvzDSu52+zaGyNjC+24Xw2bQi3kTr4QJ6N9pIIU=
github.com/puzpuzpuz/xsync/v2 v2.5.1/go.mod h1:gD2H2krq/w52MfPLE+Uy64TzJDVY7lP2znR9qmR35kU=
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
-github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
-github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
+github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
@@ -124,22 +126,22 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
-go.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw=
-go.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0 h1:Vh5HayB/0HHfOQA7Ctx69E/Y/DcQSMPpKANYVMQ7fBA=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.33.0/go.mod h1:cpgtDBaqD/6ok/UG0jT15/uKjAY8mRA53diogHBg3UI=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0 h1:5pojmb1U1AogINhN3SurB+zm/nIcusopeBNp42f45QM=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.33.0/go.mod h1:57gTHJSE5S1tqg+EKsLPlTWhpHMsWlVmer+LA926XiA=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0 h1:wpMfgF8E1rkrT1Z6meFh1NDtownE9Ii3n3X2GJYjsaU=
-go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.33.0/go.mod h1:wAy0T/dUbs468uOlkT31xjvqQgEVXv58BRFWEgn5v/0=
-go.opentelemetry.io/otel/metric v1.33.0 h1:r+JOocAyeRVXD8lZpjdQjzMadVZp2M4WmQ+5WtEnklQ=
-go.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M=
-go.opentelemetry.io/otel/sdk v1.33.0 h1:iax7M131HuAm9QkZotNHEfstof92xM+N8sr3uHXc2IM=
-go.opentelemetry.io/otel/sdk v1.33.0/go.mod h1:A1Q5oi7/9XaMlIWzPSxLRWOI8nG3FnzHJNbiENQuihM=
-go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc=
-go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8=
-go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s=
-go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck=
+go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
+go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 h1:BEj3SPM81McUZHYjRS5pEgNgnmzGJ5tRpU5krWnV8Bs=
+go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0/go.mod h1:9cKLGBDzI/F3NoHLQGm4ZrYdIHsvGt6ej6hUowxY0J4=
+go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
+go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
+go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
+go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
+go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU=
+go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ=
+go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
+go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
@@ -153,26 +155,26 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
-golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
-golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70=
-golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
+golang.org/x/net v0.36.0 h1:vWF2fRbw4qslQsQzgFqZff+BItCvGFQqKzKIzx1rmoA=
+golang.org/x/net v0.36.0/go.mod h1:bFmbeoIPfrw4sMHNhb4J9f6+tPziuGjq7Jk/38fxi1I=
+golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=
+golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
-golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
+golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
+golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
-golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
-golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
+golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
+golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
+golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
-golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
+golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
+golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -187,14 +189,14 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw=
gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY=
-google.golang.org/genproto/googleapis/api v0.0.0-20250102185135-69823020774d h1:H8tOf8XM88HvKqLTxe755haY6r1fqqzLbEnfrmLXlSA=
-google.golang.org/genproto/googleapis/api v0.0.0-20250102185135-69823020774d/go.mod h1:2v7Z7gP2ZUOGsaFyxATQSRoBnKygqVq2Cwnvom7QiqY=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d h1:xJJRGY7TJcvIlpSrN3K6LAWgNFUILlO+OMAqtg9aqnw=
-google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d/go.mod h1:3ENsm/5D1mzDyhpzeRi1NR784I0BcofWBoSc5QqqMK4=
-google.golang.org/grpc v1.69.4 h1:MF5TftSMkd8GLw/m0KM6V8CMOCY6NZ1NQDPGFgbTt4A=
-google.golang.org/grpc v1.69.4/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4=
-google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk=
-google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
+google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489 h1:fCuMM4fowGzigT89NCIsW57Pk9k2D12MMi2ODn+Nk+o=
+google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489/go.mod h1:iYONQfRdizDB8JJBybql13nArx91jcUk7zCXEsOofM4=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250207221924-e9438ea467c6 h1:2duwAxN2+k0xLNpjnHTXoMUgnv6VPSp5fiqTuwSxjmI=
+google.golang.org/genproto/googleapis/rpc v0.0.0-20250207221924-e9438ea467c6/go.mod h1:8BS3B93F/U1juMFq9+EDk+qOT5CO1R9IzXxG3PTqiRk=
+google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
+google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
+google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
+google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
@@ -204,14 +206,14 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-k8s.io/api v0.32.0 h1:OL9JpbvAU5ny9ga2fb24X8H6xQlVp+aJMFlgtQjR9CE=
-k8s.io/api v0.32.0/go.mod h1:4LEwHZEf6Q/cG96F3dqR965sYOfmPM7rq81BLgsE0p0=
-k8s.io/apiextensions-apiserver v0.32.0 h1:S0Xlqt51qzzqjKPxfgX1xh4HBZE+p8KKBq+k2SWNOE0=
-k8s.io/apiextensions-apiserver v0.32.0/go.mod h1:86hblMvN5yxMvZrZFX2OhIHAuFIMJIZ19bTvzkP+Fmw=
-k8s.io/apimachinery v0.32.0 h1:cFSE7N3rmEEtv4ei5X6DaJPHHX0C+upp+v5lVPiEwpg=
-k8s.io/apimachinery v0.32.0/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
-k8s.io/client-go v0.32.0 h1:DimtMcnN/JIKZcrSrstiwvvZvLjG0aSxy8PxN8IChp8=
-k8s.io/client-go v0.32.0/go.mod h1:boDWvdM1Drk4NJj/VddSLnx59X3OPgwrOo0vGbtq9+8=
+k8s.io/api v0.32.1 h1:f562zw9cy+GvXzXf0CKlVQ7yHJVYzLfL6JAS4kOAaOc=
+k8s.io/api v0.32.1/go.mod h1:/Yi/BqkuueW1BgpoePYBRdDYfjPF5sgTr5+YqDZra5k=
+k8s.io/apiextensions-apiserver v0.32.1 h1:hjkALhRUeCariC8DiVmb5jj0VjIc1N0DREP32+6UXZw=
+k8s.io/apiextensions-apiserver v0.32.1/go.mod h1:sxWIGuGiYov7Io1fAS2X06NjMIk5CbRHc2StSmbaQto=
+k8s.io/apimachinery v0.32.1 h1:683ENpaCBjma4CYqsmZyhEzrGz6cjn1MY/X2jB2hkZs=
+k8s.io/apimachinery v0.32.1/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
+k8s.io/client-go v0.32.1 h1:otM0AxdhdBIaQh7l1Q0jQpmo7WOFIk5FFa4bg6YMdUU=
+k8s.io/client-go v0.32.1/go.mod h1:aTTKZY7MdxUaJ/KiUs8D+GssR9zJZi77ZqtzcGXIiDg=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y=
diff --git a/conf/defaults.ini b/conf/defaults.ini
index 91e7af25442..a216bb0792a 100644
--- a/conf/defaults.ini
+++ b/conf/defaults.ini
@@ -130,6 +130,13 @@ password =
# Example: mysql://user:secret@host:port/database
url =
+# Set to true or false to enable or disable high availability mode.
+# When it's set to false some functions will be simplified and only run in-process
+# instead of relying on the database.
+#
+# Only set it to false if you run only a single instance of Grafana.
+high_availability = true
+
# Max idle conn setting default is 2
max_idle_conn = 2
@@ -354,6 +361,9 @@ disable_brute_force_login_protection = false
# max number of failed login attempts before user gets locked
brute_force_login_protection_max_attempts = 5
+# disable protection against brute force login attempts by IP address
+disable_ip_address_login_protection = true
+
# set to true if you host Grafana behind HTTPS. default is false.
cookie_secure = false
@@ -452,6 +462,9 @@ min_refresh_interval = 5s
# Path to the default home dashboard. If this value is empty, then Grafana uses StaticRootPath + "dashboards/home.json"
default_home_dashboard_path =
+# Dashboards UIDs to report performance metrics for. * can be used to report metrics for all dashboards
+dashboard_performance_metrics =
+
################################### Data sources #########################
[datasources]
# Upper limit of data sources that Grafana will return. This limit is a temporary configuration and it will be deprecated when pagination will be introduced on the list data sources API.
@@ -521,9 +534,11 @@ external_manage_link_url =
external_manage_link_name =
external_manage_info =
+# Deprecated: Assign your viewers to editors.
# Viewers can edit/inspect dashboard settings in the browser. But not save the dashboard.
viewers_can_edit = false
+# Deprecated: Assign your editors to admins.
# Editors can administrate dashboard, folders and teams they create
editors_can_admin = false
@@ -922,6 +937,7 @@ auto_sign_up = false
url_login = false
allow_assign_grafana_admin = false
skip_org_role_sync = false
+tls_skip_verify_insecure = false
#################################### Auth LDAP ###########################
[auth.ldap]
@@ -1013,6 +1029,10 @@ user_identity_fallback_credentials_enabled = true
# By default is the same as token URL configured for AAD authentication settings
user_identity_token_url =
+# Override client authentication method for Azure Active Directory
+# By default is the same as client authentication method configured for AAD authentication settings
+user_identity_client_authentication =
+
# Override ADD application ID which would be used to exchange users token to an access token for the datasource
# By default is the same as used in AAD authentication or can be set to another application (for OBO flow)
user_identity_client_id =
@@ -1021,6 +1041,14 @@ user_identity_client_id =
# By default is the same as used in AAD authentication or can be set to another application (for OBO flow)
user_identity_client_secret =
+# Override the AAD managed identity client ID
+# By default is the same as used in AAD authentication or can be set to another managed identity (for OBO flow)
+user_identity_managed_identity_client_id =
+
+# Override the AAD federated credential audience
+# By default is the same as used in AAD authentication or can be set to another audience (for OBO flow)
+user_identity_federated_credential_audience =
+
# Allows the usage of a custom token request assertion when Grafana is behind an authentication proxy
# In most cases this will not need to be used. To enable this set the value to "username"
# The default is empty and any other value will not enable this functionality
@@ -1495,6 +1523,13 @@ basic_auth_password =
# Request timeout for recording rule writes.
timeout = 10s
+# Default data source UID to write to if not specified in the rule definition.
+# Only has effect if the grafanaManagedRecordRulesDatasources feature toggle is enabled.
+default_datasource_uid =
+
+# Suffix to apply to the data source URL for remote write requests.
+remote_write_path_suffix = /push
+
# Optional custom headers to include in recording rule write requests.
[recording_rules.custom_headers]
# exampleHeader = exampleValue
@@ -1559,6 +1594,9 @@ enabled = true
# set the default offset for the time picker
defaultTimeOffset = 1h
+# hides the download logs button in Explore
+hide_logs_download = false
+
#################################### Help #############################
[help]
# Enable the Help section
@@ -1723,6 +1761,7 @@ sas_token_expiration_days =
# URL to a remote HTTP image renderer service, e.g. http://localhost:8081/render, will enable Grafana to render panels and dashboards to PNG-images using HTTP requests to an external service.
server_url =
# If the remote HTTP image renderer service runs on a different server than the Grafana server you may have to configure this to a URL where Grafana is reachable, e.g. http://grafana.domain/.
+# The `callback_url` can also be configured to support usage of the image renderer running as a plugin with support for SSL / HTTPS. For example https://localhost:3000/.
callback_url =
# An auth token that will be sent to and verified by the renderer. The renderer will deny any request without an auth token matching the one configured on the renderer side.
renderer_token = -
@@ -1785,6 +1824,10 @@ preinstall_disabled = false
# tuning. 0 disables Live, -1 means unlimited connections.
max_connections = 100
+# message_size_limit is the maximum size in bytes of Websocket messages from clients. Defaults to 64KB.
+# The limit can be disabled by setting it to -1.
+message_size_limit = 65536
+
# allowed_origins is a comma-separated list of origins that can establish connection with Grafana Live.
# If not set then origin will be matched over root_url. Supports wildcard symbol "*".
allowed_origins =
@@ -1839,6 +1882,9 @@ rendering_dumpio =
# This can be useful to enable (true) when optimizing the rendering mode settings to improve the plugin performance or when troubleshooting.
rendering_timing_metrics =
+# This is a configuration for OTLP exporter with HTTP protocol, set this URL to enable tracing (ex: http://localhost:4318/v1/traces). Default to empty (tracing disabled).
+rendering_tracing_url =
+
# Additional arguments to pass to the headless browser instance. Default is --no-sandbox. The list of Chromium flags can be found
# here (https://peter.sh/experiments/chromium-command-line-switches/). Multiple arguments is separated with comma-character.
rendering_args =
@@ -1892,6 +1938,15 @@ enable =
# feature1 = true
# feature2 = false
+[feature_toggles.openfeature]
+# This is EXPERIMENTAL. Please, do not use this section
+provider = static
+
+[feature_toggles.openfeature.context]
+# This is EXPERIMENTAL. Please, do not use this section
+# instance = "grafana"
+# version = 11.0.0
+
[date_formats]
# For information on what formatting patterns that are supported https://momentjs.com/docs/#/displaying/
diff --git a/conf/sample.ini b/conf/sample.ini
index d1a06d9c331..21ef0ad88c6 100644
--- a/conf/sample.ini
+++ b/conf/sample.ini
@@ -129,6 +129,13 @@
# Example: mysql://user:secret@host:port/database
;url =
+# Set to true or false to enable or disable high availability mode.
+# When it's set to false some functions will be simplified and only run in-process
+# instead of relying on the database.
+#
+# Only set it to false if you run only a single instance of Grafana.
+;high_availability = true
+
# Max idle conn setting default is 2
;max_idle_conn = 2
@@ -353,6 +360,9 @@
# max number of failed login attempts before user gets locked
;brute_force_login_protection_max_attempts = 5
+# disable protection against brute force login attempts by IP address
+; disable_ip_address_login_protection = true
+
# set to true if you host Grafana behind HTTPS. default is false.
;cookie_secure = false
@@ -525,9 +535,12 @@
;external_manage_link_name =
;external_manage_info =
+
+# Deprecated: Assign your viewers to editors.
# Viewers can edit/inspect dashboard settings in the browser. But not save the dashboard.
;viewers_can_edit = false
+# Deprecated: Assign your editors to admins.
# Editors can administrate dashboard, folders and teams they create
;editors_can_admin = false
@@ -894,6 +907,7 @@
;allow_assign_grafana_admin = false
;skip_org_role_sync = false
;signout_redirect_url =
+;tls_skip_verify_insecure = false
#################################### Auth LDAP ##########################
[auth.ldap]
@@ -998,6 +1012,10 @@
# By default is the same as token URL configured for AAD authentication settings
;user_identity_token_url =
+# Override client authentication method for Azure Active Directory
+# By default is the same as client authentication method configured for AAD authentication settings
+;user_identity_client_authentication =
+
# Override ADD application ID which would be used to exchange users token to an access token for the datasource
# By default is the same as used in AAD authentication or can be set to another application (for OBO flow)
;user_identity_client_id =
@@ -1006,6 +1024,14 @@
# By default is the same as used in AAD authentication or can be set to another application (for OBO flow)
;user_identity_client_secret =
+# Override the AAD managed identity client ID
+# By default is the same as used in AAD authentication or can be set to another managed identity (for OBO flow)
+;user_identity_managed_identity_client_id =
+
+# Override the AAD federated credential audience
+# By default is the same as used in AAD authentication or can be set to another audience (for OBO flow)
+;user_identity_federated_credential_audience =
+
# Allows the usage of a custom token request assertion when Grafana is behind an authentication proxy
# In most cases this will not need to be used. To enable this set the value to "username"
# The default is empty and any other value will not enable this functionality
@@ -1391,12 +1417,6 @@
# For example: `disabled_labels=grafana_folder`
disabled_labels =
-
-[unified_alerting.reserved_labels]
-# Comma-separated list of reserved labels added by the Grafana Alerting engine that should be disabled.
-# For example: `disabled_labels=grafana_folder`
-;disabled_labels =
-
[unified_alerting.state_history]
# Enable the state history functionality in Unified Alerting. The previous states of alert rules will be visible in panels and in the UI.
; enabled = true
@@ -1485,6 +1505,13 @@ basic_auth_password =
# Request timeout for recording rule writes.
timeout = 30s
+# Default data source UID to write to if not specified in the rule definition.
+# Only has effect if the grafanaManagedRecordRulesDatasources feature toggle is enabled.
+default_datasource_uid =
+
+# Suffix to apply to the data source URL for remote write requests.
+remote_write_path_suffix = /push
+
# Optional custom headers to include in recording rule write requests.
[recording_rules.custom_headers]
# exampleHeader = exampleValue
@@ -1789,6 +1816,9 @@ timeout = 30s
# This can be useful to enable (true) when optimizing the rendering mode settings to improve the plugin performance or when troubleshooting.
;rendering_timing_metrics =
+# This is a configuration for OTLP exporter with HTTP protocol, set this URL to enable tracing (ex: http://localhost:4318/v1/traces). Default to empty (tracing disabled).
+;rendering_tracing_url =
+
# Additional arguments to pass to the headless browser instance. Default is --no-sandbox. The list of Chromium flags can be found
# here (https://peter.sh/experiments/chromium-command-line-switches/). Multiple arguments is separated with comma-character.
;rendering_args =
diff --git a/contribute/developer-guide.md b/contribute/developer-guide.md
index 9a4d98d8003..da3669615ab 100644
--- a/contribute/developer-guide.md
+++ b/contribute/developer-guide.md
@@ -318,7 +318,7 @@ Previously, Grafana used Yarn PnP to install frontend dependencies, which requir
### Too many open files when running `make run`
-Depending on your environment, you may have to increase the maximum number of open files allowed. For the rest of this section, we will assume you are on a UNIX-like OS (for example, Linux or macOS), where you can control the maximum number of open files through the [ulimit](https://ss64.com/bash/ulimit.html) shell command.
+Depending on your environment, you may need to increase the maximum number of open files allowed. For the rest of this section, we will assume you are on a UNIX-like OS (for example, Linux or macOS), where you can control the maximum number of open files through the [ulimit](https://ss64.com/bash/ulimit.html) shell command.
To see how many open files are allowed, run:
@@ -361,6 +361,58 @@ ulimit: open files: cannot modify limit: Operation not permitted
If that happens to you, chances are you've already set a lower limit and your shell won't let you set a higher one. Try looking in your shell initialization files (`~/.bashrc`, typically), to see if there's already an `ulimit` command that you can tweak.
+### System limit for number of file watchers reached while running `yarn start`
+
+Depending on your environment, you may need to increase the number of file watchers allowed by `inotify` package to monitor filesystem changes. You may encounter an error `Error: ENOSPC: System limit for number of file watchers reached` otherwise.
+
+Edit the system config file to insert the new value for file watchers limit:
+
+On Linux:
+
+```bash
+echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
+```
+
+On macOS:
+
+```bash
+sudo sysctl -w kern.maxfiles=524288
+```
+
+Check if the new value was applied. It must output `524288`:
+
+On Linux:
+
+```bash
+cat /proc/sys/fs/inotify/max_user_watches
+```
+
+On macOS:
+
+```bash
+sysctl kern.maxfiles
+```
+
+### JavaScript heap out of memory while running `yarn start`
+
+Running `yarn start` requires a substantial amount of memory space. You may check the currently allocated heap space to `node` by running the command:
+
+```bash
+node -e 'console.log(v8.getHeapStatistics().heap_size_limit/(1024*1024))'
+```
+
+Increase the default heap memory to something greater than the currently allocated memory. Make sure the value is a multiple of `1024`.
+
+```bash
+export NODE_OPTIONS="--max-old-space-size=8192"
+```
+
+Or on Windows:
+
+```
+Set NODE_OPTIONS="--max-old-space-size=8192"
+```
+
### Getting `AggregateError` when building frontend tests
If you encounter an `AggregateError` when building new tests, this is probably due to a call to our client [backend service](https://github.com/grafana/grafana/blob/main/public/app/core/services/backend_srv.ts) not being mocked. Our backend service anticipates multiple responses being returned and was built to return errors as an array. A test encountering errors from the service will group those errors as an `AggregateError` without breaking down the individual errors within. `backend_srv.processRequestError` is called once per error and is a great place to return information on what the individual errors might contain.
diff --git a/contribute/style-guides/themes.md b/contribute/style-guides/themes.md
index 61c01764429..e4608ec55f1 100644
--- a/contribute/style-guides/themes.md
+++ b/contribute/style-guides/themes.md
@@ -96,11 +96,12 @@ Example use cases:
### Background colors
-| Property | When to use |
-| --------------------------------- | ------------------------------------------------------------------------------------------------ |
-| theme.colors.background.canvas | Dashboard background. A background surface for panels and panes that use primary background |
-| theme.colors.background.primary | The default content background for content panes and panels |
-| theme.colors.background.secondary | For cards and other surfaces that need to stand out when placed on top of the primary background |
+| Property | When to use |
+| --------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| theme.colors.background.canvas | Dashboard background. A background surface for panels and panes that use primary background |
+| theme.colors.background.primary | The default content background for content panes and panels |
+| theme.colors.background.secondary | For cards and other surfaces that need to stand out when placed on top of the primary background |
+| theme.colors.background.elevated | For popovers and menu backgrounds. This is the same color as primary in most light themes but in dark themes it has a brighter shade to help give it contrast against the primary background |
### Borders
diff --git a/devenv/bulk-dashboards/bulkdash.jsonnet b/devenv/bulk-dashboards/bulkdash.jsonnet
index 1a77d8abd70..05e396df2d6 100644
--- a/devenv/bulk-dashboards/bulkdash.jsonnet
+++ b/devenv/bulk-dashboards/bulkdash.jsonnet
@@ -1118,18 +1118,6 @@
"1d"
],
"status": "Stable",
- "time_options": [
- "5m",
- "15m",
- "1h",
- "2h",
- " 6h",
- "12h",
- "24h",
- "2d",
- "7d",
- "30d"
- ],
"type": "timepicker"
},
"timezone": "browser",
diff --git a/devenv/datasources.yaml b/devenv/datasources.yaml
index 452d2d3d1bc..00efa243c1c 100644
--- a/devenv/datasources.yaml
+++ b/devenv/datasources.yaml
@@ -136,6 +136,14 @@ datasources:
tsdbResolution: 1
tsdbVersion: 3
+ - name: gdev-opentsdb-v2.4
+ type: opentsdb
+ access: proxy
+ url: http://localhost:4242
+ jsonData:
+ tsdbResolution: 1
+ tsdbVersion: 4
+
- name: gdev-elasticsearch
type: elasticsearch
uid: gdev-elasticsearch
diff --git a/devenv/dev-dashboards-without-uid/panel_tests_graph.json b/devenv/dev-dashboards-without-uid/panel_tests_graph.json
index b5d50f4f7b7..6bba1d9ae02 100644
--- a/devenv/dev-dashboards-without-uid/panel_tests_graph.json
+++ b/devenv/dev-dashboards-without-uid/panel_tests_graph.json
@@ -1639,8 +1639,7 @@
"to": "now"
},
"timepicker": {
- "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
- "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
+ "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
},
"timezone": "browser",
"title": "Panel Tests - Graph",
diff --git a/devenv/dev-dashboards-without-uid/panel_tests_graph_time_regions.json b/devenv/dev-dashboards-without-uid/panel_tests_graph_time_regions.json
index 3ff76d12df2..98d49958aaf 100644
--- a/devenv/dev-dashboards-without-uid/panel_tests_graph_time_regions.json
+++ b/devenv/dev-dashboards-without-uid/panel_tests_graph_time_regions.json
@@ -490,17 +490,6 @@
"1h",
"2h",
"1d"
- ],
- "time_options": [
- "5m",
- "15m",
- "1h",
- "6h",
- "12h",
- "24h",
- "2d",
- "7d",
- "30d"
]
},
"timezone": "browser",
diff --git a/devenv/dev-dashboards-without-uid/panel_tests_polystat.json b/devenv/dev-dashboards-without-uid/panel_tests_polystat.json
index 951bb780017..25b1f7154e5 100644
--- a/devenv/dev-dashboards-without-uid/panel_tests_polystat.json
+++ b/devenv/dev-dashboards-without-uid/panel_tests_polystat.json
@@ -3408,8 +3408,7 @@
"to": "now"
},
"timepicker": {
- "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
- "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
+ "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
},
"timezone": "",
"title": "Panel Tests - Polystat",
diff --git a/devenv/dev-dashboards/datasource-influxdb/influxdb-templated.json b/devenv/dev-dashboards/datasource-influxdb/influxdb-templated.json
index 97719e82251..f46ccc2042f 100644
--- a/devenv/dev-dashboards/datasource-influxdb/influxdb-templated.json
+++ b/devenv/dev-dashboards/datasource-influxdb/influxdb-templated.json
@@ -312,7 +312,6 @@
"now": true,
"refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
"status": "Stable",
- "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"],
"type": "timepicker"
},
"timezone": "browser",
diff --git a/devenv/dev-dashboards/datasource-mssql/mssql_fakedata.json b/devenv/dev-dashboards/datasource-mssql/mssql_fakedata.json
index 19c5e1d0718..8fda3e8e714 100644
--- a/devenv/dev-dashboards/datasource-mssql/mssql_fakedata.json
+++ b/devenv/dev-dashboards/datasource-mssql/mssql_fakedata.json
@@ -537,8 +537,7 @@
"to": "now"
},
"timepicker": {
- "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
- "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
+ "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
},
"timezone": "",
"title": "Datasource tests - MSSQL",
diff --git a/devenv/dev-dashboards/datasource-mssql/mssql_unittest.json b/devenv/dev-dashboards/datasource-mssql/mssql_unittest.json
index 0137001067c..40f9d55e5ca 100644
--- a/devenv/dev-dashboards/datasource-mssql/mssql_unittest.json
+++ b/devenv/dev-dashboards/datasource-mssql/mssql_unittest.json
@@ -2831,8 +2831,7 @@
"to": "2018-03-15T13:55:01.000Z"
},
"timepicker": {
- "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
- "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
+ "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
},
"timezone": "",
"title": "Datasource tests - MSSQL (unit test)",
diff --git a/devenv/dev-dashboards/datasource-mysql/mysql_fakedata.json b/devenv/dev-dashboards/datasource-mysql/mysql_fakedata.json
index 96e4688f7bd..cd1a24fb5bd 100644
--- a/devenv/dev-dashboards/datasource-mysql/mysql_fakedata.json
+++ b/devenv/dev-dashboards/datasource-mysql/mysql_fakedata.json
@@ -541,8 +541,7 @@
"to": "now"
},
"timepicker": {
- "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
- "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
+ "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
},
"timezone": "",
"title": "Datasource tests - MySQL",
diff --git a/devenv/dev-dashboards/datasource-mysql/mysql_unittest.json b/devenv/dev-dashboards/datasource-mysql/mysql_unittest.json
index b68c9db97ec..2f2a42c1175 100644
--- a/devenv/dev-dashboards/datasource-mysql/mysql_unittest.json
+++ b/devenv/dev-dashboards/datasource-mysql/mysql_unittest.json
@@ -2643,8 +2643,7 @@
"to": "2018-03-15T13:55:01.000Z"
},
"timepicker": {
- "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
- "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
+ "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
},
"timezone": "",
"title": "Datasource tests - MySQL (unittest)",
diff --git a/devenv/dev-dashboards/datasource-postgres/postgres_fakedata.json b/devenv/dev-dashboards/datasource-postgres/postgres_fakedata.json
index d7d9514e639..750b3284517 100644
--- a/devenv/dev-dashboards/datasource-postgres/postgres_fakedata.json
+++ b/devenv/dev-dashboards/datasource-postgres/postgres_fakedata.json
@@ -577,8 +577,7 @@
"to": "now"
},
"timepicker": {
- "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
- "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
+ "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
},
"timezone": "",
"title": "Datasource tests - Postgres",
diff --git a/devenv/dev-dashboards/datasource-postgres/postgres_unittest.json b/devenv/dev-dashboards/datasource-postgres/postgres_unittest.json
index a114ed1b7ef..acec0d08a44 100644
--- a/devenv/dev-dashboards/datasource-postgres/postgres_unittest.json
+++ b/devenv/dev-dashboards/datasource-postgres/postgres_unittest.json
@@ -2621,8 +2621,7 @@
"to": "2018-03-15T13:55:01.000Z"
},
"timepicker": {
- "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
- "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
+ "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
},
"timezone": "",
"title": "Datasource tests - Postgres (unittest)",
diff --git a/devenv/dev-dashboards/datasource-testdata/demo1.json b/devenv/dev-dashboards/datasource-testdata/demo1.json
index abe39ffeb55..6d8034f81e6 100644
--- a/devenv/dev-dashboards/datasource-testdata/demo1.json
+++ b/devenv/dev-dashboards/datasource-testdata/demo1.json
@@ -1092,7 +1092,6 @@
"now": true,
"refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
"status": "Stable",
- "time_options": ["5m", "15m", "1h", "2h", " 6h", "12h", "24h", "2d", "7d", "30d"],
"type": "timepicker"
},
"timezone": "browser",
diff --git a/devenv/dev-dashboards/datasource-testdata/new_features_in_v62.json b/devenv/dev-dashboards/datasource-testdata/new_features_in_v62.json
index 4b9535ecbbd..a002a208f85 100644
--- a/devenv/dev-dashboards/datasource-testdata/new_features_in_v62.json
+++ b/devenv/dev-dashboards/datasource-testdata/new_features_in_v62.json
@@ -1326,8 +1326,7 @@
"to": "now"
},
"timepicker": {
- "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
- "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
+ "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
},
"timezone": "",
"title": "New Features in v6.2",
diff --git a/devenv/dev-dashboards/home.json b/devenv/dev-dashboards/home.json
index 9c3d65d4add..840d32919ea 100644
--- a/devenv/dev-dashboards/home.json
+++ b/devenv/dev-dashboards/home.json
@@ -240,17 +240,6 @@
"1h",
"2h",
"1d"
- ],
- "time_options": [
- "5m",
- "15m",
- "1h",
- "6h",
- "12h",
- "24h",
- "2d",
- "7d",
- "30d"
]
},
"timezone": "",
diff --git a/devenv/dev-dashboards/panel-bargauge/bar_gauge_demo.json b/devenv/dev-dashboards/panel-bargauge/bar_gauge_demo.json
index a708467d7be..eda6ccfe996 100644
--- a/devenv/dev-dashboards/panel-bargauge/bar_gauge_demo.json
+++ b/devenv/dev-dashboards/panel-bargauge/bar_gauge_demo.json
@@ -654,8 +654,7 @@
"to": "now"
},
"timepicker": {
- "refresh_intervals": ["2s", "5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
- "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
+ "refresh_intervals": ["2s", "5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
},
"timezone": "",
"title": "Bar Gauge Demo",
diff --git a/devenv/dev-dashboards/panel-bargauge/panel_tests_bar_gauge.json b/devenv/dev-dashboards/panel-bargauge/panel_tests_bar_gauge.json
index 29a6929cf8f..3dfa360c740 100644
--- a/devenv/dev-dashboards/panel-bargauge/panel_tests_bar_gauge.json
+++ b/devenv/dev-dashboards/panel-bargauge/panel_tests_bar_gauge.json
@@ -1423,17 +1423,6 @@
"1h",
"2h",
"1d"
- ],
- "time_options": [
- "5m",
- "15m",
- "1h",
- "6h",
- "12h",
- "24h",
- "2d",
- "7d",
- "30d"
]
},
"timezone": "",
diff --git a/devenv/dev-dashboards/panel-bargauge/panel_tests_bar_gauge2.json b/devenv/dev-dashboards/panel-bargauge/panel_tests_bar_gauge2.json
index 0f36c203cd0..06fc26e382d 100644
--- a/devenv/dev-dashboards/panel-bargauge/panel_tests_bar_gauge2.json
+++ b/devenv/dev-dashboards/panel-bargauge/panel_tests_bar_gauge2.json
@@ -519,8 +519,7 @@
"to": "now"
},
"timepicker": {
- "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
- "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
+ "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
},
"timezone": "",
"title": "Panel Tests - Bar Gauge 2",
diff --git a/devenv/dev-dashboards/panel-common/lazy_loading.json b/devenv/dev-dashboards/panel-common/lazy_loading.json
index 859eede4b4f..960c466124c 100644
--- a/devenv/dev-dashboards/panel-common/lazy_loading.json
+++ b/devenv/dev-dashboards/panel-common/lazy_loading.json
@@ -2202,8 +2202,7 @@
"to": "now"
},
"timepicker": {
- "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
- "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
+ "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
},
"timezone": "",
"title": "Lazy Loading",
diff --git a/devenv/dev-dashboards/panel-common/panels_without_title.json b/devenv/dev-dashboards/panel-common/panels_without_title.json
index 44bd210e73b..8f62c9cca5e 100644
--- a/devenv/dev-dashboards/panel-common/panels_without_title.json
+++ b/devenv/dev-dashboards/panel-common/panels_without_title.json
@@ -893,8 +893,7 @@
"to": "now"
},
"timepicker": {
- "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
- "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
+ "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
},
"timezone": "",
"title": "Panel Tests - With & Without title",
diff --git a/devenv/dev-dashboards/panel-gauge/gauge-multi-series.json b/devenv/dev-dashboards/panel-gauge/gauge-multi-series.json
index 09b72e5c030..f7ff80edc12 100644
--- a/devenv/dev-dashboards/panel-gauge/gauge-multi-series.json
+++ b/devenv/dev-dashboards/panel-gauge/gauge-multi-series.json
@@ -254,8 +254,7 @@
"to": "now"
},
"timepicker": {
- "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
- "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
+ "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
},
"timezone": "",
"title": "Panel Tests - Gauge Multi Series",
diff --git a/devenv/dev-dashboards/panel-gauge/gauge_tests.json b/devenv/dev-dashboards/panel-gauge/gauge_tests.json
index 458f53dbc08..309a255fcc7 100644
--- a/devenv/dev-dashboards/panel-gauge/gauge_tests.json
+++ b/devenv/dev-dashboards/panel-gauge/gauge_tests.json
@@ -1319,8 +1319,7 @@
"to": "now"
},
"timepicker": {
- "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
- "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
+ "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
},
"timezone": "",
"title": "Panel Tests - Gauge",
diff --git a/devenv/dev-dashboards/panel-geomap/geomap-route-layer.json b/devenv/dev-dashboards/panel-geomap/geomap-route-layer.json
index f91036ace8b..c6b1752bd2a 100644
--- a/devenv/dev-dashboards/panel-geomap/geomap-route-layer.json
+++ b/devenv/dev-dashboards/panel-geomap/geomap-route-layer.json
@@ -29,20 +29,22 @@
"liveNow": false,
"panels": [
{
- "datasource": {
- "type": "testdata",
- "uid": "PD8C576611E62080A"
+ "id": 2,
+ "type": "geomap",
+ "title": "Multiple Layer Types",
+ "gridPos": {
+ "x": 0,
+ "y": 0,
+ "h": 16,
+ "w": 18
},
"fieldConfig": {
"defaults": {
- "color": {
- "mode": "continuous-RdYlGr"
- },
"custom": {
"hideFrom": {
- "legend": false,
"tooltip": false,
- "viz": false
+ "viz": false,
+ "legend": false
}
},
"mappings": [],
@@ -51,7 +53,7 @@
"steps": [
{
"color": "dark-red",
- "value": 0
+ "value": null
},
{
"color": "yellow",
@@ -62,18 +64,59 @@
"value": 100
}
]
+ },
+ "color": {
+ "mode": "continuous-RdYlGr"
}
},
"overrides": []
},
- "gridPos": {
- "h": 16,
- "w": 18,
- "x": 0,
- "y": 0
+ "pluginVersion": "11.6.0-pre",
+ "targets": [
+ {
+ "csvContent": "lat,lon,val\n-5,2,0\n1,5,25\n6,10,50\n9,15,75\n10,20,100",
+ "datasource": {
+ "type": "testdata",
+ "uid": "PD8C576611E62080A"
+ },
+ "refId": "A",
+ "scenarioId": "csv_content"
+ },
+ {
+ "scenarioId": "csv_content",
+ "refId": "B",
+ "datasource": {
+ "uid": "PD8C576611E62080A",
+ "type": "grafana-testdata-datasource"
+ },
+ "csvContent": "lat,lon,alt\n45,0,0\n40,5,5\n35,10,10\n30,15, 15\n25,20,20"
+ }
+ ],
+ "datasource": {
+ "type": "testdata",
+ "uid": "PD8C576611E62080A"
},
- "id": 2,
"options": {
+ "view": {
+ "allLayers": true,
+ "id": "fit",
+ "lat": 2.359794,
+ "lon": 8.135816,
+ "zoom": 15,
+ "lastOnly": false,
+ "layer": "markers"
+ },
+ "controls": {
+ "showZoom": true,
+ "mouseWheelZoom": true,
+ "showAttribution": true,
+ "showScale": false,
+ "showMeasure": false,
+ "showDebug": false
+ },
+ "tooltip": {
+ "mode": "details"
+ },
"basemap": {
"config": {
"server": "streets"
@@ -81,14 +124,6 @@
"name": "Layer 0",
"type": "esri-xyz"
},
- "controls": {
- "mouseWheelZoom": true,
- "showAttribution": true,
- "showDebug": false,
- "showMeasure": false,
- "showScale": false,
- "showZoom": true
- },
"layers": [
{
"config": {
@@ -128,36 +163,108 @@
"location": {
"mode": "auto"
},
- "name": "Layer 2",
+ "name": "route",
"tooltip": true,
"type": "route"
- }
- ],
- "tooltip": {
- "mode": "details"
- },
- "view": {
- "allLayers": true,
- "id": "coords",
- "lat": 2.359794,
- "lon": 8.135816,
- "zoom": 4.45
- }
- },
- "pluginVersion": "9.4.0-pre",
- "targets": [
- {
- "csvContent": "lat,lon,val\n-5,2,0\n1,5,25\n6,10,50\n9,15,75\n10,20,100",
- "datasource": {
- "type": "testdata",
- "uid": "PD8C576611E62080A"
},
- "refId": "A",
- "scenarioId": "csv_content"
- }
- ],
- "title": "Route with Colors",
- "type": "geomap"
+ {
+ "type": "geojson",
+ "name": "geojson",
+ "config": {
+ "src": "public/maps/example-with-style.geojson",
+ "rules": [],
+ "style": {
+ "size": {
+ "fixed": 5,
+ "min": 2,
+ "max": 15
+ },
+ "color": {
+ "fixed": "dark-green"
+ },
+ "opacity": 0.4,
+ "symbol": {
+ "mode": "fixed",
+ "fixed": "img/icons/marker/circle.svg"
+ },
+ "symbolAlign": {
+ "horizontal": "center",
+ "vertical": "center"
+ },
+ "textConfig": {
+ "fontSize": 12,
+ "textAlign": "center",
+ "textBaseline": "middle",
+ "offsetX": 0,
+ "offsetY": 0
+ },
+ "rotation": {
+ "fixed": 0,
+ "mode": "mod",
+ "min": -360,
+ "max": 360
+ }
+ }
+ },
+ "location": {
+ "mode": "auto"
+ },
+ "tooltip": true,
+ "filterData": {
+ "id": "byRefId",
+ "options": "B"
+ }
+ },
+ {
+ "type": "markers",
+ "name": "markers",
+ "config": {
+ "style": {
+ "size": {
+ "fixed": 5,
+ "min": 2,
+ "max": 15
+ },
+ "color": {
+ "fixed": "dark-green",
+ "field": "alt"
+ },
+ "opacity": 0.4,
+ "symbol": {
+ "mode": "fixed",
+ "fixed": "img/icons/marker/circle.svg"
+ },
+ "symbolAlign": {
+ "horizontal": "center",
+ "vertical": "center"
+ },
+ "textConfig": {
+ "fontSize": 12,
+ "textAlign": "center",
+ "textBaseline": "middle",
+ "offsetX": 0,
+ "offsetY": 0
+ },
+ "rotation": {
+ "fixed": 0,
+ "mode": "mod",
+ "min": -360,
+ "max": 360
+ }
+ },
+ "showLegend": true
+ },
+ "location": {
+ "mode": "auto"
+ },
+ "tooltip": true,
+ "filterData": {
+ "id": "byRefId",
+ "options": "B"
+ }
+ }
+ ]
+ }
}
],
"schemaVersion": 37,
@@ -171,7 +278,7 @@
},
"timepicker": {},
"timezone": "",
- "title": "Panel Tests - Geomap Route Layer",
+ "title": "Panel Tests - Geomap Fit to Data - Multiple Layer Types",
"uid": "OYTKK3DVk",
"version": 25,
"weekStart": ""
diff --git a/devenv/dev-dashboards/panel-graph/graph-gradient-area-fills.json b/devenv/dev-dashboards/panel-graph/graph-gradient-area-fills.json
index 01e9e8c2f43..c2d27efd469 100644
--- a/devenv/dev-dashboards/panel-graph/graph-gradient-area-fills.json
+++ b/devenv/dev-dashboards/panel-graph/graph-gradient-area-fills.json
@@ -372,8 +372,7 @@
"to": "now"
},
"timepicker": {
- "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
- "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
+ "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
},
"timezone": "",
"title": "Panel Tests - Graph - Gradient Area Fills",
diff --git a/devenv/dev-dashboards/panel-graph/graph-time-regions.json b/devenv/dev-dashboards/panel-graph/graph-time-regions.json
index 2031788ae3f..a4e03148536 100644
--- a/devenv/dev-dashboards/panel-graph/graph-time-regions.json
+++ b/devenv/dev-dashboards/panel-graph/graph-time-regions.json
@@ -569,8 +569,7 @@
"to": "now"
},
"timepicker": {
- "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
- "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
+ "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
},
"timezone": "browser",
"title": "Panel Tests - Graph Time Regions",
diff --git a/devenv/dev-dashboards/panel-graph/graph_tests.json b/devenv/dev-dashboards/panel-graph/graph_tests.json
index 4d01c2cb534..bd1fc95d3d6 100644
--- a/devenv/dev-dashboards/panel-graph/graph_tests.json
+++ b/devenv/dev-dashboards/panel-graph/graph_tests.json
@@ -1639,8 +1639,7 @@
"to": "now"
},
"timepicker": {
- "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
- "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
+ "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
},
"timezone": "browser",
"title": "Panel Tests - Graph",
diff --git a/devenv/dev-dashboards/panel-polystat/polystat_test.json b/devenv/dev-dashboards/panel-polystat/polystat_test.json
index 6be355ebd99..faa84463019 100644
--- a/devenv/dev-dashboards/panel-polystat/polystat_test.json
+++ b/devenv/dev-dashboards/panel-polystat/polystat_test.json
@@ -3408,8 +3408,7 @@
"to": "now"
},
"timepicker": {
- "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
- "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
+ "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
},
"timezone": "",
"title": "Panel Tests - Polystat",
diff --git a/devenv/dev-dashboards/panel-table/table_tests.json b/devenv/dev-dashboards/panel-table/table_tests.json
index 8582ef068d7..b8ca436e110 100644
--- a/devenv/dev-dashboards/panel-table/table_tests.json
+++ b/devenv/dev-dashboards/panel-table/table_tests.json
@@ -440,8 +440,7 @@
"to": "now"
},
"timepicker": {
- "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
- "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
+ "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
},
"timezone": "browser",
"title": "Panel Tests - Table",
diff --git a/devenv/dev-dashboards/panel-timeseries/timeseries-gradient-area.json b/devenv/dev-dashboards/panel-timeseries/timeseries-gradient-area.json
index a7389cc6ed6..8f3267a62d7 100644
--- a/devenv/dev-dashboards/panel-timeseries/timeseries-gradient-area.json
+++ b/devenv/dev-dashboards/panel-timeseries/timeseries-gradient-area.json
@@ -562,8 +562,7 @@
"to": "now"
},
"timepicker": {
- "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
- "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
+ "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
},
"timezone": "",
"title": "Panel Tests - Graph NG - Gradient Area Fills",
diff --git a/devenv/dev-dashboards/scenarios/slow_queries_and_annotations.json b/devenv/dev-dashboards/scenarios/slow_queries_and_annotations.json
index a7cc41acd8f..8966137b55e 100644
--- a/devenv/dev-dashboards/scenarios/slow_queries_and_annotations.json
+++ b/devenv/dev-dashboards/scenarios/slow_queries_and_annotations.json
@@ -1132,8 +1132,7 @@
"to": "now"
},
"timepicker": {
- "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
- "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
+ "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
},
"timezone": "",
"title": "Panel tests - Slow Queries & Annotations",
diff --git a/devenv/dev-dashboards/scenarios/time_zone_support.json b/devenv/dev-dashboards/scenarios/time_zone_support.json
index feb317f917e..cc1f81ee221 100644
--- a/devenv/dev-dashboards/scenarios/time_zone_support.json
+++ b/devenv/dev-dashboards/scenarios/time_zone_support.json
@@ -684,8 +684,7 @@
"to": "now"
},
"timepicker": {
- "refresh_intervals": ["10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"],
- "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"]
+ "refresh_intervals": ["10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"]
},
"timezone": "utc",
"title": "Panel Tests - Time zone support",
diff --git a/devenv/docker/blocks/elasticstack/docker-compose.yaml b/devenv/docker/blocks/elasticstack/docker-compose.yaml
index ad8a0d5e7f0..35b4254ac63 100644
--- a/devenv/docker/blocks/elasticstack/docker-compose.yaml
+++ b/devenv/docker/blocks/elasticstack/docker-compose.yaml
@@ -5,6 +5,8 @@
- "discovery.type=single-node"
- "xpack.license.self_generated.type=basic"
- "xpack.security.enabled=false"
+ - 'ES_JAVA_OPTS=-XX:UseSVE=0'
+ - 'CLI_JAVA_OPTS=-XX:UseSVE=0'
ports:
- 9200:9200
diff --git a/devenv/docker/blocks/prometheus/recording.yml b/devenv/docker/blocks/prometheus/recording.yml
index f45cdbeddf2..2b8ae3e477a 100644
--- a/devenv/docker/blocks/prometheus/recording.yml
+++ b/devenv/docker/blocks/prometheus/recording.yml
@@ -1,4 +1,18 @@
groups:
+ - name: TESTING_RULES
+ rules:
+ - record: test:rate5m
+ expr: rate(ismail_prometheus_tsdb_reloads_total{job="prometheus"}[5m])
+ labels:
+ identifier: special_idx
+ - record: agent:test:rate5m
+ expr: rate(prometheus_tsdb_reloads_total{job="prometheus"}[5m])
+ labels:
+ identifier: special_idx
+ - record: agent:test:rate5m_agg_
+ expr: rate(prometheus_tsdb_reloads_total_agg_{job="aggregated"}[5m])
+ labels:
+ identifier: special_idx
- name: RECORDING_RULES
rules:
- record: instance_path:requests:rate5m
@@ -9,6 +23,14 @@ groups:
expr: rate(prometheus_tsdb_reloads_failures_total{job="prometheus"}[5m])
- record: instance_path:reloads:rate5m
expr: rate(prometheus_tsdb_reloads_total{job="prometheus"}[5m])
+ - record: test:rate5m
+ expr: rate(prometheus_tsdb_reloads_total{job="prometheus"}[5m])
+ - record: test:rate5m_agg_
+ expr: rate(prometheus_tsdb_reloads_total_agg_{job="aggregated"}[5m])
+ - record: agent:test:rate5m
+ expr: rate(prometheus_tsdb_reloads_total{job="prometheus"}[5m])
+ - record: agent:test:rate5m_agg_
+ expr: rate(prometheus_tsdb_reloads_total_agg_{job="aggregated"}[5m])
- record: instance_path:request_failures_per_requests:ratio_rate5m
expr: |2
instance_path:reloads_failures:rate5m{job="prometheus"}
diff --git a/devenv/docker/blocks/prometheus_high_card/go.mod b/devenv/docker/blocks/prometheus_high_card/go.mod
index be940ff6862..8dda4f5d7e2 100644
--- a/devenv/docker/blocks/prometheus_high_card/go.mod
+++ b/devenv/docker/blocks/prometheus_high_card/go.mod
@@ -1,6 +1,6 @@
module high-card
-go 1.22.4
+go 1.23.7
require (
github.com/prometheus/client_golang v1.20.2
@@ -15,6 +15,6 @@ require (
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.55.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
- golang.org/x/sys v0.22.0 // indirect
+ golang.org/x/sys v0.30.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
)
diff --git a/devenv/docker/blocks/prometheus_high_card/go.sum b/devenv/docker/blocks/prometheus_high_card/go.sum
index 742cb8092ff..93dcce3f212 100644
--- a/devenv/docker/blocks/prometheus_high_card/go.sum
+++ b/devenv/docker/blocks/prometheus_high_card/go.sum
@@ -20,7 +20,7 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
golang.org/x/exp v0.0.0-20240823005443-9b4947da3948 h1:kx6Ds3MlpiUHKj7syVnbp57++8WpuKPcR5yjLBjvLEA=
golang.org/x/exp v0.0.0-20240823005443-9b4947da3948/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
-golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
-golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
+golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
diff --git a/devenv/docker/blocks/prometheus_random_data/Dockerfile b/devenv/docker/blocks/prometheus_random_data/Dockerfile
index c4ebc8cb0ec..41f90677409 100644
--- a/devenv/docker/blocks/prometheus_random_data/Dockerfile
+++ b/devenv/docker/blocks/prometheus_random_data/Dockerfile
@@ -7,7 +7,7 @@ RUN CGO_ENABLED=0 GOOS=linux go install -tags netgo -ldflags '-w' github.com/pro
# Final image.
FROM scratch
-LABEL maintainer "The Prometheus Authors "
+LABEL maintainer="The Prometheus Authors "
COPY --from=builder /go/bin/random .
EXPOSE 8080
ENTRYPOINT ["/random"]
diff --git a/devenv/docker/blocks/prometheus_utf8/go.mod b/devenv/docker/blocks/prometheus_utf8/go.mod
index 706d2d12e81..1202be94ed6 100644
--- a/devenv/docker/blocks/prometheus_utf8/go.mod
+++ b/devenv/docker/blocks/prometheus_utf8/go.mod
@@ -1,9 +1,10 @@
module utf8-support
-go 1.22.4
+go 1.23.7
require (
github.com/prometheus/client_golang v1.20.5
+ github.com/prometheus/common v0.60.1
golang.org/x/exp v0.0.0-20240823005443-9b4947da3948
)
@@ -13,8 +14,7 @@ require (
github.com/klauspost/compress v1.17.9 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
- github.com/prometheus/common v0.60.1 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
- golang.org/x/sys v0.25.0 // indirect
+ golang.org/x/sys v0.30.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
)
diff --git a/devenv/docker/blocks/prometheus_utf8/go.sum b/devenv/docker/blocks/prometheus_utf8/go.sum
index 5b2f91420df..be3770f9e3f 100644
--- a/devenv/docker/blocks/prometheus_utf8/go.sum
+++ b/devenv/docker/blocks/prometheus_utf8/go.sum
@@ -26,8 +26,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/exp v0.0.0-20240823005443-9b4947da3948 h1:kx6Ds3MlpiUHKj7syVnbp57++8WpuKPcR5yjLBjvLEA=
golang.org/x/exp v0.0.0-20240823005443-9b4947da3948/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
-golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
-golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
+golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
diff --git a/devenv/docker/blocks/stateful_webhook/Dockerfile b/devenv/docker/blocks/stateful_webhook/Dockerfile
new file mode 100644
index 00000000000..4b671c20410
--- /dev/null
+++ b/devenv/docker/blocks/stateful_webhook/Dockerfile
@@ -0,0 +1,12 @@
+FROM golang:1.23.7
+
+ADD main.go /go/src/webhook/main.go
+
+WORKDIR /go/src/webhook
+
+RUN mkdir /tmp/logs
+RUN go build -o /bin main.go
+
+ENV PORT=8080
+
+ENTRYPOINT [ "/bin/main" ]
diff --git a/devenv/docker/blocks/stateful_webhook/docker-compose.yaml b/devenv/docker/blocks/stateful_webhook/docker-compose.yaml
new file mode 100644
index 00000000000..7217516c4e9
--- /dev/null
+++ b/devenv/docker/blocks/stateful_webhook/docker-compose.yaml
@@ -0,0 +1,5 @@
+ stateful_webhook:
+ build:
+ context: docker/blocks/stateful_webhook
+ ports:
+ - "8080:8080"
diff --git a/devenv/docker/blocks/stateful_webhook/main.go b/devenv/docker/blocks/stateful_webhook/main.go
new file mode 100644
index 00000000000..926cf4e593e
--- /dev/null
+++ b/devenv/docker/blocks/stateful_webhook/main.go
@@ -0,0 +1,149 @@
+package main
+
+import (
+ "encoding/json"
+ "io"
+ "log"
+ "net/http"
+ "strings"
+ "sync"
+ "time"
+)
+
+type Event struct {
+ Status string `json:"status"`
+ TimeNow time.Time `json:"timeNow"`
+ StartsAt time.Time `json:"startsAt"`
+ Node string `json:"node"`
+ DeltaLastSeconds float64 `json:"deltaLastSeconds"`
+ DeltaStartSeconds float64 `json:"deltaStartSeconds"`
+}
+
+type Notification struct {
+ Alerts []Alert `json:"alerts"`
+ CommonAnnotations map[string]string `json:"commonAnnotations"`
+ CommonLabels map[string]string `json:"commonLabels"`
+ ExternalURL string `json:"externalURL"`
+ GroupKey string `json:"groupKey"`
+ GroupLabels map[string]string `json:"groupLabels"`
+ Message string `json:"message"`
+ OrgID int `json:"orgId"`
+ Receiver string `json:"receiver"`
+ State string `json:"state"`
+ Status string `json:"status"`
+ Title string `json:"title"`
+ TruncatedAlerts int `json:"truncatedAlerts"`
+ Version string `json:"version"`
+}
+
+type Alert struct {
+ Annotations map[string]string `json:"annotations"`
+ DashboardURL string `json:"dashboardURL"`
+ StartsAt time.Time `json:"startsAt"`
+ EndsAt time.Time `json:"endsAt"`
+ Fingerprint string `json:"fingerprint"`
+ GeneratorURL string `json:"generatorURL"`
+ Labels map[string]string `json:"labels"`
+ PanelURL string `json:"panelURL"`
+ SilenceURL string `json:"silenceURL"`
+ Status string `json:"status"`
+ ValueString string `json:"valueString"`
+ Values map[string]any `json:"values"`
+}
+
+type NotificationHandler struct {
+ startedAt time.Time
+ stats map[string]int
+ hist []Event
+ m sync.Mutex
+}
+
+func NewNotificationHandler() *NotificationHandler {
+ return &NotificationHandler{
+ startedAt: time.Now(),
+ stats: make(map[string]int),
+ hist: make([]Event, 0),
+ }
+}
+
+func (ah *NotificationHandler) Notify(w http.ResponseWriter, r *http.Request) {
+ b, err := io.ReadAll(r.Body)
+ if err != nil {
+ log.Println(err)
+ w.WriteHeader(http.StatusBadRequest)
+ return
+ }
+ n := Notification{}
+ if err := json.Unmarshal(b, &n); err != nil {
+ log.Println(err)
+ w.WriteHeader(http.StatusBadRequest)
+ return
+ }
+ log.Printf("got notification from: %s. a: %v", r.RemoteAddr, n)
+
+ ah.m.Lock()
+ defer ah.m.Unlock()
+
+ addr := r.RemoteAddr
+ if split := strings.Split(r.RemoteAddr, ":"); len(split) > 0 {
+ addr = split[0]
+ }
+
+ a := n.Alerts[0]
+
+ timeNow := time.Now()
+
+ ah.stats[n.Status]++
+
+ var d time.Duration
+ if len(ah.hist) > 0 {
+ last := ah.hist[len(ah.hist)-1]
+ d = timeNow.Sub(last.TimeNow)
+ }
+
+ ah.hist = append(ah.hist, Event{
+ Status: n.Status,
+ StartsAt: a.StartsAt,
+ TimeNow: timeNow,
+ Node: addr,
+ DeltaLastSeconds: d.Seconds(),
+ DeltaStartSeconds: timeNow.Sub(ah.startedAt).Seconds(),
+ })
+}
+
+func (ah *NotificationHandler) GetNotifications(w http.ResponseWriter, _ *http.Request) {
+ ah.m.Lock()
+ defer ah.m.Unlock()
+ w.Header().Set("Content-Type", "application/json")
+
+ res, err := json.MarshalIndent(map[string]any{"stats": ah.stats, "history": ah.hist}, "", "\t")
+ if err != nil {
+ w.WriteHeader(http.StatusInternalServerError)
+ //nolint:errcheck
+ w.Write([]byte(`{"error":"failed to marshal alerts"}`))
+ log.Printf("failed to marshal alerts: %v\n", err)
+ return
+ }
+
+ log.Printf("requested current state\n%v\n", string(res))
+
+ _, err = w.Write(res)
+ if err != nil {
+ log.Printf("failed to write response: %v\n", err)
+ }
+}
+
+func main() {
+ ah := NewNotificationHandler()
+
+ http.HandleFunc("/ready", func(w http.ResponseWriter, _ *http.Request) {
+ w.WriteHeader(http.StatusOK)
+ })
+
+ http.HandleFunc("/notify", ah.Notify)
+ http.HandleFunc("/notifications", ah.GetNotifications)
+
+ log.Println("Listening")
+ //nolint:errcheck
+ http.ListenAndServe("0.0.0.0:8080", nil)
+}
diff --git a/devenv/docker/blocks/tempo/tempo.yaml b/devenv/docker/blocks/tempo/tempo.yaml
index 7cfb1230a3f..b1130a6e27c 100644
--- a/devenv/docker/blocks/tempo/tempo.yaml
+++ b/devenv/docker/blocks/tempo/tempo.yaml
@@ -6,15 +6,23 @@ distributor:
jaeger: # the receives all come from the OpenTelemetry collector. more configuration information can
protocols: # be found there: https://github.com/open-telemetry/opentelemetry-collector/tree/main/receiver
thrift_http: #
- grpc: # for a production deployment you should only enable the receivers you need!
+ endpoint: "tempo:14268" # for a production deployment you should only enable the receivers you need!
+ grpc:
+ endpoint: "tempo:14250"
thrift_binary:
+ endpoint: "tempo:6832"
thrift_compact:
+ endpoint: "tempo:6831"
zipkin:
+ endpoint: "tempo:9411"
otlp:
protocols:
- http:
grpc:
+ endpoint: "tempo:4317"
+ http:
+ endpoint: "tempo:4318"
opencensus:
+ endpoint: "tempo:55678"
compactor:
compaction:
diff --git a/devenv/docker/ha-test-unified-alerting/grafana/provisioning/dashboards/alerts/overview.json b/devenv/docker/ha-test-unified-alerting/grafana/provisioning/dashboards/alerts/overview.json
index b4946cfb6b3..0357c3d10f1 100644
--- a/devenv/docker/ha-test-unified-alerting/grafana/provisioning/dashboards/alerts/overview.json
+++ b/devenv/docker/ha-test-unified-alerting/grafana/provisioning/dashboards/alerts/overview.json
@@ -151,17 +151,6 @@
"1h",
"2h",
"1d"
- ],
- "time_options": [
- "5m",
- "15m",
- "1h",
- "6h",
- "12h",
- "24h",
- "2d",
- "7d",
- "30d"
]
},
"timezone": "",
diff --git a/devenv/docker/ha-test-unified-alerting/grafana/provisioning/dashboards/mysql/overview.json b/devenv/docker/ha-test-unified-alerting/grafana/provisioning/dashboards/mysql/overview.json
index 7643250ec28..2bf789366cc 100644
--- a/devenv/docker/ha-test-unified-alerting/grafana/provisioning/dashboards/mysql/overview.json
+++ b/devenv/docker/ha-test-unified-alerting/grafana/provisioning/dashboards/mysql/overview.json
@@ -5376,17 +5376,6 @@
"1d"
],
"status": "Stable",
- "time_options": [
- "5m",
- "15m",
- "1h",
- "6h",
- "12h",
- "24h",
- "2d",
- "7d",
- "30d"
- ],
"type": "timepicker"
},
"timezone": "browser",
diff --git a/devenv/docker/ha_test/grafana/provisioning/dashboards/alerts/overview.json b/devenv/docker/ha_test/grafana/provisioning/dashboards/alerts/overview.json
index b4946cfb6b3..0357c3d10f1 100644
--- a/devenv/docker/ha_test/grafana/provisioning/dashboards/alerts/overview.json
+++ b/devenv/docker/ha_test/grafana/provisioning/dashboards/alerts/overview.json
@@ -151,17 +151,6 @@
"1h",
"2h",
"1d"
- ],
- "time_options": [
- "5m",
- "15m",
- "1h",
- "6h",
- "12h",
- "24h",
- "2d",
- "7d",
- "30d"
]
},
"timezone": "",
diff --git a/devenv/docker/ha_test/grafana/provisioning/dashboards/mysql/overview.json b/devenv/docker/ha_test/grafana/provisioning/dashboards/mysql/overview.json
index 7643250ec28..2bf789366cc 100644
--- a/devenv/docker/ha_test/grafana/provisioning/dashboards/mysql/overview.json
+++ b/devenv/docker/ha_test/grafana/provisioning/dashboards/mysql/overview.json
@@ -5376,17 +5376,6 @@
"1d"
],
"status": "Stable",
- "time_options": [
- "5m",
- "15m",
- "1h",
- "6h",
- "12h",
- "24h",
- "2d",
- "7d",
- "30d"
- ],
"type": "timepicker"
},
"timezone": "browser",
diff --git a/docs/Makefile b/docs/Makefile
index 36b7e4f41be..7bdbe026293 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -9,6 +9,6 @@ include docs.mk
.PHONY: sources/panels-visualizations/query-transform-data/transform-data/index.md
sources/panels-visualizations/query-transform-data/transform-data/index.md: ## Generate the Transform Data page source.
- cd $(CURDIR)/.. && npx tsc ./scripts/docs/generate-transformations.ts && \
- node -e "require('./scripts/docs/generate-transformations').buildMarkdownContent()" && \
+ cd $(CURDIR)/.. && \
+ npx tsx ./scripts/docs/generate-transformations.ts && \
npx prettier -w $(CURDIR)/$@
diff --git a/docs/README.md b/docs/README.md
index 4bea7d788e7..0bf4e8446b5 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -48,18 +48,6 @@ Only use [reference style links](https://grafana.com/docs/writers-toolkit/write/
### [Contributing](/contribute/documentation/README.md)
-### Using `relref` for internal links
-
-Use the Hugo shortcode [relref](https://gohugo.io/content-management/cross-references/#use-ref-and-relref) any time you are linking to other internal docs pages.
-
-Syntax is:
-
-```
-{{< relref "example.md" >}}
-```
-
-You might need to add more context for the link (containing folders and so on, `folder/example.md`) if Hugo says the relref is ambiguous.
-
### Managing redirects
When moving content around or removing pages it's important that users following old links are properly redirected to the new location. We do this using the [aliases](https://gohugo.io/content-management/urls/#aliases) feature in Hugo.
diff --git a/docs/docs.mk b/docs/docs.mk
index c0aae10ba50..09308dc8604 100644
--- a/docs/docs.mk
+++ b/docs/docs.mk
@@ -120,3 +120,12 @@ update: ## Fetch the latest version of this Makefile and the `make-docs` script
curl -s -LO https://raw.githubusercontent.com/grafana/writers-toolkit/main/docs/docs.mk
curl -s -LO https://raw.githubusercontent.com/grafana/writers-toolkit/main/docs/make-docs
chmod +x make-docs
+
+# ls static/templates/ | sed 's/-template\.md//' | xargs
+TOPIC_TYPES := concept multiple-tasks reference section task tutorial visualization
+.PHONY: $(patsubst %,topic/%,$(TOPIC_TYPES))
+topic/%: ## Create a topic from the Writers' Toolkit template. Specify the topic type as the target, for example, `make topic/task TOPIC_PATH=sources/my-new-topic.md`.
+$(patsubst %,topic/%,$(TOPIC_TYPES)):
+ $(if $(TOPIC_PATH),,$(error "You must set the TOPIC_PATH variable to the path where the $(@F) topic will be created. For example: make $(@) TOPIC_PATH=sources/my-new-topic.md"))
+ mkdir -p $(dir $(TOPIC_PATH))
+ curl -s -o $(TOPIC_PATH) https://raw.githubusercontent.com/grafana/writers-toolkit/refs/heads/main/docs/static/templates/$(@F)-template.md
diff --git a/docs/make-docs b/docs/make-docs
index ba448ce0727..f6d72f905dc 100755
--- a/docs/make-docs
+++ b/docs/make-docs
@@ -1,4 +1,6 @@
#!/bin/sh
+# shellcheck disable=SC2034
+#
# The source of this file is https://raw.githubusercontent.com/grafana/writers-toolkit/main/docs/make-docs.
# # `make-docs` procedure changelog
#
@@ -6,6 +8,30 @@
# [Semantic versioning](https://semver.org/) is used to help the reader identify the significance of changes.
# Changes are relevant to this script and the support docs.mk GNU Make interface.
#
+# ## 8.5.2 (2025-02-28)
+#
+# ### Fixed
+#
+# - topic/ targets are no longer no-ops as a result of 8.5.1.
+#
+# ## 8.5.1 (2025-02-18)
+#
+# ### Fixed
+#
+# - PHONY declaration for topic/ targets.
+#
+# ## 8.5.0 (2025-02-13)
+#
+# ### Added
+#
+# - make topic/ TOPIC_PATH= target to create a new topic from the Writers' Toolkit templates.
+#
+# ## 8.4.0 (2025-01-27)
+#
+# ### Fixed
+#
+# - Correct mount for the /docs/grafana-cloud/send-data/fleet-management/ project.
+#
# ## 8.3.0 (2024-12-27)
#
# ### Added
@@ -304,6 +330,7 @@ PODMAN="$(if command -v podman >/dev/null 2>&1; then echo podman; else echo dock
if ! command -v curl >/dev/null 2>&1; then
if ! command -v wget >/dev/null 2>&1; then
+ # shellcheck disable=SC2016
errr 'either `curl` or `wget` must be installed for this script to work.'
exit 1
@@ -311,6 +338,7 @@ if ! command -v curl >/dev/null 2>&1; then
fi
if ! command -v "${PODMAN}" >/dev/null 2>&1; then
+ # shellcheck disable=SC2016
errr 'either `podman` or `docker` must be installed for this script to work.'
exit 1
@@ -357,6 +385,10 @@ EOF
exit 1
fi
+# The following variables comprise a pseudo associative array of project names to source repositories.
+# You only need to set a SOURCES variable if the project name does not match the source repository name.
+# You can get a key identifier using the `identifier` function.
+# To look up the value of any pseudo associative array, use the `aget` function.
SOURCES_as_code='as-code-docs'
SOURCES_enterprise_metrics='backend-enterprise'
SOURCES_enterprise_metrics_='backend-enterprise'
@@ -366,11 +398,16 @@ SOURCES_grafana_cloud_alerting_and_irm_slo='slo'
SOURCES_grafana_cloud_k6='k6-docs'
SOURCES_grafana_cloud_data_configuration_integrations='cloud-onboarding'
SOURCES_grafana_cloud_frontend_observability_faro_web_sdk='faro-web-sdk'
+SOURCES_grafana_cloud_send_data_fleet_management='fleet-management'
SOURCES_helm_charts_mimir_distributed='mimir'
SOURCES_helm_charts_tempo_distributed='tempo'
SOURCES_opentelemetry='opentelemetry-docs'
SOURCES_resources='website'
+# The following variables comprise a pseudo associative array of project names to versions.
+# You only need to set a VERSIONS variable if it is not the default of 'latest'.
+# You can get a key identifier using the `identifier` function.
+# To look up the value of any pseudo associative array, use the `aget` function.
VERSIONS_as_code='UNVERSIONED'
VERSIONS_grafana_cloud='UNVERSIONED'
VERSIONS_grafana_cloud_alerting_and_irm_machine_learning='UNVERSIONED'
@@ -378,12 +415,17 @@ VERSIONS_grafana_cloud_alerting_and_irm_slo='UNVERSIONED'
VERSIONS_grafana_cloud_k6='UNVERSIONED'
VERSIONS_grafana_cloud_data_configuration_integrations='UNVERSIONED'
VERSIONS_grafana_cloud_frontend_observability_faro_web_sdk='UNVERSIONED'
+VERSIONS_grafana_cloud_send_data_fleet_management='UNVERSIONED'
VERSIONS_opentelemetry='UNVERSIONED'
VERSIONS_resources='UNVERSIONED'
VERSIONS_technical_documentation='UNVERSIONED'
VERSIONS_website='UNVERSIONED'
VERSIONS_writers_toolkit='UNVERSIONED'
+# The following variables comprise a pseudo associative array of project names to source repository paths.
+# You only need to set a PATHS variable if it is not the default of 'docs/sources'.
+# You can get a key identifier using the `identifier` function.
+# To look up the value of any pseudo associative array, use the `aget` function.
PATHS_grafana_cloud='content/docs/grafana-cloud'
PATHS_helm_charts_mimir_distributed='docs/sources/helm-charts/mimir-distributed'
PATHS_helm_charts_tempo_distributed='docs/sources/helm-charts/tempo-distributed'
@@ -816,7 +858,9 @@ EOF
case "${OUTPUT_FORMAT}" in
human)
if ! command -v jq >/dev/null 2>&1; then
+ # shellcheck disable=SC2016
errr '`jq` must be installed for the `doc-validator` target to work.'
+ # shellcheck disable=SC2016
note 'To install `jq`, refer to https://jqlang.github.io/jq/download/,'
exit 1
diff --git a/docs/sources/_index.md b/docs/sources/_index.md
index 989ceddad50..c64772641e4 100644
--- a/docs/sources/_index.md
+++ b/docs/sources/_index.md
@@ -4,7 +4,9 @@ aliases:
- /docs/grafana/v3.1/
- guides/reference/admin/
cascade:
+ LOKI_VERSION: latest
TEMPO_VERSION: latest
+ ONCALL_VERSION: latest
PYROSCOPE_VERSION: latest
description: Find answers to your technical questions and learn how to use Grafana OSS and Enterprise products.
keywords:
diff --git a/docs/sources/administration/correlations/_index.md b/docs/sources/administration/correlations/_index.md
index 3a61b1800b5..36e0badf5f5 100644
--- a/docs/sources/administration/correlations/_index.md
+++ b/docs/sources/administration/correlations/_index.md
@@ -14,23 +14,23 @@ weight: 900
You can create interactive links for Explore visualizations by setting up Correlations. These links can either run queries or generate external URLs related to presented data.
-A correlation defines how data in one [data source]({{< relref "../../datasources" >}}) is used to query data in another data source or to generate an external URL.
+A correlation defines how data in one [data source](../../datasources/) is used to query data in another data source or to generate an external URL.
Some examples:
- an application name returned in a logs data source can be used to query metrics related to that application in a metrics data source, or
- a user name returned by an SQL data source can be used to query logs related to that particular user in a logs data source
- a customer ID in a logs data source can link to a different platform that has a profile on that customer.
-[Explore]({{< relref "../../explore" >}}) takes user-defined correlations to display links inside the visualizations.
-If a correlation links to a query, you can click on that link to run the related query and see results in [Explore Split View]({{< relref "../../explore#split-and-compare" >}}).
+[Explore](../../explore/) takes user-defined correlations to display links inside the visualizations.
+If a correlation links to a query, you can click on that link to run the related query and see results in [Explore Split View](../../explore/#split-and-compare).
If a correlation links to an external URL, you can click on the link to open the URL in a new tab in your browser.
Explore visualizations that currently support showing links based on correlations:
-- [Logs Panel]({{< relref "./use-correlations-in-visualizations#correlations-in-logs-panel">}})
-- [Table]({{< relref "./use-correlations-in-visualizations#correlations-in-table">}})
+- [Logs Panel](use-correlations-in-visualizations/#correlations-in-logs-panel)
+- [Table](use-correlations-in-visualizations/#correlations-in-table)
-You can configure correlations using [provisioning]({{< relref "../provisioning" >}}), the **Administration > Plugins and data > Correlations** page in Grafana or directly in [Explore]({{< relref "../../explore/correlations-editor-in-explore" >}}).
+You can configure correlations using [provisioning](../provisioning/), the **Administration > Plugins and data > Correlations** page in Grafana or directly in [Explore](../../explore/correlations-editor-in-explore/).
## Example of how links work in Explore once set up
diff --git a/docs/sources/administration/correlations/add-permissions-to-create-new-correlations/index.md b/docs/sources/administration/correlations/add-permissions-to-create-new-correlations/index.md
index 8dbca454cac..f232f26189c 100644
--- a/docs/sources/administration/correlations/add-permissions-to-create-new-correlations/index.md
+++ b/docs/sources/administration/correlations/add-permissions-to-create-new-correlations/index.md
@@ -12,7 +12,7 @@ weight: 30
## Before you begin
-Adding access to create correlations for [Viewers and Editors]({{< relref "../../../administration/roles-and-permissions" >}}) is available with [Role-based access control]({{< relref "../../../administration/roles-and-permissions/access-control" >}}).
+Adding access to create correlations for [Viewers and Editors](../../roles-and-permissions/) is available with [Role-based access control](../../roles-and-permissions/access-control/).
## Add permissions to create correlations
diff --git a/docs/sources/administration/correlations/correlation-configuration/index.md b/docs/sources/administration/correlations/correlation-configuration/index.md
index 56c21d89bc0..f01ef51d670 100644
--- a/docs/sources/administration/correlations/correlation-configuration/index.md
+++ b/docs/sources/administration/correlations/correlation-configuration/index.md
@@ -29,13 +29,13 @@ Each correlation is configured with the following options:
**Transformations**
: Optional manipulations to the source data included passed to the target query
-Learn how to create correlations using the [Administration page]({{< relref "./create-a-new-correlation#create-a-correlation-in-administration-page" >}}) or with [provisioning]({{< relref "./create-a-new-correlation#create-a-correlation-with-provisioning" >}}).
+Learn how to create correlations using the [Administration page](../create-a-new-correlation/#create-a-correlation-in-administration-page) or with [provisioning](../create-a-new-correlation/#create-a-correlation-with-provisioning).
## Source data source and result field
Links are shown in Explore visualizations for the results from the correlation’s source data source.
A link is assigned to one of the fields from the result provided in the correlation configuration (the results field).
-Each visualization displays fields with links in a different way ([Correlations in Logs Panel]({{< relref "./use-correlations-in-visualizations#correlations-in-logs-panel">}}) and see [Correlations in Table]({{< relref "./use-correlations-in-visualizations#correlations-in-table">}})).
+Each visualization displays fields with links in a different way ([Correlations in Logs Panel](../use-correlations-in-visualizations/#correlations-in-logs-panel) and see [Correlations in Table](../use-correlations-in-visualizations/#correlations-in-table)).
## Target query
@@ -44,10 +44,10 @@ The target query is run when a link is clicked in the visualization. You can use
### Correlation Variables
You can use variables inside the target query to access the source data related to the query.
-Correlations use [Grafana variable syntax]({{< relref "../../../dashboards/variables/variable-syntax" >}}).
+Correlations use [Grafana variable syntax](../../../dashboards/variables/variable-syntax/).
Variables are filled with values from the source results when the link is clicked. There are two types of variables you can use:
-- [field variables]({{< relref "../../../panels-visualizations/configure-data-links#field-variables" >}}) (allows to access field values and labels)
+- [field variables](../../../panels-visualizations/configure-data-links/#field-variables) (allows to access field values and labels)
- correlation variables (allows to access field values and transformations)
Example: If source results contain a field called “employee”, the value of the field can be accessed with:
@@ -57,9 +57,9 @@ Example: If source results contain a field called “employee”, the value of t
In addition to mapping field values to shorter variable names, more correlation variables can be created by applying transformations to existing fields
-For more details, please see the example in [Use variables and transformations in a correlation]({{< relref "./use-variables-and-transformations" >}}).
+For more details, please see the example in [Use variables and transformations in a correlation](../use-variables-and-transformations/).
-Correlation creates a data link only if all variables have values in the selected data row. [Global variables]({{< relref "/docs/grafana/latest/dashboards/variables/add-template-variables#global-variables" >}}) are exception to this rule and are not required to be filled in from the returned data. These variables are interpolated automatically by data sources.
+Correlation creates a data link only if all variables have values in the selected data row. [Global variables](/docs/grafana/latest/dashboards/variables/add-template-variables/#global-variables) are exception to this rule and are not required to be filled in from the returned data. These variables are interpolated automatically by data sources.
### Correlation Transformations
@@ -69,7 +69,7 @@ There are two types of transformations: logfmt and regular expression.
Each transformation uses a selected field value as the input. The output of a transformation is a set of new variables based on the type and options of the transformation.
-For more details, please see the example in [Use variables and transformations in a correlation]({{< relref "./use-variables-and-transformations" >}}) for more details.
+For more details, please see the example in [Use variables and transformations in a correlation](../use-variables-and-transformations/) for more details.
### Logfmt transformation
diff --git a/docs/sources/administration/correlations/correlation-permissions/index.md b/docs/sources/administration/correlations/correlation-permissions/index.md
index ee228d844fa..30984472c20 100644
--- a/docs/sources/administration/correlations/correlation-permissions/index.md
+++ b/docs/sources/administration/correlations/correlation-permissions/index.md
@@ -9,11 +9,11 @@ weight: 20
# Permissions
-Users with [Viewer base role]({{< relref "../../../administration/roles-and-permissions" >}}) or with [datasources:query RBAC role]({{< relref "../../../administration/roles-and-permissions/access-control" >}}) can:
+Users with [Viewer base role](../../roles-and-permissions/) or with [datasources:query RBAC role](../../roles-and-permissions/access-control/) can:
- Use correlations in Explore’s visualizations.
- List all available correlations in read-only mode.
-Users with [Admin base role]({{< relref "../../../administration/roles-and-permissions" >}}) or with [datasources:write RBAC role]({{< relref "../../../administration/roles-and-permissions/access-control" >}}) can:
+Users with [Admin base role](../../roles-and-permissions/) or with [datasources:write RBAC role](../../roles-and-permissions/access-control/) can:
- Add, edit and delete correlations.
diff --git a/docs/sources/administration/correlations/create-a-new-correlation/index.md b/docs/sources/administration/correlations/create-a-new-correlation/index.md
index 225d6ca8e1c..2ea3bb0b447 100644
--- a/docs/sources/administration/correlations/create-a-new-correlation/index.md
+++ b/docs/sources/administration/correlations/create-a-new-correlation/index.md
@@ -15,7 +15,7 @@ Make sure you have permission to add new correlations. Only users with write per
## Create a correlation in Explore's correlations editor
-To learn more, refer to Explore's [documentation]({{< relref "../../../explore/correlations-editor-in-explore" >}}) about building correlations in Explore.
+To learn more, refer to Explore's [documentation](../../../explore/correlations-editor-in-explore/) about building correlations in Explore.
## Create a correlation in Administration page
diff --git a/docs/sources/administration/correlations/use-correlations-in-visualizations/index.md b/docs/sources/administration/correlations/use-correlations-in-visualizations/index.md
index 4c98948ee3a..07070f27741 100644
--- a/docs/sources/administration/correlations/use-correlations-in-visualizations/index.md
+++ b/docs/sources/administration/correlations/use-correlations-in-visualizations/index.md
@@ -27,7 +27,7 @@ weight: 70
1. Open Explore.
1. Select a data source that you chose as the source data source of the correlation.
1. Run a query that results in data containing fields required to build variables in the target query.
-1. Links are added to cell rows in the column representing the field with the assigned link ([the results field]({{< relref "../correlation-configuration#source-data-source-and-result-field" >}}).
+1. Links are added to cell rows in the column representing the field with the assigned link ([the results field](../correlation-configuration/#source-data-source-and-result-field).
1. Cells containing multiple links accessible with a context menu.
{{< figure src="/static/img/docs/correlations/correlations-in-table-10-0.png" max-width="600px" caption="Correlations links in table" >}}
diff --git a/docs/sources/administration/correlations/use-variables-and-transformations/index.md b/docs/sources/administration/correlations/use-variables-and-transformations/index.md
index 6bc3668f9d8..6251d537352 100644
--- a/docs/sources/administration/correlations/use-variables-and-transformations/index.md
+++ b/docs/sources/administration/correlations/use-variables-and-transformations/index.md
@@ -73,7 +73,7 @@ Instructions below show how to set up a link that can run metrics query for the
- Required correlation type (query)
- Target query matching test data source model
- “App metrics” correlation contains the following configuration:
- - Alias is set to ${application} variable (note that in provisioning files $ is used to access environment variables so it has to be [escaped]({{< relref "../../../administration/provisioning#using-environment-variables" >}})).
+ - Alias is set to ${application} variable (note that in provisioning files $ is used to access environment variables so it has to be [escaped](../../provisioning/#using-environment-variables)).
- Regular expression transformation is created to extract values from “msg” field
- Regular expression transformation is used to capture the application name from the full name of the service stored in the log line.
- The output of the transformation is mapped to a variable called “application”.
diff --git a/docs/sources/administration/data-source-management/_index.md b/docs/sources/administration/data-source-management/_index.md
index 71c5d87d625..9eab6986e11 100644
--- a/docs/sources/administration/data-source-management/_index.md
+++ b/docs/sources/administration/data-source-management/_index.md
@@ -18,10 +18,10 @@ weight: 100
# Data source management
Grafana supports many different storage backends for your time series data (data source).
-Refer to [data sources]({{< relref "../../datasources" >}}) for more information about using data sources in Grafana.
+Refer to [data sources](../../datasources/) for more information about using data sources in Grafana.
Only users with the organization admin role can add data sources.
-For links to data source-specific documentation, see [Data sources]({{< relref "../../datasources" >}}).
+For links to data source-specific documentation, see [Data sources](../../datasources/).
## Data source permissions
@@ -32,7 +32,7 @@ You can configure data source permissions to allow or deny certain users the abi
- The `admin` permission allows users to query and edit the data source, change permissions on the data source and enable or disable query caching for the data source.
{{% admonition type="note" %}}
-Available in [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise/" >}}) and [Grafana Cloud](/docs/grafana-cloud).
+Available in [Grafana Enterprise](../../introduction/grafana-enterprise/) and [Grafana Cloud](/docs/grafana-cloud).
{{% /admonition %}}
By default, data sources in an organization can be queried by any user in that organization. For example, a user with the `Viewer` role can issue any possible query to a data source, not just queries that exist on dashboards to which they have access. Additionally, by default, data sources can be edited by the user who created the data source, as well as users with the `Admin` role.
@@ -80,10 +80,10 @@ When you enable query and resource caching, Grafana temporarily stores the resul
When using Grafana, a query pertains to a request for data frames to be modified or displayed. A resource relates to any HTTP requests made by a plugin, such as the Amazon Timestream plugin requesting a list of available databases from AWS. For more information on data source queries and resources, please see the developers page on [backend plugins](https://grafana.com/developers/plugin-tools/key-concepts/backend-plugins/).
-The caching feature works for **all** backend data sources. You can enable the cache globally in Grafana's [configuration]({{< relref "../../setup-grafana/configure-grafana/enterprise-configuration/#caching" >}}), and configure a cache duration (also called Time to Live, or TTL) for each data source individually.
+The caching feature works for **all** backend data sources. You can enable the cache globally in Grafana's [configuration](../../setup-grafana/configure-grafana/enterprise-configuration/#caching), and configure a cache duration (also called Time to Live, or TTL) for each data source individually.
{{% admonition type="note" %}}
-Available in [Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise/" >}}) and [Grafana Cloud](/docs/grafana-cloud/).
+Available in [Grafana Enterprise](../../introduction/grafana-enterprise/) and [Grafana Cloud](/docs/grafana-cloud/).
{{% /admonition %}}
The following cache backend options are available: in-memory, Redis, and Memcached.
@@ -94,9 +94,9 @@ Storing cached queries in-memory can increase Grafana's memory footprint. In pro
When a panel queries a data source with cached data, it will either fetch fresh data or use cached data depending on the panel's **interval.** The interval is used to round the query time range to a nearby cached time range, increasing the likelihood of cache hits. Therefore, wider panels and dashboards with shorter time ranges fetch new data more often than narrower panels and dashboards with longer time ranges.
-A panel's interval is visible in the [query options]({{< relref "../../panels-visualizations/query-transform-data/" >}}). It is calculated as follows: `time range / max data points`. Max data points are calculated based on the width of the panel. For example, a wide panel with `1000 data points` on a dashboard with a time range of `last 7 days` will retrieve fresh data every 10 minutes: `7d / 1000 = 10m`. In this example, cached data for this panel will be served for up to 10 minutes before Grafana needs to query the data source again for new data.
+A panel's interval is visible in the [query options](../../panels-visualizations/query-transform-data/). It is calculated as follows: `time range / max data points`. Max data points are calculated based on the width of the panel. For example, a wide panel with `1000 data points` on a dashboard with a time range of `last 7 days` will retrieve fresh data every 10 minutes: `7d / 1000 = 10m`. In this example, cached data for this panel will be served for up to 10 minutes before Grafana needs to query the data source again for new data.
-You can configure a panel to retrieve data more often by increasing the **Max data points** setting in the panel's [query options]({{< relref "../../panels-visualizations/query-transform-data/" >}}).
+You can configure a panel to retrieve data more often by increasing the **Max data points** setting in the panel's [query options](../../panels-visualizations/query-transform-data/).
### Caching benefits
@@ -108,7 +108,11 @@ By reducing the number of queries and requests sent to data sources, caching can
### Data sources that work with query caching
-Query caching works for Grafana's [built-in data sources]({{< relref "../../datasources/#built-in-core-data-sources" >}}), and [backend data source plugins](https://grafana.com/grafana/plugins/?type=datasource) that extend the `DataSourceWithBackend` class in the plugins SDK.
+Query caching works for Grafana's [built-in data sources](../../datasources/#built-in-core-data-sources), and [backend data source plugins](https://grafana.com/grafana/plugins/?type=datasource) that extend the `DataSourceWithBackend` class in the plugins SDK.
+
+{{% admonition type="note" %}}
+Logs Insights for the CloudWatch data source does not support query caching due to the way logs are requested from AWS.
+{{% /admonition %}}
To verify that a data source works with query caching, follow the [instructions below](#enable-and-configure-query-caching) to **Enable and Configure query caching**. If caching is enabled in Grafana but the Caching tab is not visible for the given data source, then query caching is not available for that data source.
@@ -118,7 +122,7 @@ Some data sources, such as Elasticsearch, Prometheus, and Loki, cache queries th
### Enable and configure query caching
-You must be an Org admin or Grafana admin to enable query caching for a data source. For more information on Grafana roles and permissions, refer to [About users and permissions]({{< relref "../roles-and-permissions/" >}}).
+You must be an Org admin or Grafana admin to enable query caching for a data source. For more information on Grafana roles and permissions, refer to [About users and permissions](../roles-and-permissions/).
By default, data source queries are not cached. To enable query caching for a single data source:
@@ -137,7 +141,7 @@ You can optionally override a data source's configured TTL for individual dashbo
If query caching is enabled and the Cache tab is not visible in a data source's settings, then query caching is not available for that data source.
{{% /admonition %}}
-To configure global settings for query caching, refer to the `caching` section of [Configure Grafana Enterprise]({{< relref "../../setup-grafana/configure-grafana/enterprise-configuration/#caching" >}}).
+To configure global settings for query caching, refer to the `caching` section of [Configure Grafana Enterprise](../../setup-grafana/configure-grafana/enterprise-configuration/#caching).
### Disable query caching
@@ -148,7 +152,7 @@ To disable query caching for a single data source:
1. In the data source list, click the data source that you want to turn off caching for.
1. On the Cache tab, click **Disable**.
-To disable query caching for an entire Grafana instance, set the `enabled` flag to `false` in the `caching` section of [Configure Grafana Enterprise]({{< relref "../../setup-grafana/configure-grafana/enterprise-configuration/#caching" >}}). You will no longer see the Cache tab on any data sources, and no data source queries will be cached.
+To disable query caching for an entire Grafana instance, set the `enabled` flag to `false` in the `caching` section of [Configure Grafana Enterprise](../../setup-grafana/configure-grafana/enterprise-configuration/#caching). You will no longer see the Cache tab on any data sources, and no data source queries will be cached.
### Clear cache
diff --git a/docs/sources/administration/data-source-management/teamlbac/_index.md b/docs/sources/administration/data-source-management/teamlbac/_index.md
index ac801cf9d18..4bf449af022 100644
--- a/docs/sources/administration/data-source-management/teamlbac/_index.md
+++ b/docs/sources/administration/data-source-management/teamlbac/_index.md
@@ -20,7 +20,18 @@ Label-Based Access Control (LBAC) allows fine-grained access control to data sou
## Supported Data Sources
-LBAC for data sources is currently available for `Loki, Prometheus` with basic authentication. Support for additional data sources may be added in future updates.
+### Feature availability
+
+LBAC for data sources is currently generally available for `Loki` and in **experimental** for `Prometheus`. Support for additional data sources may be added in future updates.
+
+| Data source | [Grafana Cloud](/docs/grafana-cloud) | [Grafana Enterprise](../../../introduction/grafana-enterprise/) |
+| ----------- | ------------------------------------ | --------------------------------------------------------------- |
+| Loki | GA | GA |
+| Prometheus | PrivatePreview | PrivatePreview |
+
+{{% admonition type="note" %}}
+For enterprise this feature requires Grafana Enterprise Metrics (GEM) or Grafana Enterprise Logs (GEL) to function.
+{{% /admonition %}}
**LBAC for data sources offers:**
@@ -28,11 +39,6 @@ LBAC for data sources is currently available for `Loki, Prometheus` with basic a
- Simplified data source management by consolidating multiple sources into one.
- Dashboard reuse across teams with tailored access.
-{{< admonition type="note" >}}
-LBAC rules is available for **private preview** in Grafana Cloud.
-Report any unexpected behavior to the Grafana Support team.
-{{< /admonition >}}
-
You can configure user access based upon team memberships using `LogQL`.
LBAC for data sources controls access to logs or metrics depending on the rules set for each team.
@@ -57,7 +63,7 @@ This flexibility allows teams to use the same data source for multiple use cases
## Before you begin
-To be able to use LBAC for data sources, you need to enable the feature toggle `teamHttpHeaders` on your Grafana instance.
+To be able to use LBAC for data sources metrics, you need to enable the feature toggle `teamHttpHeadersMimir` on your Grafana instance.
## Limitations
@@ -95,4 +101,4 @@ To set up LBAC for data sources for a data source, refer to [Configure LBAC for
## Provisioning of LBAC rules
-We recommend using our Terraform provider to set up provisioning for [Resource data source config LBAC rules] (https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/data_source_config_lbac_rules). Refer to our provider documentation to learn how to configure rules for a data source.
+We recommend using our Terraform provider to set up provisioning for [Resource data source config LBAC rules](https://registry.terraform.io/providers/grafana/grafana/latest/docs/resources/data_source_config_lbac_rules). Refer to our provider documentation to learn how to configure rules for a data source.
diff --git a/docs/sources/administration/data-source-management/teamlbac/configure-teamlbac-for-loki/index.md b/docs/sources/administration/data-source-management/teamlbac/configure-teamlbac-for-loki/index.md
index 0e5875eb26c..18a21b24ee8 100644
--- a/docs/sources/administration/data-source-management/teamlbac/configure-teamlbac-for-loki/index.md
+++ b/docs/sources/administration/data-source-management/teamlbac/configure-teamlbac-for-loki/index.md
@@ -19,8 +19,6 @@ You cannot configure LBAC rules for Grafana-provisioned data sources from the UI
## Before you begin
-To be able to use LBAC for data sources rules, you need to enable the feature toggle `teamHttpHeaders` on your Grafana instance. Contact support to enable the feature toggle for you.
-
- Be sure that you have the permission setup to create a Loki tenant in Grafana Cloud
- Be sure that you have admin data source permissions for Grafana.
diff --git a/docs/sources/administration/data-source-management/teamlbac/configure-teamlbac-for-prometheus/index.md b/docs/sources/administration/data-source-management/teamlbac/configure-teamlbac-for-prometheus/index.md
index aa54d970e6f..fa08b2f47cc 100644
--- a/docs/sources/administration/data-source-management/teamlbac/configure-teamlbac-for-prometheus/index.md
+++ b/docs/sources/administration/data-source-management/teamlbac/configure-teamlbac-for-prometheus/index.md
@@ -18,20 +18,26 @@ weight: 250
LBAC for data sources is available in private preview on Grafana Cloud for Prometheus created with basic authentication. Prometheus data sources for LBAC for data sources can only be created, provisioning is currently not available.
-You cannot configure LBAC rules for Grafana-provisioned data sources from the UI. Alternatively, you can replicate the setting of the provisioned data source in a new data source as described in [LBAC Configuration for New Prometheus Data Source](https://grafana.com/docs/grafana/latest/administration/data-source-management/teamlbac/configure-teamlbac-for-Prometheus/#task-1-lbac-configuration-for-new-Prometheus-data-source) and then add the LBAC configuration to the new data source.
+You cannot configure LBAC rules for Grafana-provisioned data sources from the UI. Alternatively, you can replicate the setting of the provisioned data source in a new data source as described in [LBAC Configuration for New Prometheus Data Source](#task-1-lbac-configuration-for-new-prometheus-data-source) and then add the LBAC configuration to the new data source.
## Before you begin
-To be able to use LBAC for data sources rules, you need to enable the feature toggle `teamHttpHeaders` on your Grafana instance. Contact support to enable the feature toggle for you.
+To be able to use LBAC for Prometheus data sources, you need to enable the feature toggle `teamHttpHeadersMimir` on your Grafana instance. Contact support to enable the feature toggle for you.
- Be sure that you have the permission setup to create a Prometheus tenant in Grafana Cloud
- Be sure that you have admin data source permissions for Grafana.
+## Grafana Cloud
+
+LBAC for data sources is available in private preview on Grafana Cloud for Prometheus created with basic authentication. Prometheus data sources for LBAC for data sources can only be created, provisioning is currently not available.
+
+You cannot configure LBAC rules for Grafana-provisioned data sources from the UI. We recommend that you replicate the setting of the provisioned data source in a new data source as described in [LBAC Configuration for New Prometheus Data Source](#task-1-lbac-configuration-for-new-prometheus-data-source) and then add the LBAC configuration to the new data source.
+
### Permissions
We recommend that you remove all permissions for roles and teams that are not required to access the data source. This will help to ensure that only the required teams have access to the data source. The recommended permissions are `Admin` permission and only add the teams `Query` permissions that you want to add LBAC for data sources rules for.
-## Task 1: LBAC Configuration for New Prometheus Data Source
+## Task 1: LBAC Configuration for new Prometheus data source
1. Access Prometheus data sources details for your stack through grafana.com
1. Copy Prometheus details and create a CAP
@@ -53,11 +59,11 @@ For more information on how to setup LBAC for data sources rules for a Prometheu
LBAC for data sources is available in Grafana Enterprise for Prometheus created with basic authentication. Prometheus data sources for LBAC for data sources can only be created.
-You cannot configure LBAC rules for Grafana-provisioned data sources from the UI. Alternatively, you can replicate the setting of the provisioned data source in a new data source as described in [LBAC Configuration for New Prometheus Data Source](https://grafana.com/docs/grafana/latest/administration/data-source-management/teamlbac/configure-teamlbac-for-Prometheus/#task-1-lbac-configuration-for-new-Prometheus-data-source) and then add the LBAC configuration to the new data source.
+You cannot configure LBAC rules for Grafana-provisioned data sources from the UI. Alternatively, you can replicate the setting of the provisioned data source in a new data source as described in [LBAC Configuration for new Prometheus data source](https://grafana.com/docs/grafana//administration/data-source-management/teamlbac/configure-teamlbac-for-prometheus/#task-1-lbac-configuration-for-new-prometheus-data-source) and then add the LBAC configuration to the new data source.
## Before you begin
-To be able to use LBAC for data sources rules, you need to enable the feature toggle `teamHttpHeaders` on your Grafana instance. Contact support to enable the feature toggle for you.
+To be able to use LBAC for Prometheus data sources, you need to enable the feature toggle `teamHttpHeadersMimir` on your Grafana instance. Contact support to enable the feature toggle for you.
- Be sure that you have the permission setup to create a cluster in your Grafana
- Be sure that you have admin plugins permissions for Grafana.
@@ -79,7 +85,7 @@ We recommend that you remove all permissions for roles and teams that are not re
- Ensure the CAP does not include `labels` rules.
- Store the `token` to be used as password for authentication.
-## Task 1: LBAC Configuration for New Prometheus Data Source
+## Task 1: LBAC Configuration for new Prometheus data source
1. Create a new Prometheus data source
- In Grafana, proceed to add a new data source and select Prometheus as the type.
diff --git a/docs/sources/administration/data-source-management/teamlbac/create-teamlbac-rules/index.md b/docs/sources/administration/data-source-management/teamlbac/create-teamlbac-rules/index.md
index 3942490c0ff..f76dd3d64bb 100644
--- a/docs/sources/administration/data-source-management/teamlbac/create-teamlbac-rules/index.md
+++ b/docs/sources/administration/data-source-management/teamlbac/create-teamlbac-rules/index.md
@@ -17,8 +17,6 @@ LBAC for data sources is available for LBAC-supported data sources created with
## Before you begin
-To be able to use LBAC for data sources rules, you need to enable the feature toggle `teamHttpHeaders` on your Grafana instance. Contact support to enable the feature toggle for you.
-
- Be sure that you have the permission setup to create a Loki tenant in Grafana Cloud.
- Be sure that you have admin data source permissions for Grafana.
- Be sure that you have a team setup in Grafana.
diff --git a/docs/sources/administration/enterprise-licensing/_index.md b/docs/sources/administration/enterprise-licensing/_index.md
index 131ec8d0f79..31fbf6027a3 100644
--- a/docs/sources/administration/enterprise-licensing/_index.md
+++ b/docs/sources/administration/enterprise-licensing/_index.md
@@ -23,11 +23,11 @@ weight: 500
# Grafana Enterprise license
-When you become a Grafana Enterprise customer, you gain access to Grafana's premium observability features, including enterprise data source plugins, reporting, and role-based access control. In order to use these [enhanced features of Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise" >}}), you must purchase and activate a Grafana Enterprise license.
+When you become a Grafana Enterprise customer, you gain access to Grafana's premium observability features, including enterprise data source plugins, reporting, and role-based access control. In order to use these [enhanced features of Grafana Enterprise](../../introduction/grafana-enterprise/), you must purchase and activate a Grafana Enterprise license.
-To purchase a license directly from Grafana Labs, [Contact a Grafana Labs representative](/contact?about=grafana-enterprise). To activate an Enterprise license purchased from Grafana Labs, refer to [Activate an Enterprise license]({{< relref "#activate-an-enterprise-license" >}}).
+To purchase a license directly from Grafana Labs, [Contact a Grafana Labs representative](/contact?about=grafana-enterprise). To activate an Enterprise license purchased from Grafana Labs, refer to [Activate an Enterprise license](#activate-an-enterprise-license).
-You can also purchase a Grafana Enterprise license through the AWS Marketplace. To learn more about activating a license purchased through AWS, refer to [Activate a Grafana Enterprise license purchased through AWS Marketplace]({{< relref "./activate-aws-marketplace-license/" >}}).
+You can also purchase a Grafana Enterprise license through the AWS Marketplace. To learn more about activating a license purchased through AWS, refer to [Activate a Grafana Enterprise license purchased through AWS Marketplace](activate-aws-marketplace-license/).
{{< section >}}
@@ -94,9 +94,9 @@ environment variable.
### Step 3. Ensure that the license file's root URL matches the root_url configuration option
-Update the [`root_url`]({{< relref "../../setup-grafana/configure-grafana/#root_url" >}}) in your configuration. It should be the URL that users type in their browsers to access the frontend, not the node hostname(s).
+Update the [`root_url`](../../setup-grafana/configure-grafana/#root_url) in your configuration. It should be the URL that users type in their browsers to access the frontend, not the node hostname(s).
-This is important, because as part of the validation checks at startup, Grafana compares the license URL to the [`root_url`]({{< relref "../../setup-grafana/configure-grafana/#root_url" >}}) in your configuration.
+This is important, because as part of the validation checks at startup, Grafana compares the license URL to the [`root_url`](../../setup-grafana/configure-grafana/#root_url) in your configuration.
In your configuration file:
@@ -113,7 +113,7 @@ GF_SERVER_ROOT_URL=https://grafana.example.com/
### Step 4. Restart Grafana
-To finalize the installation of Grafana Enterprise, restart Grafana to enable all Grafana Enterprise features. Refer to [restart Grafana]({{< relref "../../setup-grafana/start-restart-grafana/" >}}) for more information.
+To finalize the installation of Grafana Enterprise, restart Grafana to enable all Grafana Enterprise features. Refer to [restart Grafana](../../setup-grafana/start-restart-grafana/) for more information.
## License expiration
@@ -123,7 +123,7 @@ If your license has expired, most of Grafana keeps working as normal. Some enter
### Update your license
-1. Locate your current `license.jwt` file. In a standard installation it is stored inside the Grafana data directory, which on a typical Linux installation is in `/var/lib/grafana/data`. This location might be overridden in the ini file [Configuration]({{< relref "../../setup-grafana/configure-grafana/" >}}).
+1. Locate your current `license.jwt` file. In a standard installation it is stored inside the Grafana data directory, which on a typical Linux installation is in `/var/lib/grafana/data`. This location might be overridden in the ini file [Configuration](../../setup-grafana/configure-grafana/).
```ini
[enterprise]
@@ -135,7 +135,7 @@ If your license has expired, most of Grafana keeps working as normal. Some enter
2. Log in to your [Grafana Cloud Account](/login) and make sure you're in the correct organization in the dropdown at the top of the page.
3. Under the **Grafana Enterprise** section in the menu bar to the left, choose licenses and download the currently valid license with which you want to run Grafana. If you cannot see a valid license on Grafana.com, please contact your account manager at Grafana Labs to renew your subscription.
4. Replace the current `license.jwt`-file with the one you've just downloaded.
-5. [Restart Grafana]({{< relref "../../setup-grafana/start-restart-grafana/" >}}).
+5. [Restart Grafana](../../setup-grafana/start-restart-grafana/).
### If your license expires
@@ -244,11 +244,19 @@ Your license is controlled by the following rules:
**License expiration date:** The license includes an expiration date, which is the date when a license becomes inactive.
-As the license expiration date approaches, you will see a banner in Grafana that encourages you to renew. To learn about how to renew your license and what happens in Grafana when a license expires, refer to [License expiration]({{< relref "#license-expiration" >}}).
+As the license expiration date approaches, you will see a banner in Grafana that encourages you to renew. To learn about how to renew your license and what happens in Grafana when a license expires, refer to [License expiration](#license-expiration).
+
+**License token expiration:** Grafana Enterprise requires a valid token, which is automatically renewed.
+
+A license token is a digital key that activates your license. By default, the license token is renewed every 24 hours by calling the Grafana API. Short-lived license tokens enable more frequent validation that licenses are compliant, and allow for more frequent license updates - for example, adding users or invalidating a compromised license.
+
+To view the details of your license token, sign in to Grafana Enterprise as a Server Administrator and visit **Administration** > **General** > **Statistics and licensing**. Token details are in the Token section under License Details.
+
+License token renewal requires internet access, and requires that the `auto_refresh_license` [configuration setting](https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/enterprise-configuration/#auto_refresh_license) be set to `true`. If your Grafana Enterprise instance cannot connect to the internet, contact your Grafana Labs account team for additional options for token renewal and license audit.
**Grafana License URL:** Your license does not work with an instance of Grafana with a different root URL.
-The License URL is the complete URL of your Grafana instance, for example `https://grafana.your-company.com/`. It is defined in the [root_url]({{< relref "../../setup-grafana/configure-grafana/#root_url" >}}) configuration setting.
+The License URL is the complete URL of your Grafana instance, for example `https://grafana.your-company.com/`. It is defined in the [root_url](../../setup-grafana/configure-grafana/#root_url) configuration setting.
**Concurrent sessions limit**: As of Grafana Enterprise 7.5, users can initiate up to three concurrent sessions of Grafana.
@@ -256,14 +264,24 @@ The system creates a session when a user signs in to Grafana from a new device,
When a user reaches the session limit, the fourth connection succeeds and the longest inactive session is signed out.
-### Request usage billing
-
-You can request Grafana Labs to activate usage billing which allows an unlimited number of active users. When usage billing is enabled, Grafana does not enforce active user limits or display warning banners. Instead, you are charged for active users that exceed the limit, according to your customer contract.
-
-Usage billing involves a contractual agreement between you and Grafana Labs, and it is only available if Grafana Enterprise is configured to [automatically refresh its license token]({{< relref "../../setup-grafana/configure-grafana/enterprise-configuration/#auto_refresh_license" >}}).
-
### Request a change to your license
To increase the number of licensed users within Grafana, extend a license, or change your licensed URL, contact [Grafana support](/profile/org#support) or your Grafana Labs account team. They will update your license, which you can activate from within Grafana.
-For instructions about how to activate your license after it is updated, refer to [Activate an Enterprise license]({{< relref "#activate-an-enterprise-license" >}}).
+For instructions about how to activate your license after it is updated, refer to [Activate an Enterprise license](#activate-an-enterprise-license).
+
+## Usage billing
+
+Standard Grafana Enterprise licenses include a certain number of seats that can be used, and prevent more users logging into Grafana than have been licensed. This makes sense if you prefer a predictable bill. It can however be a problem if you anticipate uneven usage patterns over time or when it's critical that no user ever be prevented from logging in to Grafana due to capacity constraints.
+
+For those use-cases we support usage-based billing, where your license includes a certain number of included users and you are billed on a monthly basis for any excess active users during the month.
+
+Usage billing involves a contractual agreement between you and Grafana Labs and an update to your license, and it is only available if Grafana Enterprise version 10.0.0 or higher is configured to [automatically refresh its license token](../../setup-grafana/configure-grafana/enterprise-configuration/#auto_refresh_license).
+
+### User deduplication
+
+If your organization has multiple Grafana Enterprise instances with usage billing enabled, then each active user counts only once toward your license, regardless of how many instances that user signs into. Each Grafana Enterprise instance submits a hashed list of users to Grafana Labs via API every day. Each user email address or anonymous device ID is hashed using a one-way sha256 algorithm, and submitted to Grafana where the hashed users are deduplicated across instances.
+
+### Request usage billing
+
+To request usage billing, contact your Grafana Labs account team or [submit a support ticket](https://grafana.com/profile/org#support).
diff --git a/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/_index.md b/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/_index.md
index 2ecc592a76d..4ac9e4814be 100644
--- a/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/_index.md
+++ b/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/_index.md
@@ -30,7 +30,7 @@ You can deploy Grafana Enterprise in the following ways:
- Using AWS services like ECS, EKS or EC2.
- In an instance outside AWS.
-In each case, you must activate the Grafana Enterprise license purchased in AWS Marketplace to take advantage of Grafana Enterprise observability features. Grafana Enterprise licenses purchased through AWS Marketplace are subject to the same [restrictions]({{< relref "../#license-restrictions" >}}) as Grafana Enterprise licensed purchased directly from Grafana Labs.
+In each case, you must activate the Grafana Enterprise license purchased in AWS Marketplace to take advantage of Grafana Enterprise observability features. Grafana Enterprise licenses purchased through AWS Marketplace are subject to the same [restrictions](../#license-restrictions) as Grafana Enterprise licensed purchased directly from Grafana Labs.
> To purchase a license directly from Grafana Labs or learn more about other Grafana offerings, [Contact a Grafana Labs representative](/contact?about=grafana-enterprise).
diff --git a/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/activate-license-on-ecs/index.md b/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/activate-license-on-ecs/index.md
index 5d3858c25cc..c9192e585e6 100644
--- a/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/activate-license-on-ecs/index.md
+++ b/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/activate-license-on-ecs/index.md
@@ -48,7 +48,7 @@ Grafana requires that you configure a database to hold dashboards, users, and ot
### Before you begin
- Ensure that you have a supported Grafana database available.
- - For a list of supported databases, refer to [Supported databases]({{< relref "../../../../setup-grafana/installation/#supported-databases" >}}).
+ - For a list of supported databases, refer to [Supported databases](../../../../setup-grafana/installation/#supported-databases).
- For information about creating a database, refer to [Creating an Amazon RDS DB instance](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_CreateDBInstance.html).
- Review the information required to connect to the RDS DB instance. For more information, refer to [Connecting to an Amazon RDS DB instance](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_CommonTasks.Connect.html).
@@ -56,7 +56,7 @@ To configure Grafana for high availability:
1. In AWS ECS, use environment variables to update the `database` parameters.
- For a list of database parameters, refer to [Configuration]({{< relref "../../../../setup-grafana/configure-grafana/#database" >}}).
+ For a list of database parameters, refer to [Configuration](../../../../setup-grafana/configure-grafana/#database).
1. Create a revision of the task definition for the ECS Task that runs Grafana Enterprise.
@@ -114,4 +114,4 @@ In this task you configure Grafana Enterprise to validate the license with AWS i
1. To restart Grafana and activate your license, update the service running Grafana to use the latest revision of the task definition that you created.
1. After you update the service, navigate to your Grafana instance, sign in with Grafana Admin credentials, and navigate to **Administration > General > Stats and license** to validate that your license is active.
-For more information about validating that your license is active, refer to [Grafana Enterprise license restrictions]({{< relref "../../#grafana-enterprise-license-restrictions" >}}).
+For more information about validating that your license is active, refer to [Grafana Enterprise license restrictions](../../#grafana-enterprise-license-restrictions).
diff --git a/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/activate-license-on-eks/index.md b/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/activate-license-on-eks/index.md
index a5698448447..5199690faa3 100644
--- a/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/activate-license-on-eks/index.md
+++ b/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/activate-license-on-eks/index.md
@@ -50,7 +50,7 @@ Grafana requires that you configure a database to hold dashboards, users, and ot
### Before you begin
- Ensure that you have a supported Grafana database available.
- - For a list of supported databases, refer to [Supported databases]({{< relref "../../../../setup-grafana/installation/#supported-databases" >}}).
+ - For a list of supported databases, refer to [Supported databases](../../../../setup-grafana/installation/#supported-databases).
- For information about creating a database, refer to [Creating an Amazon RDS DB instance](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_CreateDBInstance.html).
- Review the information required to connect to the RDS DB instance. For more information, refer to [Connecting to an Amazon RDS DB instance](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_CommonTasks.Connect.html).
@@ -82,7 +82,7 @@ To configure Grafana for high availability, choose **one** of the following opti
value: [database password]
```
-For more information on Grafana High Availability setup, refer to [Set up Grafana for high availability]({{< relref "../../../../setup-grafana/set-up-for-high-availability/" >}}).
+For more information on Grafana High Availability setup, refer to [Set up Grafana for high availability](../../../../setup-grafana/set-up-for-high-availability/).
## Task 3: Configure Grafana Enterprise to validate its license with AWS
@@ -99,7 +99,7 @@ In this task, you configure Grafana Enterprise to validate the license with AWS
For more information about AWS license permissions, refer to [Actions, resources, and condition keys for AWS License Manager](https://docs.aws.amazon.com/service-authorization/latest/reference/list_awslicensemanager.html).
-1. Choose **one** of the following options to update the [license_validation_type]({{< relref "../../../../setup-grafana/configure-grafana/enterprise-configuration/#license_validation_type" >}}) configuration to `aws`:
+1. Choose **one** of the following options to update the [license_validation_type](../../../../setup-grafana/configure-grafana/enterprise-configuration/#license_validation_type) configuration to `aws`:
- **Option 1:** Use `kubectl edit configmap grafana` to edit `grafana.ini` add the following section to the configuration:
@@ -125,6 +125,6 @@ To restart Grafana on a Kubernetes cluster,
1. After you update the service, navigate to your Grafana instance, sign in with Grafana Admin credentials, and navigate to **Administration > General > Stats and license** to validate that your license is active.
-For more information about restarting Grafana, refer to [Restart Grafana]({{< relref "../../../../setup-grafana/start-restart-grafana/" >}}).
+For more information about restarting Grafana, refer to [Restart Grafana](../../../../setup-grafana/start-restart-grafana/).
> If you experience issues when you update the EKS cluster, refer to [Amazon EKS troubleshooting](https://docs.aws.amazon.com/eks/latest/userguide/troubleshooting.html).
diff --git a/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/activate-license-on-instance-outside-aws/index.md b/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/activate-license-on-instance-outside-aws/index.md
index a205673c676..9d1741d94a4 100644
--- a/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/activate-license-on-instance-outside-aws/index.md
+++ b/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/activate-license-on-instance-outside-aws/index.md
@@ -35,9 +35,9 @@ To activate a Grafana Enterprise license from AWS on a Grafana Enterprise instan
To install Grafana, refer to the documentation specific to your implementation.
-- [Install Grafana]({{< relref "../../../../setup-grafana/installation/" >}}).
-- [Run Grafana Docker image]({{< relref "../../../../setup-grafana/installation/docker/" >}}).
-- [Deploy Grafana on Kubernetes]({{< relref "../../../../setup-grafana/installation/kubernetes/#deploy-grafana-enterprise-on-kubernetes" >}}).
+- [Install Grafana](../../../../setup-grafana/installation/).
+- [Run Grafana Docker image](../../../../setup-grafana/installation/docker/).
+- [Deploy Grafana on Kubernetes](../../../../setup-grafana/installation/kubernetes/#deploy-grafana-enterprise-on-kubernetes).
## Task 2: Create an AWS IAM user with access to your Grafana Enterprise license
@@ -110,7 +110,7 @@ To retrieve your license, Grafana Enterprise requires access to your AWS account
In this task you configure Grafana Enterprise to validate the license with AWS instead of Grafana Labs.
-Choose one of the following options to update the [license_validation_type]({{< relref "../../../../setup-grafana/configure-grafana/enterprise-configuration/#license_validation_type" >}}) configuration to `aws`:
+Choose one of the following options to update the [license_validation_type](../../../../setup-grafana/configure-grafana/enterprise-configuration/#license_validation_type) configuration to `aws`:
- **Option 1:** In the `[enterprise]` section of the grafana.ini configuration file, add `license_validation_type=aws`.
@@ -131,4 +131,4 @@ Choose one of the following options to update the [license_validation_type]({{<
To activate Grafana Enterprise features, start (or restart) Grafana.
-For information about restarting Grafana, refer to [Restart Grafana]({{< relref "../../../../setup-grafana/start-restart-grafana/" >}}).
+For information about restarting Grafana, refer to [Restart Grafana](../../../../setup-grafana/start-restart-grafana/).
diff --git a/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/manage-license-in-aws-marketplace/index.md b/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/manage-license-in-aws-marketplace/index.md
index 56ba176742d..47988bf8a14 100644
--- a/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/manage-license-in-aws-marketplace/index.md
+++ b/docs/sources/administration/enterprise-licensing/activate-aws-marketplace-license/manage-license-in-aws-marketplace/index.md
@@ -42,4 +42,4 @@ You can use AWS Marketplace to make the following modifications to your Grafana
This action retrieves updated license information from AWS.
-> To learn more about licensing and active users, refer to [Activate a Grafana Enterprise license purchased through AWS Marketplace]({{< relref "../" >}}).
+> To learn more about licensing and active users, refer to [Activate a Grafana Enterprise license purchased through AWS Marketplace](../).
diff --git a/docs/sources/administration/feature-toggles/index.md b/docs/sources/administration/feature-toggles/index.md
index 90d08353bec..b79d62fbede 100644
--- a/docs/sources/administration/feature-toggles/index.md
+++ b/docs/sources/administration/feature-toggles/index.md
@@ -19,7 +19,7 @@ For detailed information about particular features and how they operate, refer t
## Manage feature toggles
In the **Administration** page, the **Feature Management** section enables authorized users to view and edit the various features that are active in their Grafana environment.
-Authorized users include administrators, and users with the [fixed roles]({{< relref "../roles-and-permissions/access-control#fixed-roles" >}}) `featuremgmt.read` and `featuremgmt.write`.
+Authorized users include administrators, and users with the [fixed roles](../roles-and-permissions/access-control/#fixed-roles) `featuremgmt.read` and `featuremgmt.write`.
There are different options for visibility and customization depending on the development stage of the feature.
diff --git a/docs/sources/administration/migration-guide/_index.md b/docs/sources/administration/migration-guide/_index.md
new file mode 100644
index 00000000000..deb7de8c533
--- /dev/null
+++ b/docs/sources/administration/migration-guide/_index.md
@@ -0,0 +1,23 @@
+---
+aliases:
+ - /docs/grafana-cloud/account-management/e2c-guide/
+ - /docs/grafana-cloud/account-management/migration-guide/
+description: Migrate from Grafana OSS/Enterprise to Grafana Cloud
+keywords:
+ - Grafana Cloud
+ - Grafana Enterprise
+ - Grafana OSS
+menuTitle: Migrate from Grafana OSS/Enterprise to Grafana Cloud
+title: Migrate from Grafana OSS/Enterprise to Grafana Cloud
+---
+
+# Migrate from Grafana OSS/Enterprise to Grafana Cloud
+
+When you decide to migrate from your self-managed Grafana instance to Grafana Cloud, you can benefit from the convenience of a managed observability platform, additional cloud-only features, and robust security. There are a couple of key approaches to help you transition to Grafana Cloud.
+
+| Migration type | Tools used | Availability | Migratable resources |
+| :------------- | :-------------------------------------------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Manual | - Command line utilities
- The Grafana HTTP API
| Generally available in all versions of Grafana OSS/Enterprise | The entire Grafana instance |
+| Automated | The Grafana Cloud Migration Assistant | Available in public preview from Grafana v11.2 using the `onPremToCloudMigrations` feature toggle. This toggle is enabled by default in Grafana v11.5 and later. | - Dashboards
- Folders
- Data sources
- App Plugins
- Panel Plugins
- Library Panels
- Grafana Alerting resources
|
+
+Our detailed [migration guide](https://www.grafana.com/docs/grafana-cloud/account-management/migration-guide/manually-migrate-to-grafana-cloud/) explains the key steps and scripts to manually migrate your resources to Grafana Cloud, covering a comprehensive set of resources in your Grafana instance. Alternatively, the [Grafana Cloud Migration Assistant](https://www.grafana.com/docs/grafana-cloud/account-management/migration-guide/cloud-migration-assistant/), available in public preview in Grafana v11.2 and later, automates the migration process across a broad range of Grafana resources. You can use the migration assistant to migrate a large proportion of your Grafana resources and then, if needed, leverage the migration guide to migrate the rest.
diff --git a/docs/sources/administration/migration-guide/cloud-migration-assistant.md b/docs/sources/administration/migration-guide/cloud-migration-assistant.md
new file mode 100644
index 00000000000..5e1e1b0b423
--- /dev/null
+++ b/docs/sources/administration/migration-guide/cloud-migration-assistant.md
@@ -0,0 +1,201 @@
+---
+description: Migrate from Grafana OSS/Enterprise to Grafana Cloud using the Grafana Cloud Migration Assistant
+keywords:
+ - Grafana Cloud
+ - Grafana Enterprise
+ - Grafana OSS
+menuTitle: Migrate to Grafana Cloud using the Grafana Cloud Migration Assistant
+title: Migrate from Grafana OSS/Enterprise to Grafana Cloud using the Grafana Cloud Migration Assistant
+weight: 400
+---
+
+# Grafana Cloud Migration Assistant
+
+The Grafana Cloud Migration Assistant is available in Grafana 11.2+ as a [public preview feature](https://grafana.com/docs/release-life-cycle/#public-preview) that automatically migrates resources from your Grafana OSS/Enterprise instance to Grafana Cloud. It provides the following functionalities:
+
+- Securely connect your self-managed instance to a Grafana Cloud instance.
+- Seamlessly migrate resources such as dashboards, data sources, and folders to your cloud instance in a few easy steps.
+- View the migration status of your resources in real-time.
+
+Some of the benefits of the migration assistant are:
+
+Ease of use
+: Follow the steps provided by the UI to easily migrate all your resources to Grafana Cloud without using Grafana APIs or scripts.
+
+Security
+: Encrypt and securely migrate your resources to your connected Grafana Cloud instance.
+
+Speed
+: Migrate all of your resources in minutes and accelerate your transition to Grafana Cloud.
+
+## Supported resources
+
+The following resources are supported by the migration assistant:
+
+- Dashboards
+- Folders
+- Data sources
+- App Plugins
+- Panel Plugins
+- Library Panels
+- Grafana Alerting resources
+
+## Before you begin
+
+To use the Grafana migration assistant, you need:
+
+- Grafana v11.2 or above with the `onPremToCloudMigrations` feature toggle enabled. In Grafana 11.5, this is enabled by default. For more information on how to enable a feature toggle, refer to [Configure feature toggles](https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/feature-toggles/#configure-feature-toggles).
+- A [Grafana Cloud Stack](https://grafana.com/docs/grafana-cloud/get-started/) you intend to migrate your resources to.
+- [`Admin`](https://grafana.com/docs/grafana-cloud/account-management/authentication-and-permissions/cloud-roles/) access to the Grafana Cloud Stack. To check your access level, go to `https://grafana.com/orgs//members`.
+- [Grafana server administrator](https://grafana.com/docs/grafana/latest/administration/roles-and-permissions/#grafana-server-administrators) access to your existing Grafana OSS/Enterprise instance. To check your access level, go to `https:///admin/users`.
+- Internet access from your existing Grafana OSS/Enterprise instance.
+
+## Access the migration assistant
+
+In Grafana OSS, access to the migration assistant is limited to the server administrator.
+
+In Grafana Enterprise, the server administrator has access to the migration assistant by default. It is also possible to grant access to other Admins using a role-based access control (RBAC) role that enables other admins on the Grafana instance to view, build snapshots, and upload resources to Grafana Cloud.
+
+### Grant access in Grafana Enterprise
+
+{{< admonition type="important">}}
+You must [configure RBAC](https://grafana.com/docs/grafana/latest/administration/roles-and-permissions/access-control/configure-rbac/) before you can grant other administrators access to the Grafana Migration Assistant.
+{{< /admonition >}}
+
+To grant other Admins access to the migration assistant in Grafana Enterprise:
+
+1. Sign in to Grafana as a server administrator.
+1. Navigate to **Home** > **Administration** > **Users and access** > **Users** in the Grafana sidebar.
+1. Click an Admin.
+1. In the **Organizations** section, click **Change role**.
+1. Select **Organization resource migrator** from the role selector menu under **Migration Assistant**.
+
+ 
+
+1. Click **Apply**.
+
+## Use the migration assistant
+
+You can use the migration assistant to generate a migration token on your Grafana Cloud instance, use that token to connect your self-managed Grafana instance to your Grafana Cloud instance, build snapshots of your self-managed Grafana instance, and upload these snapshots to Grafana Cloud.
+
+### Generate a migration token on the destination cloud instance:
+
+1. Navigate to **Home** > **Administration** > **General** > **Migrate to Grafana Cloud** in the cloud instance where you intend to migrate your resources.
+1. Click on the **Generate a migration token** button.
+
+ 
+
+1. Make a copy of the migration token by copying to clipboard. The token is required to authenticate your self-managed instance with the Grafana Cloud Stack.
+
+### Connect your self-managed Grafana instance to the Grafana Cloud Stack
+
+1. On your self-managed Grafana instance, navigate to **Home** > **Administration** > **General** > **Migrate to Grafana Cloud**.
+
+1. Click the **Migrate this instance to Cloud** button.
+
+ 
+
+1. Enter your token and click **Connect to this Stack**.
+
+ 
+
+### Build a snapshot
+
+After connecting to the cloud stack, this is the empty state of the migration assistant. You need to create a snapshot of the self-managed Grafana instance to upload it to the cloud stack.
+
+- Click **Build snapshot**
+
+ 
+
+### Upload resources to the cloud
+
+After a snapshot is created, a list of resources appears with resource Type and Status populated with **Not yet uploaded**.
+
+
+
+1. Click on **Upload snapshot** to copy the resources to the Grafana Cloud instance. This also updates statuses for the list of resources. The status changes to 'Uploaded to cloud' for resources successfully copied to the cloud.
+
+ The Snapshot information also updates to inform the user of total resources, errors, and total number of successfully migrated resources.
+
+ 
+
+1. Use the assistant's real-time progress tracking to monitor the migration.
+
+1. Review error details for any issues that need manual resolution.
+
+## Snapshots created by the migration assistant
+
+The migration assistant currently supports a subset of all resources available in Grafana. Refer to [Supported Resources](https://wwww.grafana.com/docs/grafana-cloud/account-management/cloud-migration-assistant/#supported-resources) for more details.
+
+When you create a snapshot, the migration assistant makes a copy of all supported resources and saves them in the snapshot. The snapshot reflects the current state of the resources when the snapshot is built and is stored locally on your instance, ready to be uploaded in the last stage. It is currently not possible to select specific resources to include in the snapshot, such as only dashboards. All supported resources are included by default.
+
+Resources saved in the snapshot are strictly limited to the resources stored within an organization. This is important to note if there are multiple organizations used in your Grafana instance. If you want to migrate multiple organizations, refer to [Migrate multiple organizations](https://wwww.grafana.com/docs/grafana-cloud/account-management/cloud-migration-assistant/#migrate-multiple-organizations) for more information and guidance.
+
+## Resource migration details
+
+During a migration, resource UIDs are preserved, allowing you to correlate your local and cloud resources. If you perform the same migration multiple times, resources in your Grafana Cloud stack that were previously migrated are updated. The assistant never modifies your self-managed resources or cloud resources that didn't come from a snapshot.
+
+### Dashboards and folders
+
+Dashboard names and UIDs are preserved along with references to data sources. Folder hierarchy is also preserved, so you can find your dashboards and other resources saved in identical folder locations.
+
+### Data sources
+
+Your data sources, including credentials, are migrated securely and seamlessly to your Grafana Cloud instance, so you don't need to find and enter all your data source credentials again.
+
+### Plugins
+
+The migration assistant supports any plugins found in the plugins catalog. As long as the plugin is signed or is a core plugin built into Grafana, it is eligible for migration. Due to security reasons, unsigned plugins are not supported in Grafana Cloud. If you are using any unsigned private plugins, Grafana recommends you seek an alternative plugin for the catalog or work on a strategy to deprecate certain functionality from your self-managed instance.
+
+Upgrade any plugins you intend to migrate before using the migration assistant as any migrated plugins will be configured on the Grafana Cloud instance as the latest version of that plugin.
+
+{{< admonition type="caution">}}
+If you want to migrate Enterprise plugins, check what type of plan your Grafana Cloud instance is on and whether or not this plan requires an Enterprise plugin add-on.
+{{< /admonition >}}
+
+### Grafana Alerting resources
+
+The migration assistant can migrate the majority of Grafana Alerting resources to your Grafana Cloud instance. These include:
+
+- Alert rules
+- Notifications
+- Contact points
+- Mute timings
+- Notification policy tree
+- Notification templates
+
+This is sufficient to have your Alerting configuration up and running in Grafana Cloud with minimal effort.
+
+Migration of Silences is not supported by the migration assistant and needs to be configured manually. Alert History is also not available for migration.
+
+Successfully migrating Alerting resources to your Grafana Cloud instance could result in 2 sets of notifications being generated; one from your OSS/Enterprise instance and another from the newly migrated alerts in your Grafana Cloud instance. To avoid double notifications, a new `alert_rules_state` configuration option in the `custom.ini` or `grafana.ini` file controls how Alert Rules are migrated to the Grafana Cloud instance and is set to `paused` by default so you can review and test your Alerting resources in your Grafana Cloud instance without duplicate notifications.
+
+The available options for `alert_rule_state` are:
+
+`paused`
+: Creates all Alert rules in paused state on the Cloud instance. This is helpful to avoid double notifications.
+
+`unchanged`
+: The Alert rules maintain their original state coming from the source instance.
+
+When you are ready to start using your alert rules and notifications from your Grafana Cloud instance, run the migration again with `alert_rules_state = unchanged`.
+
+### Resource permissions
+
+Because the migration assistant does not yet migrate teams or RBAC permissions, your resources are migrated with default permissions. Ensure that you reconfigure permissions in your cloud stack as needed following a migration. For more information, refer to [Grafana Cloud user roles and permissions](https://grafana.com/docs/grafana-cloud/account-management/authentication-and-permissions/cloud-roles/).
+
+## Migrate multiple organizations
+
+If you are using the [organizations](https://grafana.com/docs/grafana/latest/administration/organization-management/#about-organizations) feature on your Grafana Instance and intend to migrate to Grafana Cloud, you need to plan this aspect of the migration carefully.
+
+The organizations feature is not supported in Grafana Cloud, but folders and RBAC can be used to protect and grant permissions to resources instead. The recommended path is to migrate multiple organizations to a single cloud stack. This is the simplest option and provides the best user experience.
+
+The migration assistant creates and uploads snapshots based on the resources within a specific organization. There is no option to migrate an entire Grafana instance with multiple organizations at once. You need to run the migration process for each organization you want to migrate.
+
+The Grafana server administrator is granted access to the migration assistant by default. The server administrator can perform the migration by switching organizations and running the migration assistant each time. The Grafana server administrator can also grant access to the migration assistant to organization administrators who are members using the RBAC **Migration Assistant:Organization resource migrator** role. This allows those organization administrators to run the migration process for their respective organizations.
+
+### Access Control and managing resources in the Cloud Instance
+
+The main driver for setting up organizations in the first place is resource isolation. In order to achieve this in Grafana Cloud, you can organize resources into folders and set up teams and permissions that correspond to your organizations.
+
+For more information about configuring teams and permissions, refer to [Configure Grafana Teams](https://grafana.com/docs/grafana/latest/administration/team-management/configure-grafana-teams/).
diff --git a/docs/sources/administration/migration-guide/manually-migrate-to-grafana-cloud.md b/docs/sources/administration/migration-guide/manually-migrate-to-grafana-cloud.md
new file mode 100644
index 00000000000..d0bffd7b8f2
--- /dev/null
+++ b/docs/sources/administration/migration-guide/manually-migrate-to-grafana-cloud.md
@@ -0,0 +1,312 @@
+---
+description: Migrate from Grafana OSS/Enterprise to Grafana Cloud manually
+keywords:
+ - Grafana Cloud
+ - Grafana Enterprise
+ - Grafana OSS
+menuTitle: Manually migrate to Grafana Cloud
+title: Migrate from Grafana OSS/Enterprise to Grafana Cloud manually
+weight: 300
+---
+
+# Migrate from Grafana OSS/Enterprise to Grafana Cloud manually
+
+This migration guide is designed to assist Grafana OSS/Enterprise users in seamlessly transitioning manually to Grafana Cloud.
+
+{{< admonition type="note" >}}
+There isn't yet a standard method for importing existing data into Grafana Cloud from self-managed databases.
+{{< /admonition >}}
+
+## Plan and perform a manual migration
+
+If you need to migrate resources beyond what is supported by the Grafana Cloud Migration Assistant, you can migrate them manually with this guide. Moving your team from Grafana OSS/Enterprise to Grafana Cloud manually involves some coordination and communication in addition to the technical migration in the following documentation.
+
+If you are an existing Grafana OSS/Enterprise customer, contact your account team at Grafana Labs to plan a transition period, arrange licenses, and learn how much your Grafana Cloud subscription costs in comparison to Grafana OSS/Enterprise. The account team can also offer specific guidance and arrange professional services to assist with your migration if needed.
+
+Evaluate Grafana Cloud's security and compliance policies at the [Grafana Labs Trust Center](https://trust.grafana.com/).
+
+You may choose to test Grafana Cloud for some time before migrating your entire organization. To do so, set up a “test” stack in Cloud and migrate resources there first. If you use Grafana Alerting, make sure to set up a different contact point so that alerts do not fire twice.
+
+When you decide to migrate, set aside a day of cutover during which users should not create new dashboards or alerts. Migrate any newly-created resources, turn on your production Alerting contact points and notification policies in Cloud and turn them off in Grafana OSS/Enterprise, and notify your users. You may also choose to redirect the Grafana OSS/Enterprise URL to your Grafana Cloud URL.
+
+| Component | Migration Effort | Notes |
+| ------------ | ---------------- | -------------------------------------------------------------------------- |
+| Folders | Low | |
+| Dashboards | Low | Data source references might need to be renamed |
+| Alerts | Medium | Data source based alerts might need to be adapted |
+| Plugins | Medium | Depends on the feature set of the plugin |
+| Data sources | High | If the data sources references any secrets, you need to provide them again |
+
+## Before you begin
+
+Ensure you have the following:
+
+- A [Grafana Cloud Stack](https://grafana.com/docs/grafana-cloud/get-started/) and access to a Linux Machine (or a working WSL2 installation) to run the code snippets in this guide.
+- Administrator access to a Grafana Cloud stack. To check you access level, Go to `https://grafana.com/orgs//members`
+- Administrator access to your existing Grafana OSS/Enterprise instance. To check your access level, Go to `https:///admin/users`
+- Access to the credentials used to connect to your data sources. For example, API keys or usernames and passwords. Since this information is encrypted, it cannot be copied from one instance to the other.
+- If some of your data sources are only available from inside your network, refer to the requirements for [Private Data Source Connect](https://grafana.com/docs/grafana-cloud/connect-externally-hosted/private-data-source-connect/)
+- For Plugins, Reports and Playlists only: The [curl](https://github.com/curl/curl) and [jq](https://jqlang.github.io/jq/download/) command line tools
+
+## Upgrade Grafana OSS/Enterprise to the latest version
+
+Grafana Cloud stacks generally run the latest version of Grafana. In order to avoid issues during migration, upgrade Grafana by following our guides [here](https://grafana.com/docs/grafana/latest/upgrade-guide/).
+
+## Migrate Grafana resources
+
+In this guide, the term **"resources"** refers to things you create in Grafana, like dashboards, folders, alerts, data sources, and permissions.
+
+The process of migration works by pulling the existing resources (like dashboards and folders) from the old Grafana instance, modifying them if necessary, and then pushing them to the new Grafana Cloud instance.
+
+In the provided code snippets throughout this migration guide, you need to substitute specific placeholders with your actual credentials and instance URLs. Make the following replacements before executing the scripts:
+
+- `$GRAFANA_SOURCE_TOKEN` with the access token from your Grafana OSS/Enterprise instance.
+- `$GRAFANA_DEST_TOKEN` with the access token from your Grafana Cloud instance.
+- `$GRAFANA_ONPREM_INSTANCE_URL` with the URL of your Grafana OSS/Enterprise instance. For example: `https://grafana.mydomain.com`
+- `$GRAFANA_CLOUD_INSTANCE_URL` with the URL of your Grafana Cloud instance. For example: `https://myorganization.grafana.net`
+
+### Migrate Grafana Plugins
+
+Migration of plugins is the first step when transitioning from Grafana OSS/Enterprise to Grafana Cloud, given that plugins are integral components that influence the functionality and display of other Grafana resources, such as dashboards.
+
+1. To retrieve the Plugins installed in your Grafana OSS/Enterprise instance, issue an HTTP GET request to the `/api/plugins` endpoint. Use the following shell command:
+
+ ```shell
+ response=$(curl -s -H "Accept: application/json" -H "Authorization: Bearer $GRAFANA_SOURCE_TOKEN" "${GRAFANA_ONPREM_INSTANCE_URL}/api/plugins")
+
+ plugins=$(echo $response | jq '[.[] | select(.signatureType == "community" or (.signatureType != "internal" and .signatureType != "")) | {name: .id, version: .info.version}]')
+
+ echo "$plugins" > plugins.json
+ ```
+
+ The command provided above will carry out an HTTP request to this endpoint and accomplish several tasks:
+
+ - It issues a GET request to the `/api/plugins` endpoint of your Grafana OSS/Enterprise instance to retrieve a list of installed plugins.
+ - It filters out the list to only include community plugins and those signed by external parties.
+ - It extracts the plugin ID and version before storing them in a `plugins.json` file.
+
+1. To import the plugins in your Grafana Cloud Instance, execute the following command. This command constructs an HTTP POST request to `https://grafana.com/api/instances//plugins`
+
+ ```shell
+ CLOUD_INSTANCE=$GRAFANA_CLOUD_INSTANCE_URL
+
+ stack_slug="${CLOUD_INSTANCE#*//}"
+ stack_slug="${stack_slug%%.*}"
+ jq -c '.[]' plugins.json | while IFS= read -r plugin; do
+ name=$(echo "$plugin" | jq -r '.name')
+ version=$(echo "$plugin" | jq -r '.version')
+ echo "Adding plugin $name with version $version to stack $stack_slug"
+ response=$(curl -s -X POST "https://grafana.com/api/instances/$stack_slug/plugins" \
+ -H "Authorization: Bearer " \
+ -H "Content-Type: application/json" \
+ -d "{\"plugin\": \"$name\", \"version\": \"$version\"}")
+ echo "POST response for plugin $name version $version: $response"
+ done
+ ```
+
+ Replace `` with your Grafana Cloud Access Policy Token. To create a new one, refer to Grafana Cloud [access policies documentation](https://grafana.com/docs/grafana-cloud/account-management/authentication-and-permissions/access-policies/)
+
+ This script iterates through each plugin listed in the `plugins.json` file:
+
+ - It constructs a POST request for each plugin to add it to the specified Grafana Cloud instance.
+ - It reports back the response for each POST request to give you confirmation or information about any issues that occurred.
+
+### Migrate resources that are already provisioned as-code
+
+If you already use tools like [Terraform](https://grafana.com/docs/grafana-cloud/developer-resources/infrastructure-as-code/terraform/), [Ansible](https://grafana.com/docs/grafana-cloud/developer-resources/infrastructure-as-code/ansible/), or [Grafana’s HTTP API](https://grafana.com/docs/grafana-cloud/developer-resources/api-reference/http-api/) to provision resources to Grafana, redirect those to the new Grafana Cloud instance by replacing the Grafana URL and credentials.
+
+### Migrate dashboards, folders, data sources, library panels, and alert rules using Grizzly
+
+Grizzly is a command line tool that streamlines working with Grafana resources. Use it to migrate most of the content in your Grafana instance. Follow these steps in your terminal to install Grizzly. If you need to change the os or the architecture, Refer to the Grizzly [releases](https://github.com/grafana/grizzly/releases) and use the binary according to your needs.
+
+```shell
+# download the binary (adapt os and arch as needed)
+$ curl -fSL -o "/usr/local/bin/grr" "https://github.com/grafana/grizzly/releases/download/v0.3.1/grr-linux-amd64"
+
+# make it executable
+$ chmod a+x "/usr/local/bin/grr"
+
+# have fun :)
+$ grr --help
+```
+
+First, create a new folder on your computer and navigate to it to keep your work organized.
+
+```shell
+mkdir grafana-migration
+cd grafana-migration
+```
+
+To give grizzly access to your Grafana OSS/Enterprise instance and the Grafana Cloud Instance, you need to create a [service account](https://grafana.com/docs/grafana-cloud/account-management/authentication-and-permissions/service-accounts/) and a corresponding [access token](https://www.grafana.com/docs/grafana-cloud/account-management/authentication-and-permissions/service-accounts/#service-account-tokens) on each instance. You can use these tokens to authenticate requests to pull and push resources. Follow these steps on your Grafana OSS/Enterprise instance:
+
+- Navigate to the **Administration -> Users and access -> Service Accounts** Page within the Grafana OSS/Enterprise instance.
+- Click on **Add Service Account**
+- Give the Service account a descriptive name like “grizzly-migration” and apply the **Admin** role.
+- After creating the account, click on **Add Service Account Token**
+- Enter a name for the token
+- Select **Set expiration date** and enter an expiry date for the token
+- Click **Generate Token** and save this token in a password manager or other secure place.
+
+Complete the service account creation and token generation process for your Grafana Cloud Instance by following the same steps outlined above for your Grafana OSS/Enterprise instance. This ensures that Grizzly has the necessary access token for both platforms.
+
+Next, to tell grizzly which instances you’re going to work on, use the following commands:
+
+```shell
+grr config create-context grafana-onprem
+grr config use-context grafana-onprem
+grr config set output-format json
+grr config set grafana.url $GRAFANA_ENT_INSTANCE_URL
+grr config set grafana.token $GRAFANA_SOURCE_TOKEN
+
+grr config create-context grafana-cloud
+grr config use-context grafana-cloud
+grr config set output-format json
+grr config set grafana.url $GRAFANA_CLOUD_INSTANCE_URL
+grr config set grafana.token $GRAFANA_DEST_TOKEN
+```
+
+Afterward, you will have two contexts set up; one for your local Grafana OSS/Enterprise installation and one for Grafana Cloud. The `grr config use-context` command allows you to switch between the two instances while using Grizzly.
+
+#### Export existing resources
+
+Switch to the `grafana-onprem` context and use the pull command to fetch the resources you want to migrate:
+
+```shell
+grr config use-context grafana-onprem
+grr pull . \
+ -t 'Dashboard/*' \
+ -t 'Datasource/*' \
+ -t 'DashboardFolder/*' \
+ -t 'LibraryElement/*' \
+ -t 'AlertRuleGroup/*' \
+ -t 'AlertContactPoint/*' \
+ -t 'AlertNotificationPolicy/*'
+```
+
+This will fetch the specified resources from Grafana and store them in the current directory.
+
+#### Push the resources to your Grafana Cloud stack
+
+With everything in place, switch to the Grafana cloud context and use the following commands to apply the resources to the configured instance:
+
+```shell
+grr config use-context grafana-cloud
+
+grr apply . -t 'DashboardFolder/*'
+grr apply . -t 'LibraryElement/*'
+grr apply . -t 'Datasource/*'
+grr apply . -t 'Dashboard/*'
+grr apply . -t 'AlertRuleGroup/*'
+grr apply . -t 'AlertContactPoint/*'
+grr apply . -t 'AlertNotificationPolicy/*'
+```
+
+#### Fill in data source credentials
+
+After migrating your data sources, you must fill in their credentials, like tokens, usernames, or passwords. For security reasons, grizzly cannot read encrypted data source credentials from the existing Grafana instance.
+
+To fill in the missing authentication information, go to the **Connections -> Datasources** page in your new Grafana Cloud instance and verify that credentials for all data sources are set. You can skip data sources starting with `grafanacloud` - These are managed by Grafana Cloud directly and provide access to Grafana Cloud databases.
+
+If one of your data sources can only be accessed from your internal network, take a look at the [Private Data Source Connect documentation](https://grafana.com/docs/grafana-cloud/connect-externally-hosted/private-data-source-connect/).
+
+After you have configured the data sources, all your dashboards should be available as they were before.
+
+##### (Optional) Configure Private Data Source Connect (PDC)
+
+This step only applies if you use Grafana OSS/Enterprise to access network-secured data sources.
+
+Some data sources, like Prometheus or SQL databases, live on private networks or behind fire wall rules that are not accessible by Grafana Cloud. If your Grafana OSS/Enterprise instance was hosted on the same network as your data source, you might find that Grafana Cloud cannot connect to all of the same data sources that Grafana OSS/Enterprise could access.
+
+To access these data sources from Grafana Cloud, follow our guide to [configure PDC in your network](https://grafana.com/docs/grafana-cloud/connect-externally-hosted/private-data-source-connect/configure-pdc/), and then configure the applicable Grafana data sources to [connect using PDC](https://grafana.com/docs/grafana-cloud/connect-externally-hosted/private-data-source-connect/configure-pdc/#configure-a-data-source-to-use-private-data-source-connect-pdc). Note that PDC is only needed for your network-secured data sources, not for data sources like Splunk or CloudWatch that are accessible over the public internet.
+
+For more information on how PDC works, see our [overview document](/docs/grafana-cloud/connect-externally-hosted/private-data-source-connect/).
+
+### Migrate reports and playlists using Grafana’s HTTP API
+
+Grizzly does not currently support Reports and Playlists as a resource, so you can perform this migration using Grafana’s HTTP API using the `curl` command.
+
+#### Reports (For Grafana Enterprise only)
+
+1. To export your Reports, you will need to invoke the `api/reports` endpoint of your Grafana OSS/Enterprise instance. The below shell command accomplishes this by using `curl` to send a request to the endpoint and then stores the retrieved report configuration into a file named `reports.json`.
+
+ ```shell
+ curl ${GRAFANA_ONPREM_INSTANCE_URL}/api/reports -H "Authorization: Bearer $GRAFANA_SOURCE_TOKEN" > reports.json
+ ```
+
+2. To upload the configuration data you have saved in the `reports.json` file to your new Grafana Cloud instance, run the below command. The command will take the local file `reports.json` and push its contents to the `api/reports` endpoint of your Grafana Cloud instance.
+
+ ```shell
+ jq -M -r -c '.[]' < reports.json | while read -r json; do curl -XPOST ${GRAFANA_CLOUD_INSTANCE_URL}/api/reports -H"Authorization: Bearer $GRAFANA_DEST_TOKEN" -d"$json" -H 'Content-Type: application/json'; done
+ ```
+
+#### Playlists
+
+1. To retrieve the Playlists from your Grafana OSS/Enterprise instance, issue an HTTP GET request to the `/api/playlists` endpoint. Use the following shell command:
+
+ ```shell
+ mkdir playlists
+ curl "${GRAFANA_ONPREM_INSTANCE_URL}/api/playlists" \
+ -H "Authorization: Bearer $GRAFANA_SOURCE_TOKEN" \
+ | jq -M -r -c '.[] | .uid' \
+ | while read -r uid; do \
+ curl "${GRAFANA_ONPREM_INSTANCE_URL}/api/playlists/$uid" \
+ -H "Authorization: Bearer $GRAFANA_SOURCE_TOKEN" \
+ > playlists/$uid.json; \
+ done
+ ```
+
+ The command provided above will carry out an HTTP request to this endpoint and accomplish several tasks:
+
+ - It fetches an array of all the playlists available in the Grafana OSS/Enterprise instance.
+ - It then iterates through each playlist to obtain the complete set of details.
+ - Finally, it stores each playlist's specification as separate JSON files within a directory named `playlists`
+
+2. To import the playlists, execute the following command. This command constructs an HTTP POST request targeting the `/api/playlists` endpoint of your Grafana Cloud Instance.
+
+ ```shell
+ for playlist in playlists/*; do
+ curl -XPOST "${GRAFANA_CLOUD_INSTANCE_URL}/api/playlists" \
+ -H "Authorization: Bearer $GRAFANA_DEST_TOKEN" \
+ -H "Content-Type: application/json" \
+ -d $playlist > /dev/null;
+ done
+ ```
+
+### Migrate single sign-on configuration
+
+Grafana Cloud stacks support all of the same authentication and authorization options as Grafana OSS/Enterprise, except for [anonymous authentication](https://grafana.com/docs/grafana/latest/setup-grafana/configure-security/configure-authentication/anonymous-auth/) and use of the [Auth proxy](https://grafana.com/docs/grafana/latest/setup-grafana/configure-security/configure-authentication/auth-proxy/). However, single sign-on settings cannot be exported and imported like dashboards, alerts, and other resources.
+
+To set up SAML authentication from scratch using Grafana’s UI or API, follow [these instructions](https://grafana.com/docs/grafana/latest/setup-grafana/configure-security/configure-authentication/saml-ui/) to Configure SAML authentication in Grafana.
+
+LDAP and OIDC/OAuth2 can only be configured in Grafana Cloud by the Grafana Labs support team. Follow [these instructions](https://grafana.com/docs/grafana-cloud/account-management/authentication-and-permissions/) to request SSO configuration from the support team.
+
+### Migrate custom Grafana configuration
+
+You may have customized the [configuration](https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/) of your Grafana OSS/Enterprise instance, for example with feature toggles, custom auth, or embedding options. Since Grafana configuration is stored in environment variables or the filesystem where Grafana runs, Grafana Cloud users do not have access to it. However, you can open a support ticket to ask a Grafana Labs support engineer for customizations.
+
+The following customizations are available via support:
+
+- Enabling [feature toggles](http://www.grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/feature-toggles).
+- [Single sign-on and team sync using SAML, LDAP, or OAuth](http://www.grafana.com/docs/grafana/latest/setup-grafana/configure-security/configure-authentication).
+- Enable [embedding Grafana dashboards in other applications](https://grafana.com/docs/grafana/latest/setup-grafana/configure-grafana/#allow_embedding) for Grafana Cloud contracted customers.
+- [Audit logging](https://grafana.com/docs/grafana/latest/setup-grafana/configure-security/audit-grafana/) ([Usage insights logs and dashboards](https://grafana.com/docs/grafana-cloud/account-management/usage-insights/) are available in Grafana Cloud Pro and Advanced by default).
+
+Note that the following custom configurations are not supported in Grafana Cloud:
+
+- [Anonymous user access](https://grafana.com/docs/grafana/latest/setup-grafana/configure-security/configure-authentication/anonymous-auth/).
+- [Auth proxy](https://grafana.com/docs/grafana/latest/setup-grafana/configure-security/configure-authentication/auth-proxy/).
+- [Third-party database encryption](https://grafana.com/docs/grafana/latest/setup-grafana/configure-security/configure-database-encryption/) and the [Hashicorp Vault](https://grafana.com/docs/grafana/latest/setup-grafana/configure-security/configure-database-encryption/encrypt-secrets-using-hashicorp-key-vault/) integration.
+- Running self-signed plugins, like custom-built data sources or visualizations. For more information on plugin signing, refer to our [developer documentation](https://grafana.com/developers/plugin-tools/publish-a-plugin/sign-a-plugin).
+
+If you have a custom configuration in Grafana OSS/Enterprise that is not listed here, reach out to our support team to find out whether they can help you set it up.
+
+## Next steps
+
+After you have successfully migrated resources and configuration from Grafana OSS/Enterprise, consider the following steps to enhance your monitoring experience:
+
+- **Get started with Grafana Cloud**: learn more about the functionality available in Grafana Cloud, which is not available in the open source or Enterprise editions. Read more in [Get started with Grafana Cloud](https://grafana.com/docs/grafana-cloud/get-started/)
+- **AWS PrivateLink for Grafana Cloud**: securely transmit telemetry data from your AWS Virtual Private Cloud (VPC) to Grafana Cloud, entirely within the AWS network.
+ Learn how to set this up with [AWS PrivateLink Integration](https://grafana.com/docs/grafana-cloud/send-data/aws-privatelink/).
+- **Azure PrivateLink for Grafana Cloud**, securely transmit telemetry from your Azure Virtual Network to Grafana Cloud while staying on the Azure network, and avoid exposing your traffic to the public internet.
+ Learn how to set this up with [AWS PrivateLink Integration](https://grafana.com/docs/grafana-cloud/send-data/azure-privatelink/).
+- **[Grafana Integrations](https://grafana.com/docs/grafana-cloud/monitor-infrastructure/integrations/)**: ready-made integrations to make monitoring your infrastructure and applications more straightforward.
diff --git a/docs/sources/administration/organization-management/index.md b/docs/sources/administration/organization-management/index.md
index a332c8110db..6c4d52941f3 100644
--- a/docs/sources/administration/organization-management/index.md
+++ b/docs/sources/administration/organization-management/index.md
@@ -46,7 +46,7 @@ The following table summarizes the resources you can share and/or isolate using
The member of one organization cannot view dashboards assigned to another organization. However, a user can belong to multiple organizations.
-Grafana Server Administrators are responsible for creating organizations. For more information about the Grafana Server Administrator role, refer to [Grafana server administrators]({{< relref "../roles-and-permissions/#grafana-server-administrators" >}}).
+Grafana Server Administrators are responsible for creating organizations. For more information about the Grafana Server Administrator role, refer to [Grafana server administrators](../roles-and-permissions/#grafana-server-administrators).
## View a list of organizations
@@ -80,9 +80,9 @@ Create an organization when you want to isolate dashboards and other resources f
1. In the Preferences section, select a home dashboard, time zone, and week start.
- For more information about preferences, refer to [Preferences]({{< relref "../organization-preferences/" >}}).
+ For more information about preferences, refer to [Preferences](../organization-preferences/).
-For more information about adding users to an organization, refer to [Add a user to an organization]({{< relref "../user-management/server-user-management/add-remove-user-to-org/" >}}).
+For more information about adding users to an organization, refer to [Add a user to an organization](../user-management/server-user-management/add-remove-user-to-org/).
## Delete an organization
diff --git a/docs/sources/administration/organization-preferences/index.md b/docs/sources/administration/organization-preferences/index.md
index 590370bf27f..6ff4cf25dc0 100644
--- a/docs/sources/administration/organization-preferences/index.md
+++ b/docs/sources/administration/organization-preferences/index.md
@@ -20,9 +20,9 @@ Grafana preferences are basic settings. They control the Grafana UI theme, home
Preferences are sometimes confusing because they can be set at four different levels, listed from highest level to lowest:
-- **Server -** Affects all users on the Grafana server. Set by a [Grafana server admin]({{< relref "../roles-and-permissions/#grafana-server-administrators" >}}).
-- **Organization -** Affects all users in an organization. Set by an [Organization admin]({{< relref "../roles-and-permissions/#organization-roles" >}}).
-- **Team -** Affects all users assigned to a team. Set by an Organization Admin or Team Admin. To learn more about these roles, refer to [Teams and permissions]({{< relref "../roles-and-permissions/#teams-and-permissions" >}}).
+- **Server -** Affects all users on the Grafana server. Set by a [Grafana server admin](../roles-and-permissions/#grafana-server-administrators).
+- **Organization -** Affects all users in an organization. Set by an [Organization admin](../roles-and-permissions/#organization-roles).
+- **Team -** Affects all users assigned to a team. Set by an Organization Admin or Team Admin. To learn more about these roles, refer to [Teams and permissions](../roles-and-permissions/#teams-and-permissions).
- **User account -** Affects the individual user. Set by the user on their own account.
The lowest level always takes precedence. For example, if a user sets their theme to **Light**, then their visualization of Grafana displays the light theme. Nothing at any higher level can override that.
@@ -33,7 +33,7 @@ If the user is aware of the change and intended it, then that's great! But if th
In Grafana, you can change your names and emails associated with groups or accounts in the Settings or Preferences. This topic provides instructions for each task.
-Some tasks require certain permissions. For more information about roles, refer to [Roles and permissions]({{< relref "../roles-and-permissions/" >}}).
+Some tasks require certain permissions. For more information about roles, refer to [Roles and permissions](../roles-and-permissions/).
### Change organization name
@@ -75,13 +75,13 @@ To change the team name or email, follow these steps:
### Change user name or email
-To learn how to edit your user information, refer to [Edit your profile]({{< relref "../user-management/user-preferences/#edit-your-profile" >}}).
+To learn how to edit your user information, refer to [Edit your profile](../user-management/user-preferences/#edit-your-profile).
## Change Grafana UI theme
In Grafana, you can modify the UI theme configured in the Settings or Preferences. Set the UI theme for the server, an organization, a team, or your personal user account using the instructions in this topic.
-Some tasks require certain permissions. For more information about roles, refer to [Roles and permissions]({{< relref "../roles-and-permissions/" >}}).
+Some tasks require certain permissions. For more information about roles, refer to [Roles and permissions](../roles-and-permissions/).
### Theme options
@@ -105,9 +105,9 @@ Here is an example of the light theme.
### Change server UI theme
-As a Grafana server administrator, you can change the default Grafana UI theme for all users who are on the server by setting the [default_theme]({{< relref "../../setup-grafana/configure-grafana/#default_theme" >}}) option in the Grafana configuration file.
+As a Grafana server administrator, you can change the default Grafana UI theme for all users who are on the server by setting the [default_theme](../../setup-grafana/configure-grafana/#default_theme) option in the Grafana configuration file.
-To see what the current settings are, refer to [View server settings]({{< relref "../stats-and-license#view-server-settings" >}}).
+To see what the current settings are, refer to [View server settings](../stats-and-license/#view-server-settings).
### Change organization UI theme
@@ -141,11 +141,11 @@ You can change the UI theme for your user account. This setting overrides UI the
By default, Grafana uses the timezone in your web browser. However, you can override this setting at the server, organization, team, or individual user level. This topic provides instructions for each task.
-Some tasks require certain permissions. For more information about roles, refer to [Roles and permissions]({{< relref "../roles-and-permissions/" >}}).
+Some tasks require certain permissions. For more information about roles, refer to [Roles and permissions](../roles-and-permissions/).
### Set server timezone
-Grafana server administrators can choose a default timezone for all users on the server by setting the [default_timezone]({{< relref "../../setup-grafana/configure-grafana/#default_timezone" >}}) option in the Grafana configuration file.
+Grafana server administrators can choose a default timezone for all users on the server by setting the [default_timezone](../../setup-grafana/configure-grafana/#default_timezone) option in the Grafana configuration file.
### Set organization timezone
@@ -179,7 +179,7 @@ You can change the timezone for your user account. This setting overrides timezo
The home dashboard you set is the one all users will see by default when they log in. Click the Grafana icon or **Home** in the breadcrumb to return to it. You can set the home dashboard for the server, an organization, a team, or your personal user account. This topic provides instructions for each task.
-Some tasks require certain permissions. For more information about roles, refer to [Roles and permissions]({{< relref "../roles-and-permissions/" >}}).
+Some tasks require certain permissions. For more information about roles, refer to [Roles and permissions](../roles-and-permissions/).
### Set the home dashboard for the server
@@ -194,7 +194,7 @@ Users with the Grafana Server Admin flag on their account or access to the confi
#### Use a JSON file as the home dashboard
1. Save your JSON file somewhere that Grafana can access it. For example, in the Grafana `data` folder of Grafana.
-1. Update your configuration file to set the path to the JSON file. Refer to [default_home_dashboard_path]({{< relref "../../setup-grafana/configure-grafana/#default_home_dashboard_path" >}}) for more information about modifying the Grafana configuration files.
+1. Update your configuration file to set the path to the JSON file. Refer to [default_home_dashboard_path](../../setup-grafana/configure-grafana/#default_home_dashboard_path) for more information about modifying the Grafana configuration files.
```ini
[dashboards]
@@ -244,7 +244,7 @@ You can choose your own personal home dashboard. This setting overrides all home
### Change server language
-Grafana server administrators can change the default Grafana UI language for all users on the server by setting the [default_language]({{< relref "../../setup-grafana/configure-grafana/#default_language" >}}) option in the Grafana configuration file.
+Grafana server administrators can change the default Grafana UI language for all users on the server by setting the [default_language](../../setup-grafana/configure-grafana/#default_language) option in the Grafana configuration file.
### Change organization language
diff --git a/docs/sources/administration/plugin-management/index.md b/docs/sources/administration/plugin-management/index.md
index 09566ccf250..1f43832b69b 100644
--- a/docs/sources/administration/plugin-management/index.md
+++ b/docs/sources/administration/plugin-management/index.md
@@ -56,17 +56,17 @@ Use app plugins when you want an out-of-the-box monitoring experience.
### Managing access for app plugins
-Customize access to app plugins with [RBAC]({{< relref "../roles-and-permissions/access-control/rbac-for-app-plugins" >}}).
+Customize access to app plugins with [RBAC](../roles-and-permissions/access-control/rbac-for-app-plugins/).
By default, the Viewer, Editor and Admin roles have access to all app plugins that their Organization role allows them to access. Access is granted by the `fixed:plugins.app:reader` role.
{{% admonition type="note" %}}
-To prevent users from seeing an app plugin, refer to [these permissions scenarios]({{< relref "../roles-and-permissions/access-control/plan-rbac-rollout-strategy#prevent-viewers-from-accessing-an-app-plugin" >}}).
+To prevent users from seeing an app plugin, refer to [these permissions scenarios](../roles-and-permissions/access-control/plan-rbac-rollout-strategy/#prevent-viewers-from-accessing-an-app-plugin).
{{% /admonition %}}
## Plugin catalog
-The Grafana plugin catalog allows you to browse and manage plugins from within Grafana. Only Grafana server administrators and Organization administrators can access and use the plugin catalog. For more information about Grafana roles and permissions, refer to [Roles and permissions]({{< relref "../administration/roles-and-permissions" >}}).
+The Grafana plugin catalog allows you to browse and manage plugins from within Grafana. Only Grafana server administrators and Organization administrators can access and use the plugin catalog. For more information about Grafana roles and permissions, refer to [Roles and permissions](../roles-and-permissions/).
The following access rules apply depending on the user role:
@@ -88,7 +88,7 @@ The Grafana plugin catalog is designed to work with a single Grafana server inst
_Video shows the Plugin catalog in a previous version of Grafana._
{{% admonition type="note" %}}
-If required, the Grafana plugin catalog can be disabled using the `plugin_admin_enabled` flag in the [configuration]({{< relref "../../setup-grafana/configure-grafana/#plugin_admin_enabled" >}}) file.
+If required, the Grafana plugin catalog can be disabled using the `plugin_admin_enabled` flag in the [configuration](../../setup-grafana/configure-grafana/#plugin_admin_enabled) file.
{{% /admonition %}}
@@ -114,7 +114,7 @@ There are also additional ways to install plugins depending on your setup.
#### Install a plugin using Grafana CLI
-Grafana CLI allows you to install, upgrade, and manage your Grafana plugins using a command line. For more information about Grafana CLI plugin commands, refer to [Plugin commands]({{< relref "../../cli/#plugins-commands" >}}).
+Grafana CLI allows you to install, upgrade, and manage your Grafana plugins using a command line. For more information about Grafana CLI plugin commands, refer to [Plugin commands](../../cli/#plugins-commands).
#### Install a plugin from a ZIP file
@@ -126,15 +126,15 @@ Download the archive containing the plugin assets, and install it by extracting
unzip my-plugin-0.2.0.zip -d YOUR_PLUGIN_DIR/my-plugin
```
-The path to the plugin directory is defined in the configuration file. For more information, refer to [Configuration]({{< relref "../../setup-grafana/configure-grafana/#plugins" >}}).
+The path to the plugin directory is defined in the configuration file. For more information, refer to [Configuration](../../setup-grafana/configure-grafana/#plugins).
-#### Install a plugin using Grafana configuration
+#### Install a plugin using Grafana configuration
{{% admonition type="note" %}}
This feature requires Grafana 11.5.0 or later.
{{% /admonition %}}
-You can install plugins by adding the plugin ID to the `plugins.preinstall` section in the Grafana configuration file. This prevents the plugin from being accidentally uninstalled and can be auto-updated. For more information, refer to [Configuration]({{< relref "../../setup-grafana/configure-grafana/#plugins" >}}).
+You can install plugins by adding the plugin ID to the `plugins.preinstall` section in the Grafana configuration file. This prevents the plugin from being accidentally uninstalled and can be auto-updated. For more information, refer to [Configuration](../../setup-grafana/configure-grafana/#plugins).
#### Install a plugin in air-gapped environment
@@ -224,7 +224,7 @@ All plugins are signed under a _signature level_. The signature level determines
Unsigned plugins are not supported in Grafana Cloud.
{{% /admonition %}}
-We strongly recommend that you don't run unsigned plugins in your Grafana instance. However, if you're aware of the risks and you still want to load an unsigned plugin, refer to [Configuration]({{< relref "../../setup-grafana/configure-grafana/#allow_loading_unsigned_plugins" >}}).
+We strongly recommend that you don't run unsigned plugins in your Grafana instance. However, if you're aware of the risks and you still want to load an unsigned plugin, refer to [Configuration](../../setup-grafana/configure-grafana/#allow_loading_unsigned_plugins).
If you've allowed loading of an unsigned plugin, then Grafana writes a warning message to the server log:
@@ -236,6 +236,32 @@ WARN[06-01|16:45:59] Running an unsigned plugin pluginID=
If you're developing a plugin, then you can enable development mode to allow all unsigned plugins.
{{% /admonition %}}
+## Integrate plugins
+
+You can configure your Grafana instance to let the frontends of installed plugins directly communicate locally with the backends of other installed plugins. By default, you can only communicate with plugin backends remotely. You can use this configuration to, for example, enable a [canvas panel](https://grafana.com/docs/grafana/latest/panels-visualizations/visualizations/canvas/) to call an application resource API that is permitted by the `actions_allow_post_url` option.
+
+To enable backend communication between plugins:
+
+1. Set the plugins you want to communicate with. In your configuration file (`grafana.ini` or `custom.ini` depending on your operating system) remove the semicolon to enable and then set the following configuration option:
+
+ ```
+ actions_allow_post_url=
+ ```
+
+ This is a comma-separated list that uses glob matching.
+
+ - To allow access to all plugins that have a backend:
+
+ ```
+ actions_allow_post_url=/api/plugins/*
+ ```
+
+ - To access to the backend of only one plugin:
+
+ ```
+ actions_allow_post_url=/api/plugins/
+ ```
+
## Plugin Frontend Sandbox
{{% admonition type="caution" %}}
@@ -256,7 +282,7 @@ Plugins running inside the Frontend Sandbox should continue to work normally wit
The Frontend Sandbox feature is currently behind the `pluginsFrontendSandbox` feature flag. To enable it, you'll need to:
-1. Enable the feature flag in your Grafana configuration. For more information about enabling feature flags, refer to [Configure feature toggles](/setup-grafana/configure-grafana/feature-toggles/).
+1. Enable the feature flag in your Grafana configuration. For more information about enabling feature flags, refer to [Configure feature toggles](/docs/grafana//setup-grafana/configure-grafana/feature-toggles/).
2. For self-hosted Grafana installations, add the plugin IDs you want to sandbox in the `security` section using the `enable_frontend_sandbox_for_plugins` configuration option.
diff --git a/docs/sources/administration/provisioning/index.md b/docs/sources/administration/provisioning/index.md
index 5c164a708aa..bbbbec185cd 100644
--- a/docs/sources/administration/provisioning/index.md
+++ b/docs/sources/administration/provisioning/index.md
@@ -20,7 +20,7 @@ This makes GitOps more natural since data sources and dashboards can be defined
## Configuration file
-Refer to [Configuration]({{< relref "../../setup-grafana/configure-grafana/" >}}) for more information on what you can configure in `grafana.ini`.
+Refer to [Configuration](../../setup-grafana/configure-grafana/) for more information on what you can configure in `grafana.ini`.
### Configuration file locations
@@ -73,7 +73,7 @@ Therefore, we heavily rely on the expertise of the community.
## Data sources
-You can manage data sources in Grafana by adding YAML configuration files in the [`provisioning/datasources`]({{< relref "../../setup-grafana/configure-grafana#provisioning" >}}) directory.
+You can manage data sources in Grafana by adding YAML configuration files in the [`provisioning/datasources`](../../setup-grafana/configure-grafana/#provisioning) directory.
Each configuration file can contain a list of `datasources` to add or update during startup.
If the data source already exists, Grafana reconfigures it to match the provisioned configuration file.
@@ -92,7 +92,7 @@ This prevents old configurations from overwriting newer ones if you have differe
### Example data source configuration file
-This example provisions a [Graphite data source]({{< relref "../../datasources/graphite" >}}):
+This example provisions a [Graphite data source](../../datasources/graphite/):
```yaml
# Configuration file version
@@ -172,14 +172,14 @@ datasources:
editable: false
```
-For provisioning examples of specific data sources, refer to that [data source's documentation]({{< relref "../../datasources" >}}).
+For provisioning examples of specific data sources, refer to that [data source's documentation](../../datasources/).
#### JSON data
Not all data sources have the same configuration settings. Only the most common fields are included in examples.
To provision the rest of a data source's settings, include them as a JSON blob in the `jsonData` field.
-Common settings in the [built-in core data sources]({{< relref "../../datasources#built-in-core-data-sources" >}}) include:
+Common settings in the [built-in core data sources](../../datasources/#built-in-core-data-sources) include:
{{< admonition type="note" >}}
Data sources tagged with _HTTP\*_ communicate using the HTTP protocol, which includes all core data source plugins except MySQL, PostgreSQL, and MSSQL.
@@ -240,11 +240,11 @@ Data sources tagged with _HTTP\*_ communicate using the HTTP protocol, which inc
| implementation | string | AlertManager | The implementation of the AlertManager data source, such as `prometheus`, `cortex` or `mimir` |
| handleGrafanaManagedAlerts | boolean | AlertManager | When enabled, Grafana-managed alerts are sent to this Alertmanager |
-For examples of specific data sources' JSON data, refer to that [data source's documentation]({{< relref "../../datasources" >}}).
+For examples of specific data sources' JSON data, refer to that [data source's documentation](../../datasources/).
#### Secure JSON Data
-Secure JSON data is a map of settings that are encrypted with a [secret key]({{< relref "../../setup-grafana/configure-grafana#secret_key" >}}) from the Grafana configuration.
+Secure JSON data is a map of settings that are encrypted with a [secret key](../../setup-grafana/configure-grafana/#secret_key) from the Grafana configuration.
The encryption hides content from the users of the application.
This should be used for storing the TLS Cert and password that Grafana appends to the request on the server side.
All of these settings are optional.
@@ -285,7 +285,7 @@ datasources:
## Plugins
-You can manage plugin applications in Grafana by adding one or more YAML configuration files in the [`provisioning/plugins`]({{< relref "../../setup-grafana/configure-grafana#provisioning" >}}) directory.
+You can manage plugin applications in Grafana by adding one or more YAML configuration files in the [`provisioning/plugins`](../../setup-grafana/configure-grafana/#provisioning) directory.
Each configuration file can contain a list of `apps` that update during start up.
Grafana updates each app to match the configuration file.
@@ -320,7 +320,7 @@ apps:
## Dashboards
-You can manage dashboards in Grafana by adding one or more YAML configuration files in the [`provisioning/dashboards`]({{< relref "../../setup-grafana/configure-grafana#dashboards" >}}) directory.
+You can manage dashboards in Grafana by adding one or more YAML configuration files in the [`provisioning/dashboards`](../../setup-grafana/configure-grafana/#dashboards) directory.
Each configuration file can contain a list of `dashboards providers` that load dashboards into Grafana from the local filesystem.
The dashboard provider configuration file looks somewhat like this:
@@ -380,7 +380,7 @@ The JSON definition in the input field when using `Copy JSON to Clipboard` or `S
### Reusable dashboard URLs
-If the dashboard in the JSON file contains an [UID]({{< relref "../../dashboards/build-dashboards/view-dashboard-json-model" >}}), Grafana forces insert/update on that UID.
+If the dashboard in the JSON file contains an [UID](../../dashboards/build-dashboards/view-dashboard-json-model/), Grafana forces insert/update on that UID.
This allows you to migrate dashboards between Grafana instances and provisioning Grafana from configuration without breaking the URLs given because the new dashboard URL uses the UID as identifier.
When Grafana starts, it updates and inserts all dashboards available in the configured folders.
If you modify the file, then the dashboard is also updated.
@@ -436,7 +436,7 @@ You can't create nested folders structures, where you have folders within folder
## Alerting
-For information on provisioning Grafana Alerting, refer to [Provision Grafana Alerting resources]({{< relref "../../alerting/set-up/provision-alerting-resources/" >}}).
+For information on provisioning Grafana Alerting, refer to [Provision Grafana Alerting resources](../../alerting/set-up/provision-alerting-resources/).
### Supported settings
@@ -479,6 +479,7 @@ The following sections detail the supported settings and secure settings for eac
| mentionGroups | |
| mentionChannel | |
| token | yes |
+| color | |
#### Alert notification `victorops`
@@ -650,5 +651,5 @@ The following sections detail the supported settings and secure settings for eac
Grafana Enterprise supports:
-- [Provisioning role-based access control with Grafana]({{< relref "../roles-and-permissions/access-control/rbac-grafana-provisioning/" >}})
-- [Provisioning role-based access control with Terraform]({{< relref "../roles-and-permissions/access-control/rbac-terraform-provisioning/" >}})
+- [Provisioning role-based access control with Grafana](../roles-and-permissions/access-control/rbac-grafana-provisioning/)
+- [Provisioning role-based access control with Terraform](../roles-and-permissions/access-control/rbac-terraform-provisioning/)
diff --git a/docs/sources/administration/recorded-queries/index.md b/docs/sources/administration/recorded-queries/index.md
index d61585f0da5..fdeaa7da656 100644
--- a/docs/sources/administration/recorded-queries/index.md
+++ b/docs/sources/administration/recorded-queries/index.md
@@ -35,7 +35,7 @@ Recorded queries only work with backend data source plugins. Refer to [Backend d
- single row and column - A query that returns a single row and column.
- row count - A query that returns meaningful rows to be counted.
-- expression - Any expression. To learn more about creating and using expressions, see [Write expression queries]({{< relref "../../panels-visualizations/query-transform-data/expression-queries" >}}).
+- expression - Any expression. To learn more about creating and using expressions, see [Write expression queries](../../panels-visualizations/query-transform-data/expression-queries/).
- dataplane numeric - A query that returns [dataplane numeric kind](/developers/dataplane/numeric) data.
After a recorded query is created or enabled, it immediately creates a snapshot and continues to create snapshots at the set interval. The recorded query stops taking snapshots when it is disabled, deleted, or when Grafana is not running. Data points are gathered in the backend by running the recorded query and forwarding each result to a remote-write enabled Prometheus instance.
@@ -48,7 +48,7 @@ To use a recorded query, create one and add it to a dashboard. After that, it ca
1. Find/create a query you want to record on a dashboard in an edit panel. The query must only return one row and column. If it returns more, you can still record the number of results returned using the “count” option.
- The query's data source must be a backend data source.
- - Expressions can be used to aggregate data from a time series query. Refer to [Write expression queries]({{< relref "../../panels-visualizations/query-transform-data/expression-queries" >}}) to learn more about creating and using expressions.
+ - Expressions can be used to aggregate data from a time series query. Refer to [Write expression queries](../../panels-visualizations/query-transform-data/expression-queries/) to learn more about creating and using expressions.
1. Click the record query button located in the top right of the query editor.
1. Enter recorded query information. All fields are required unless otherwise indicated.
- Name - Name of the recorded query.
@@ -68,7 +68,7 @@ You can add existing recorded queries to panels in a dashboard. For each recorde
1. If you want to filter recorded queries by data source, select a data source from the filter by data source drop down menu.
1. Click the `Add` button on your recorded query to add it to the panel.
-After adding your recorded query to the panel, the panel data source will become `-- Mixed --`. Your recorded query is represented by a `Prometheus` query with a name label matching your recorded query name. Refer to [Prometheus]({{< relref "../../datasources/prometheus/" >}}) to learn more about the `Prometheus` data source.
+After adding your recorded query to the panel, the panel data source will become `-- Mixed --`. Your recorded query is represented by a `Prometheus` query with a name label matching your recorded query name. Refer to [Prometheus](../../datasources/prometheus/) to learn more about the `Prometheus` data source.
If after adding a recorded query, a query with a `-- Mixed --` data source instead of `Prometheus` data source appears, this could mean that a Prometheus remote write target was not set up for recorded queries. Refer to [Remote write target](#remote-write-target) to set up a remote write point.
diff --git a/docs/sources/administration/roles-and-permissions/_index.md b/docs/sources/administration/roles-and-permissions/_index.md
index 134482723b4..29c69087072 100644
--- a/docs/sources/administration/roles-and-permissions/_index.md
+++ b/docs/sources/administration/roles-and-permissions/_index.md
@@ -34,14 +34,14 @@ If you are running Grafana Enterprise, you can also control access to data sourc
A Grafana server administrator manages server-wide settings and access to resources such as organizations, users, and licenses. Grafana includes a default server administrator that you can use to manage all of Grafana, or you can divide that responsibility among other server administrators that you create.
{{% admonition type="note" %}}
-The server administrator role does not mean that the user is also a Grafana [organization administrator]({{< relref "#organization-roles" >}}).
+The server administrator role does not mean that the user is also a Grafana [organization administrator](#organization-roles).
{{% /admonition %}}
A server administrator can perform the following tasks:
- Manage users and permissions
- Create, edit, and delete organizations
-- View server-wide settings defined in the [Configuration]({{< relref "../../setup-grafana/configure-grafana/" >}}) file
+- View server-wide settings defined in the [Configuration](../../setup-grafana/configure-grafana/) file
- View Grafana server statistics, including total users and active sessions
- Upgrade the server to Grafana Enterprise.
@@ -49,7 +49,7 @@ A server administrator can perform the following tasks:
The server administrator role does not exist in Grafana Cloud.
{{% /admonition %}}
-To assign or remove server administrator privileges, see [Server user management]({{< relref "../user-management/server-user-management/assign-remove-server-admin-privileges/" >}}).
+To assign or remove server administrator privileges, see [Server user management](../user-management/server-user-management/assign-remove-server-admin-privileges/).
## Organization users and permissions
@@ -69,11 +69,11 @@ Permissions assigned to a user within an organization control the extent to whic
- library panels
- API keys
-For more information about managing organization users, see [User management]({{< relref "../user-management/manage-org-users/" >}}).
+For more information about managing organization users, see [User management](../user-management/manage-org-users/).
### Organization roles
-Organization role-based permissions are global, which means that each permission level applies to all Grafana resources within an given organization. For example, an editor can see and update _all_ dashboards in an organization, unless those dashboards have been specifically restricted using [dashboard permissions]({{< relref "../user-management/manage-dashboard-permissions/" >}}).
+Organization role-based permissions are global, which means that each permission level applies to all Grafana resources within an given organization. For example, an editor can see and update _all_ dashboards in an organization, unless those dashboards have been specifically restricted using [dashboard permissions](../user-management/manage-dashboard-permissions/).
Grafana uses the following roles to control user access:
@@ -117,32 +117,9 @@ You can specify the following permissions to dashboards and folders.
> Important: When a user creates a dashboard or a folder they are automatically granted **Admin** permissions for it.
-For more information about assigning dashboard folder permissions, refer to [Grant dashboard folder permissions]({{< relref "../user-management/manage-dashboard-permissions/#grant-dashboard-folder-permissions" >}}).
+For more information about assigning dashboard folder permissions, refer to [Grant dashboard folder permissions](../user-management/manage-dashboard-permissions/#grant-dashboard-folder-permissions).
-For more information about assigning dashboard permissions, refer to [Grant dashboard permissions]({{< relref "../user-management/manage-dashboard-permissions/#grant-dashboard-permissions" >}}).
-
-## Editors with administrator permissions
-
-If you have access to the Grafana server, you can modify the default editor role so that editors can use administrator permissions to manage dashboard folders, dashboards, and teams that they create.
-
-{{% admonition type="note" %}}
-This permission does not allow editors to manage folders, dashboards, and teams that they do not create.
-{{% /admonition %}}
-
-This setting can be used to enable self-organizing teams to administer their own dashboards.
-
-For more information about assigning administrator permissions to editors, refer to [Grant editors administrator permissions]({{< relref "../user-management/server-user-management/grant-editor-admin-permissions/" >}}).
-
-## Viewers with dashboard preview and Explore permissions
-
-If you have access to the Grafana server, you can modify the default viewer role so that viewers can:
-
-- Edit and preview dashboards, but cannot save their changes or create new dashboards.
-- Access and use [Explore]({{< relref "../../explore" >}}).
-
-Extending the viewer role is useful for public Grafana installations where you want anonymous users to be able to edit panels and queries, but not be able to save or create new dashboards.
-
-For more information about assigning dashboard preview permissions to viewers, refer to [Enable viewers to preview dashboards and use Explore]({{< relref "../user-management/manage-dashboard-permissions/#enable-viewers-to-edit-but-not-save-dashboards-and-use-explore" >}}).
+For more information about assigning dashboard permissions, refer to [Grant dashboard permissions](../user-management/manage-dashboard-permissions/#grant-dashboard-permissions).
## Teams and permissions
@@ -153,15 +130,15 @@ You can assign a team member one of the following permissions:
- **Member**: Includes the user as a member of the team. Members do not have team administrator privileges.
- **Admin**: Administrators have permission to manage various aspects of the team, including team membership, permissions, and settings.
-Because teams exist inside an organization, the organization administrator can manage all teams. When the `editors_can_admin` setting is enabled, editors can create teams and manage teams that they create. For more information about the `editors_can_admin` setting, refer to [Grant editors administrator permissions]({{< relref "../user-management/server-user-management/grant-editor-admin-permissions/" >}}).
+Because teams exist inside an organization, the organization administrator can manage all teams.
-For details on managing teams, see [Team management]({{< relref "../team-management/" >}}).
+For details on managing teams, see [Team management](../team-management/).
## Grafana Enterprise user permissions features
While Grafana OSS includes a robust set of permissions and settings that you can use to manage user access to server and organization resources, you might find that you require additional capabilities.
-[Grafana Enterprise]({{< relref "../../introduction/grafana-enterprise">}}) provides the following permissions-related features:
+[Grafana Enterprise](../../introduction/grafana-enterprise/) provides the following permissions-related features:
- Data source permissions
- Role-based access control (RBAC)
@@ -170,13 +147,13 @@ While Grafana OSS includes a robust set of permissions and settings that you can
By default, a user can query any data source in an organization, even if the data source is not linked to the user's dashboards.
-Data source permissions enable you to restrict data source query permissions to specific **Users**, **Service Accounts**, and **Teams**. For more information about assigning data source permissions, refer to [Data source permissions]({{< relref "../data-source-management/#data-source-permissions/" >}}).
+Data source permissions enable you to restrict data source query permissions to specific **Users**, **Service Accounts**, and **Teams**. For more information about assigning data source permissions, refer to [Data source permissions](../data-source-management/#data-source-permissions/).
### Role-based access control
RBAC provides you a way of granting, changing, and revoking user read and write access to Grafana resources, such as users, reports, and authentication.
-For more information about RBAC, refer to [Role-based access control]({{< relref "../roles-and-permissions/access-control/" >}}).
+For more information about RBAC, refer to [Role-based access control](access-control/).
### Learn more
diff --git a/docs/sources/administration/roles-and-permissions/access-control/plan-rbac-rollout-strategy/index.md b/docs/sources/administration/roles-and-permissions/access-control/plan-rbac-rollout-strategy/index.md
index 09c2fc4c3d4..e04c2fcecf2 100644
--- a/docs/sources/administration/roles-and-permissions/access-control/plan-rbac-rollout-strategy/index.md
+++ b/docs/sources/administration/roles-and-permissions/access-control/plan-rbac-rollout-strategy/index.md
@@ -369,9 +369,11 @@ Here are two ways to achieve this:
# Update the role
curl -H 'Authorization: Bearer glsa_kcVxDhZtu5ISOZIEt' -H 'Content-Type: application/json' \
- -X PUT-d @/tmp/basic_viewer.json '/api/access-control/roles/basic_viewer'
+ -X PUT -d @/tmp/basic_viewer.json '/api/access-control/roles/basic_viewer'
```
+ The token that is used in this request is the [service account token](ref:service-accounts).
+
- Or use the `role > from` list and `permission > state` option of your provisioning file:
```yaml
@@ -394,6 +396,20 @@ Here are two ways to achieve this:
state: 'present'
```
+ If your goal is to remove an access to an app you should remove it from the role and update it. For example:
+
+ ```bash
+ # Fetch the role, modify it to remove permissions to kentik-connect-app and increment role version
+ curl -H 'Authorization: Bearer glsa_kcVxDhZtu5ISOZIEt' \
+ -X GET '/api/access-control/roles/basic_viewer' | \
+ jq 'del(.created)| del(.updated) | del(.permissions[].created) | del(.permissions[].updated) | .version += 1' | \
+ jq 'del(.permissions[] | select (.action == "plugins.app:access" and .scope == "plugins:id:kentik-connect-app"))'
+
+ # Update the role
+ curl -H 'Authorization: Bearer glsa_kcVxDhZtu5ISOZIEt' -H 'Content-Type: application/json' \
+ -X PUT -d @/tmp/basic_viewer.json '/api/access-control/roles/basic_viewer'
+ ```
+
### Manage user permissions through teams
In the scenario where you want users to grant access by the team they belong to, we recommend to set users role to `No Basic Role` and let the team assignment assign the role instead.
diff --git a/docs/sources/administration/roles-and-permissions/access-control/rbac-fixed-basic-role-definitions/index.md b/docs/sources/administration/roles-and-permissions/access-control/rbac-fixed-basic-role-definitions/index.md
index f651becaa4e..8458e4d9355 100644
--- a/docs/sources/administration/roles-and-permissions/access-control/rbac-fixed-basic-role-definitions/index.md
+++ b/docs/sources/administration/roles-and-permissions/access-control/rbac-fixed-basic-role-definitions/index.md
@@ -58,8 +58,8 @@ The following tables list permissions associated with basic and fixed roles.
| ------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Grafana Admin | `basic_grafana_admin` | `fixed:roles:reader`
`fixed:roles:writer`
`fixed:users:reader`
`fixed:users:writer`
`fixed:org.users:reader`
`fixed:org.users:writer`
`fixed:ldap:reader`
`fixed:ldap:writer`
`fixed:stats:reader`
`fixed:settings:reader`
`fixed:settings:writer`
`fixed:provisioning:writer`
`fixed:organization:reader`
`fixed:organization:maintainer`
`fixed:licensing:reader`
`fixed:licensing:writer`
`fixed:datasources.caching:reader`
`fixed:datasources.caching:writer`
`fixed:dashboards.insights:reader`
`fixed:datasources.insights:reader`
`fixed:plugins:maintainer`
`fixed:authentication.config:writer`
`fixed:library.panels:creator`
`fixed:library.panels:reader`
`fixed:library.panels:general.reader`
`fixed:library.panels:writer`
`fixed:library.panels:general.writer`
`fixed:groupsync:writer`
`fixed:migrationassistant:migrator` | Default [Grafana server administrator](/docs/grafana//administration/roles-and-permissions/#grafana-server-administrators) assignments. |
| Admin | `basic_admin` | `fixed:reports:reader`
`fixed:reports:writer`
`fixed:datasources:reader`
`fixed:datasources:writer`
`fixed:organization:writer`
`fixed:datasources.permissions:reader`
`fixed:datasources.permissions:writer`
`fixed:teams:writer`
`fixed:dashboards:reader`
`fixed:dashboards:writer`
`fixed:dashboards.permissions:reader`
`fixed:dashboards.permissions:writer`
`fixed:dashboards.public:writer`
`fixed:folders:reader`
`fixed:folders:writer`
`fixed:folders.permissions:reader`
`fixed:folders.permissions:writer`
`fixed:alerting:writer`
`fixed:apikeys:reader`
`fixed:apikeys:writer`
`fixed:alerting.provisioning.secrets:reader`
`fixed:alerting.provisioning:writer`
`fixed:datasources.caching:reader`
`fixed:datasources.caching:writer`
`fixed:dashboards.insights:reader`
`fixed:datasources.insights:reader`
`fixed:plugins:writer`
`fixed:library.panels:creator`
`fixed:library.panels:reader`
`fixed:library.panels:general.reader`
`fixed:library.panels:writer`
`fixed:library.panels:general.writer`
`fixed:alerting.provisioning.status:writer`
`fixed:groupsync:writer` | Default [Grafana organization administrator](ref:rbac-basic-roles) assignments. |
-| Editor | `basic_editor` | `fixed:datasources:explorer`
`fixed:dashboards:creator`
`fixed:folders:creator`
`fixed:annotations:writer`
`fixed:teams:creator` if the `editors_can_admin` configuration flag is enabled
`fixed:alerting:writer`
`fixed:dashboards.insights:reader`
`fixed:datasources.insights:reader`
`fixed:library.panels:creator`
`fixed:library.panels:general.reader`
`fixed:library.panels:general.writer`
`fixed:alerting.provisioning.status:writer` | Default [Editor](ref:rbac-basic-roles) assignments. |
-| Viewer | `basic_viewer` | `fixed:datasources.id:reader`
`fixed:organization:reader`
`fixed:annotations:reader`
`fixed:annotations.dashboard:writer`
`fixed:alerting:reader`
`fixed:plugins.app:reader`
`fixed:dashboards.insights:reader`
`fixed:datasources.insights:reader`
`fixed:library.panels:general.reader`
`fixed:datasources:explorer` if the `viewers_can_edit` configuration flag is enabled | Default [Viewer](ref:rbac-basic-roles) assignments. |
+| Editor | `basic_editor` | `fixed:datasources:explorer`
`fixed:dashboards:creator`
`fixed:folders:creator`
`fixed:annotations:writer`
`fixed:alerting:writer`
`fixed:dashboards.insights:reader`
`fixed:datasources.insights:reader`
`fixed:library.panels:creator`
`fixed:library.panels:general.reader`
`fixed:library.panels:general.writer`
`fixed:alerting.provisioning.status:writer` | Default [Editor](ref:rbac-basic-roles) assignments. |
+| Viewer | `basic_viewer` | `fixed:datasources.id:reader`
`fixed:organization:reader`
`fixed:annotations:reader`
`fixed:annotations.dashboard:writer`
`fixed:alerting:reader`
`fixed:plugins.app:reader`
`fixed:dashboards.insights:reader`
`fixed:datasources.insights:reader`
`fixed:library.panels:general.reader` | Default [Viewer](ref:rbac-basic-roles) assignments. |
| No Basic Role | n/a | | Default [No Basic Role](ref:rbac-basic-roles) |
## Fixed role definitions
@@ -94,7 +94,7 @@ To learn how to use the roles API to determine the role UUIDs, refer to [Manage
| `fixed:authentication.config:writer` | `fixed_0rYhZ2Qnzs8AdB1nX7gexk3fHDw` | `settings:read` for scope `settings:auth.saml:*`
`settings:write` for scope `settings:auth.saml:*` | Read and update authentication and SAML settings. |
| `fixed:dashboards:creator` | `fixed_ZorKUcEPCM01A1fPakEzGBUyU64` | `dashboards:create`
`folders:read` | Create dashboards. |
| `fixed:dashboards:reader` | `fixed_Sgr67JTOhjQGFlzYRahOe45TdWM` | `dashboards:read` | Read all dashboards. |
-| `fixed:dashboards:writer` | `fixed_OK2YOQGIoI1G031hVzJB6rAJQAs` | All permissions from `fixed:dashboards:reader` and
`dashboards:write`
`dashboards:edit`
`dashboards:delete`
`dashboards:create`
`dashboards.permissions:read`
`dashboards.permissions:write` | Read, create, update, and delete all dashboards. |
+| `fixed:dashboards:writer` | `fixed_OK2YOQGIoI1G031hVzJB6rAJQAs` | All permissions from `fixed:dashboards:reader` and
`dashboards:write`
`dashboards:delete`
`dashboards:create`
`dashboards.permissions:read`
`dashboards.permissions:write` | Read, create, update, and delete all dashboards. |
| `fixed:dashboards.insights:reader` | `fixed_JlBJ2_gizP8zhgaeGE2rjyZe2Rs` | `dashboards.insights:read` | Read dashboard insights data and see presence indicators. |
| `fixed:dashboards.permissions:reader` | `fixed_f17oxuXW_58LL8mYJsm4T_mCeIw` | `dashboards.permissions:read` | Read all dashboard permissions. |
| `fixed:dashboards.permissions:writer` | `fixed_CcznxhWX_Yqn8uWMXMQ-b5iFW9k` | All permissions from `fixed:dashboards.permissions:reader` and
`dashboards.permissions:write` | Read and update all dashboard permissions. |
diff --git a/docs/sources/administration/stats-and-license/index.md b/docs/sources/administration/stats-and-license/index.md
index 1643fd505cf..ec926f73c2f 100644
--- a/docs/sources/administration/stats-and-license/index.md
+++ b/docs/sources/administration/stats-and-license/index.md
@@ -25,11 +25,11 @@ This setting contains information about tools that Grafana Server Admins can use
## View Grafana server settings
-> Refer to [Role-based access control]({{< relref "../roles-and-permissions/access-control" >}}) in Grafana Enterprise to understand how you can control access with RBAC permissions.
+> Refer to [Role-based access control](../roles-and-permissions/access-control/) in Grafana Enterprise to understand how you can control access with RBAC permissions.
-If you are a Grafana server administrator, use the Settings tab to view the settings that are applied to your Grafana server via the [Configuration]({{< relref "../../setup-grafana/configure-grafana#configuration-file-location" >}}) file and any environmental variables.
+If you are a Grafana server administrator, use the Settings tab to view the settings that are applied to your Grafana server via the [Configuration](../../setup-grafana/configure-grafana/#configuration-file-location) file and any environmental variables.
-> **Note:** Only Grafana server administrators can access the **Server Admin** menu. For more information about about administrative permissions, refer to [Roles and permissions]({{< relref "../roles-and-permissions#grafana-server-administrators" >}}).
+> **Note:** Only Grafana server administrators can access the **Server Admin** menu. For more information about about administrative permissions, refer to [Roles and permissions](../roles-and-permissions/#grafana-server-administrators).
### View server settings
@@ -38,15 +38,15 @@ If you are a Grafana server administrator, use the Settings tab to view the sett
### Available settings
-For a full list of server settings, refer to [Configuration]({{< relref "../../setup-grafana/configure-grafana#server" >}}).
+For a full list of server settings, refer to [Configuration](../../setup-grafana/configure-grafana/#server).
## View Grafana server stats
-> Refer to [Role-based access control]({{< relref "../roles-and-permissions/access-control" >}}) in Grafana Enterprise to understand how you can control access with RBAC permissions.
+> Refer to [Role-based access control](../roles-and-permissions/access-control/) in Grafana Enterprise to understand how you can control access with RBAC permissions.
If you are a Grafana server admin, then you can view useful statistics about your Grafana server in the Stats & Licensing tab.
-> **Note:** Only Grafana server administrators can access the **Server Admin** menu. For more information about about administrative permissions, refer to [Roles and permissions]({{< relref "../roles-and-permissions#grafana-server-administrators" >}}).
+> **Note:** Only Grafana server administrators can access the **Server Admin** menu. For more information about about administrative permissions, refer to [Roles and permissions](../roles-and-permissions/#grafana-server-administrators).
### View server stats
diff --git a/docs/sources/administration/user-management/manage-dashboard-permissions/index.md b/docs/sources/administration/user-management/manage-dashboard-permissions/index.md
index e87d0193fcc..88087df89c2 100644
--- a/docs/sources/administration/user-management/manage-dashboard-permissions/index.md
+++ b/docs/sources/administration/user-management/manage-dashboard-permissions/index.md
@@ -14,7 +14,7 @@ weight: 500
Dashboard and folder permissions enable you to grant a viewer the ability to edit and save dashboard changes, or limit an editor's permission to modify a dashboard.
-For more information about dashboard permissions, refer to [Dashboard permissions]({{< relref "../../roles-and-permissions/#dashboard-permissions" >}}).
+For more information about dashboard permissions, refer to [Dashboard permissions](../../roles-and-permissions/#dashboard-permissions).
## Grant folder permissions
@@ -23,7 +23,7 @@ When you grant user permissions for folders, that setting applies to all dashboa
### Before you begin
- Ensure you have organization administrator privileges
-- Identify the dashboard folder permissions you want to modify and the users, service accounts or teams to which you want to grant access. For more information about dashboard permissions, refer to [Dashboard permissions]({{< relref "../../roles-and-permissions/#dashboard-permissions" >}}).
+- Identify the dashboard folder permissions you want to modify and the users, service accounts or teams to which you want to grant access. For more information about dashboard permissions, refer to [Dashboard permissions](../../roles-and-permissions/#dashboard-permissions).
**To grant dashboard folder permissions**:
@@ -63,29 +63,9 @@ Grant dashboard permissions when you want to restrict or enhance dashboard acces
1. Select the user, service account, team, or role.
1. Select the permission and click **Save**.
-## Enable viewers to edit (but not save) dashboards and use Explore
+# Edit dashboard permissions
-By default, the viewer organization role does not allow viewers to create dashboards or use the Explore feature. However, by modifying a configuration setting, you can allow viewers to edit a panel and make changes to a dashboard but not save those changes. This setting also enables viewers to use the Explore feature.
-
-This modification is useful for public Grafana installations where you want anonymous users to be able to edit panels and queries but not save or create new dashboards.
-
-### Before you begin
-
-- Ensure that you have access to the Grafana server
-
-**To enable viewers to preview dashboards and use Explore**:
-
-1. Open the Grafana configuration file.
-
- For more information about the Grafana configuration file and its location, refer to [Configuration]({{< relref "../../../setup-grafana/configure-grafana/" >}}).
-
-1. Locate the `viewers_can_edit` parameter.
-1. Set the `viewers_can_edit` value to `true`.
-1. Save your changes and restart Grafana.
-
-## Edit dashboard permissions
-
-Edit dashboard permissions when you are want to enhance or restrict a user's access to a dashboard. For more information about dashboard permissions, refer to [Dashboard permissions]({{< relref "../../roles-and-permissions/#dashboard-permissions" >}}).
+Edit dashboard permissions when you are want to enhance or restrict a user's access to a dashboard. For more information about dashboard permissions, refer to [Dashboard permissions](../../roles-and-permissions/#dashboard-permissions).
### Before you begin
@@ -155,4 +135,4 @@ Folder permissions settings:
Result: User1 has editor permissions for the folder because user1 has permissions on a folder that contains this folder.
-> Refer to [Role-based access Control]({{< relref "../../roles-and-permissions/access-control/" >}}) in Grafana Enterprise to understand how to use RBAC permissions to restrict access to dashboards, folders, administrative functions, and other resources.
+> Refer to [Role-based access Control](../../roles-and-permissions/access-control/) in Grafana Enterprise to understand how to use RBAC permissions to restrict access to dashboards, folders, administrative functions, and other resources.
diff --git a/docs/sources/administration/user-management/manage-org-users/index.md b/docs/sources/administration/user-management/manage-org-users/index.md
index 85c8a8bb882..1364e55882f 100644
--- a/docs/sources/administration/user-management/manage-org-users/index.md
+++ b/docs/sources/administration/user-management/manage-org-users/index.md
@@ -19,7 +19,7 @@ weight: 400
Organization administrators can invite users to join their organization. Organization users have access to organization resources based on their role, which is **Admin**, **Editor**, or **Viewer**. Permissions associated with each role determine the tasks a user can perform in the system.
-For more information about organization user permissions, refer to [Organization users and permissions]({{< relref "../../roles-and-permissions/#organization-users-and-permissions" >}}).
+For more information about organization user permissions, refer to [Organization users and permissions](../../roles-and-permissions/#organization-users-and-permissions).
{{% admonition type="note" %}}
Users added at the organization level will have access to all stacks and services by default, without the ability to be filtered by stack unless Single Sign-On (SSO) or Role-Based Access Control (RBAC) is implemented.
@@ -41,15 +41,15 @@ You can see a list of users with accounts in your Grafana organization. If neces
1. Navigate to **Administration > Users and access > Users**.
{{% admonition type="note" %}}
-If you have [server administrator]({{< relref "../../roles-and-permissions/#grafana-server-administrators" >}}) permissions, you can also [view a global list of users]({{< relref "../server-user-management#view-a-list-of-users" >}}) in the Server Admin section of Grafana.
+If you have [server administrator](../../roles-and-permissions/#grafana-server-administrators) permissions, you can also [view a global list of users](../server-user-management/#view-a-list-of-users) in the Server Admin section of Grafana.
{{% /admonition %}}
## Change a user's organization permissions
-Update user permissions when you want to enhance or restrict a user's access to organization resources. For more information about organization permissions, refer to [Organization roles]({{< relref "../../roles-and-permissions/#organization-roles" >}}).
+Update user permissions when you want to enhance or restrict a user's access to organization resources. For more information about organization permissions, refer to [Organization roles](../../roles-and-permissions/#organization-roles).
{{% admonition type="note" %}}
-Organization roles sync from the authentication provider on user sign-in. To prevent synchronization of organization roles from the authentication provider regardless of their role in the authentication provider, then refer to the `skip_org_role_sync` setting in your Grafana configuration. Refer to [skip org role sync]({{< relref "../../../setup-grafana/configure-grafana/#authgrafana_com-skip_org_role_sync" >}}) for more information.
+Organization roles sync from the authentication provider on user sign-in. To prevent synchronization of organization roles from the authentication provider regardless of their role in the authentication provider, then refer to the `skip_org_role_sync` setting in your Grafana configuration. Refer to [skip org role sync](../../../setup-grafana/configure-grafana/#authgrafana_com-skip_org_role_sync) for more information.
{{% /admonition %}}
### Before you begin
@@ -69,7 +69,7 @@ Organization roles sync from the authentication provider on user sign-in. To pre
1. Click **Update**.
{{% admonition type="note" %}}
-If you have [server administrator]({{< relref "../../roles-and-permissions/#grafana-server-administrators" >}}) permissions, you can also [change a user's organization permissions]({{< relref "../server-user-management/change-user-org-permissions/" >}}) in the Server Admin section.
+If you have [server administrator](../../roles-and-permissions/#grafana-server-administrators) permissions, you can also [change a user's organization permissions](../server-user-management/change-user-org-permissions/) in the Server Admin section.
{{% /admonition %}}
## Invite a user to join an organization
@@ -80,14 +80,14 @@ When you invite users to join an organization, you assign the **Admin**, **Edito
- If the user is new to Grafana, then use their email address to issue an invitation. The system automatically creates the user account on first sign in.
{{% admonition type="note" %}}
-If you have [server administrator]({{< relref "../../roles-and-permissions/#grafana-server-administrators" >}}) permissions, you can also manually [add a user to an organization]({{< relref "../server-user-management/add-remove-user-to-org/" >}}).
+If you have [server administrator](../../roles-and-permissions/#grafana-server-administrators) permissions, you can also manually [add a user to an organization](../server-user-management/add-remove-user-to-org/).
{{% /admonition %}}
### Before you begin
- Ensure you have organization administrator privileges.
- If the user already has access to Grafana, obtain their user name.
-- Determine the permissions you want to assign to the user. For more information about organization permissions, refer to [Organization roles]({{< relref "../../roles-and-permissions/#organization-roles" >}}).
+- Determine the permissions you want to assign to the user. For more information about organization permissions, refer to [Organization roles](../../roles-and-permissions/#organization-roles).
**To invite or add an existing user account to your organization**:
@@ -105,7 +105,7 @@ If you have [server administrator]({{< relref "../../roles-and-permissions/#graf
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Email or username | Either the email or username that the user will use to sign in to Grafana. |
| Name | The user's name. |
- | Role | Click the organization role to assign this user. For more information about organization roles, refer to [Organization roles]({{< relref "../../roles-and-permissions/#organization-roles" >}}).. |
+ | Role | Click the organization role to assign this user. For more information about organization roles, refer to [Organization roles](../../roles-and-permissions/#organization-roles).. |
| Send invite email | Switch to on if your organization has configured. The system sends an email to the user inviting them to sign in to Grafana and join the organization. Switch to off if you are not using email. The user can sign in to Grafana with the email or username you entered. |
1. Click **Submit**.
@@ -156,4 +156,4 @@ This action does not remove the user account from the Grafana server.
1. Click the red **X** to remove the user from the organization.
-> **Note:** If you have [server administrator]({{< relref "../../roles-and-permissions/#grafana-server-administrators" >}}) permissions, you can also [remove a user from an organization]({{< relref "../server-user-management/add-remove-user-to-org/#remove-a-user-from-an-organization" >}}) on the Users page of the Server Admin section.
+> **Note:** If you have [server administrator](../../roles-and-permissions/#grafana-server-administrators) permissions, you can also [remove a user from an organization](../server-user-management/add-remove-user-to-org/#remove-a-user-from-an-organization) on the Users page of the Server Admin section.
diff --git a/docs/sources/administration/user-management/server-user-management/_index.md b/docs/sources/administration/user-management/server-user-management/_index.md
index f5d14efcd25..cd3640c8224 100644
--- a/docs/sources/administration/user-management/server-user-management/_index.md
+++ b/docs/sources/administration/user-management/server-user-management/_index.md
@@ -20,13 +20,13 @@ weight: 100
A _user_ is defined as any individual who can log in to Grafana. Each user is associated with a _role_ that includes _permissions_. Permissions determine the tasks a user can perform in the system.
-If you have [server administrator]({{< relref "../../roles-and-permissions/#grafana-server-administrators" >}}) permissions in Grafana, you can manage all users for a Grafana instance in the Server Admin section:
+If you have [server administrator](../../roles-and-permissions/#grafana-server-administrators) permissions in Grafana, you can manage all users for a Grafana instance in the Server Admin section:
{{< section >}}
-If you have [organization administrator]({{< relref "../../roles-and-permissions/#organization-roles" >}}) permissions and _not_ [server administrator]({{< relref "../../roles-and-permissions/#grafana-server-administrators" >}}) permissions, refer to [Manage users in a organization]({{< relref "../manage-org-users/" >}}).
+If you have [organization administrator](../../roles-and-permissions/#organization-roles) permissions and _not_ [server administrator](../../roles-and-permissions/#grafana-server-administrators) permissions, refer to [Manage users in a organization](../manage-org-users/).
-For more information about user roles and permissions, refer to [Roles and permissions]({{< relref "../../roles-and-permissions/" >}}). For more information about managing users in general, see [User management]({{< relref "../" >}}).
+For more information about user roles and permissions, refer to [Roles and permissions](../../roles-and-permissions/). For more information about managing users in general, see [User management](../).
## View a list of users
@@ -42,7 +42,7 @@ You can see a list of users with accounts on your Grafana server. This action mi
1. Click **Administration** in the left-side menu, **Users and access**, and then **Users**.
{{% admonition type="note" %}}
-If you have [organization administrator]({{< relref "../../roles-and-permissions/#organization-roles" >}}) permissions and _not_ [server administrator]({{< relref "../../roles-and-permissions/#grafana-server-administrators" >}}) permissions, you can still [view of list of users in a given organization]({{< relref "../manage-org-users/#view-a-list-of-organization-users" >}}).
+If you have [organization administrator](../../roles-and-permissions/#organization-roles) permissions and _not_ [server administrator](../../roles-and-permissions/#grafana-server-administrators) permissions, you can still [view of list of users in a given organization](../manage-org-users/#view-a-list-of-organization-users).
{{% /admonition %}}
## View user details
@@ -104,7 +104,7 @@ Edit a user account when you want to modify user login credentials, or delete, d
Add users when you want to manually provide individuals with access to Grafana.
-When you create a user using this method, you must create their password. The user does not receive a notification by email. To invite a user to Grafana and allow them to create their own password, [invite a user to join an organization]({{< relref "../manage-org-users#invite-a-user-to-join-an-organization" >}}).
+When you create a user using this method, you must create their password. The user does not receive a notification by email. To invite a user to Grafana and allow them to create their own password, [invite a user to join an organization](../manage-org-users/#invite-a-user-to-join-an-organization).
When you configure advanced authentication using Oauth, SAML, LDAP, or the Auth proxy, users are created automatically.
@@ -119,10 +119,10 @@ When you configure advanced authentication using Oauth, SAML, LDAP, or the Auth
1. Click **New user**.
1. Complete the fields and click **Create user**.
-When you create a user, the system assigns the user viewer permissions in a default organization, which you can change. You can now [add a user to a second organization]({{< relref "add-remove-user-to-org/" >}}).
+When you create a user, the system assigns the user viewer permissions in a default organization, which you can change. You can now [add a user to a second organization](add-remove-user-to-org/).
{{% admonition type="note" %}}
-If you have [organization administrator]({{< relref "../../roles-and-permissions/#organization-roles" >}}) permissions and _not_ [server administrator]({{< relref "../../roles-and-permissions/#grafana-server-administrators" >}}) permissions, you can still add users by [inviting a user to join an organization]({{< relref "../manage-org-users#invite-a-user-to-join-an-organization" >}}).
+If you have [organization administrator](../../roles-and-permissions/#organization-roles) permissions and _not_ [server administrator](../../roles-and-permissions/#grafana-server-administrators) permissions, you can still add users by [inviting a user to join an organization](../manage-org-users/#invite-a-user-to-join-an-organization).
{{% /admonition %}}
## Force a user to log out of Grafana
diff --git a/docs/sources/administration/user-management/server-user-management/add-remove-user-to-org/index.md b/docs/sources/administration/user-management/server-user-management/add-remove-user-to-org/index.md
index 04ddd0dc490..f67983d8e68 100644
--- a/docs/sources/administration/user-management/server-user-management/add-remove-user-to-org/index.md
+++ b/docs/sources/administration/user-management/server-user-management/add-remove-user-to-org/index.md
@@ -14,7 +14,7 @@ weight: 30
# Add or remove a user in an organization
-Server administrators can add and remove users in organizations. To do this as an organization administrator, see [Manage users in an organization]({{< relref "../../manage-org-users/" >}}).
+Server administrators can add and remove users in organizations. To do this as an organization administrator, see [Manage users in an organization](../../manage-org-users/).
## Add a user to an organization
@@ -24,9 +24,9 @@ You are required to specify an Admin role for each organization. The first user
### Before you begin
-- [Create an organization]({{< relref "../../../organization-management/#create-an-organization" >}})
-- [Add a user]({{< relref "./#add-a-user" >}}) to Grafana
-- Ensure you have [Grafana server administrator privileges]({{< relref "./assign-remove-server-admin-privileges" >}})
+- [Create an organization](../../../organization-management/#create-an-organization)
+- [Add a user](./#add-a-user) to Grafana
+- Ensure you have [Grafana server administrator privileges](../assign-remove-server-admin-privileges/)
**To add a user to an organization**:
@@ -36,14 +36,14 @@ You are required to specify an Admin role for each organization. The first user
1. In the Organizations section, click **Add user to organization**.
1. Select an organization and a role.
- For more information about user permissions, refer to [Organization roles]({{< relref "../../../roles-and-permissions#organization-roles" >}}).
+ For more information about user permissions, refer to [Organization roles](../../../roles-and-permissions/#organization-roles).
1. Click **Add to organization**.
The next time the user signs in, they will be able to navigate to their new organization using the Switch Organizations option in the user profile menu.
{{% admonition type="note" %}}
-If you have [organization administrator]({{< relref "../../../roles-and-permissions#organization-roles" >}}) permissions and _not_ [server administrator]({{< relref "../../../roles-and-permissions#grafana-server-administrators" >}}) permissions, you can still [invite a user to join an organization]({{< relref "../../manage-org-users#invite-a-user-to-join-an-organization" >}}).
+If you have [organization administrator](../../../roles-and-permissions/#organization-roles) permissions and _not_ [server administrator](../../../roles-and-permissions/#grafana-server-administrators) permissions, you can still [invite a user to join an organization](../../manage-org-users/#invite-a-user-to-join-an-organization).
{{% /admonition %}}
## Remove a user from an organization
@@ -62,4 +62,4 @@ Remove a user from an organization when they no longer require access to the das
1. In the Organization section, click **Remove from organization** next to the organization from which you want to remove the user.
1. Click **Confirm removal**.
-> **Note:** If you have [organization administrator]({{< relref "../../../roles-and-permissions#organization-roles" >}}) permissions and _not_ [server administrator]({{< relref "../../../roles-and-permissions#grafana-server-administrators" >}}) permissions, you can still [remove a user from an organization]({{< relref "../../manage-org-users#remove-a-user-from-an-organization" >}}) in the Users section of organization configuration.
+> **Note:** If you have [organization administrator](../../../roles-and-permissions/#organization-roles) permissions and _not_ [server administrator](../../../roles-and-permissions/#grafana-server-administrators) permissions, you can still [remove a user from an organization](../../manage-org-users/#remove-a-user-from-an-organization) in the Users section of organization configuration.
diff --git a/docs/sources/administration/user-management/server-user-management/assign-remove-server-admin-privileges/index.md b/docs/sources/administration/user-management/server-user-management/assign-remove-server-admin-privileges/index.md
index c017f104bdd..31523789db9 100644
--- a/docs/sources/administration/user-management/server-user-management/assign-remove-server-admin-privileges/index.md
+++ b/docs/sources/administration/user-management/server-user-management/assign-remove-server-admin-privileges/index.md
@@ -13,7 +13,7 @@ weight: 20
# Assign or remove Grafana server administrator privileges
-Grafana server administrators are responsible for creating users, organizations, and managing permissions. For more information about the server administration role, refer to [Grafana server administrators]({{< relref "../../../roles-and-permissions#grafana-server-administrators" >}}).
+Grafana server administrators are responsible for creating users, organizations, and managing permissions. For more information about the server administration role, refer to [Grafana server administrators](../../../roles-and-permissions/#grafana-server-administrators).
{{% admonition type="note" %}}
Server administrators are "super-admins" with full permissions to create, read, update, and delete all resources and users in all organizations, as well as update global settings such as licenses. Only grant this permission to trusted users.
@@ -21,7 +21,7 @@ Server administrators are "super-admins" with full permissions to create, read,
## Before you begin
-- [Add a user]({{< relref "../#add-a-user" >}})
+- [Add a user](../#add-a-user)
- Ensure you have Grafana server administrator privileges
**To assign or remove Grafana administrator privileges**:
diff --git a/docs/sources/administration/user-management/server-user-management/change-user-org-permissions/index.md b/docs/sources/administration/user-management/server-user-management/change-user-org-permissions/index.md
index 4569a5ac8f2..4bf9eac2862 100644
--- a/docs/sources/administration/user-management/server-user-management/change-user-org-permissions/index.md
+++ b/docs/sources/administration/user-management/server-user-management/change-user-org-permissions/index.md
@@ -11,11 +11,11 @@ weight: 50
# Change a user's organization permissions
-Update organization permissions when you want to enhance or restrict a user's access to organization resources. For more information about organization permissions, refer to [Organization roles]({{< relref "../../../roles-and-permissions/#organization-roles" >}}).
+Update organization permissions when you want to enhance or restrict a user's access to organization resources. For more information about organization permissions, refer to [Organization roles](../../../roles-and-permissions/#organization-roles).
## Before you begin
-- [Add a user to an organization]({{< relref "./add-remove-user-to-org/" >}})
+- [Add a user to an organization](../add-remove-user-to-org/)
- Ensure you have Grafana server administrator privileges
**To change a user's organization permissions**:
diff --git a/docs/sources/administration/user-management/server-user-management/grant-editor-admin-permissions/index.md b/docs/sources/administration/user-management/server-user-management/grant-editor-admin-permissions/index.md
deleted file mode 100644
index cfefd775975..00000000000
--- a/docs/sources/administration/user-management/server-user-management/grant-editor-admin-permissions/index.md
+++ /dev/null
@@ -1,30 +0,0 @@
----
-aliases:
- - ../../manage-users-and-permissions/manage-server-users/grant-editor-admin-permissions/
-labels:
- products:
- - enterprise
- - oss
-title: Grant editors team creator permissions
-weight: 60
----
-
-# Grant editors team creator permissions
-
-By default, the editor organization role does not allow editors to creator and manage teams. You can allow them to do so using the `editors_can_admin` configuration option.
-
-When `editors_can_admin` is enabled, users with the Editor role in an organization can create teams, and they are Administrators of the teams they create. To learn more about team permissions, refer to [Team management]({{< relref "../../../team-management/" >}}).
-
-## Before you begin
-
-- Ensure that you have access to the Grafana server
-
-**To enable editors with team creator permissions**:
-
-1. Log in to the Grafana server and open the Grafana configuration file.
-
- For more information about the Grafana configuration file and its location, refer to [Configuration]({{< relref "../../../../setup-grafana/configure-grafana/" >}}).
-
-1. Locate the `editors_can_admin` parameter.
-1. Set the `editors_can_admin` value to `true`.
-1. Save your changes and restart the Grafana server.
diff --git a/docs/sources/administration/user-management/user-preferences/index.md b/docs/sources/administration/user-management/user-preferences/index.md
index 41166419d52..eb1bae56a7f 100644
--- a/docs/sources/administration/user-management/user-preferences/index.md
+++ b/docs/sources/administration/user-management/user-preferences/index.md
@@ -50,7 +50,7 @@ Your profile includes your name, user name, and email address, which you can upd
## Edit your preferences
-You can choose the way you would like data to appear in Grafana, including the UI theme, home dashboard, timezone, and first day of the week. You can set these preferences for your own account, for a team, for an organization, or Grafana-wide using configuration settings. Your user preferences take precedence over team, organization, and Grafana default preferences. For more information, see [Grafana preferences]({{< relref "../../organization-preferences/" >}}).
+You can choose the way you would like data to appear in Grafana, including the UI theme, home dashboard, timezone, and first day of the week. You can set these preferences for your own account, for a team, for an organization, or Grafana-wide using configuration settings. Your user preferences take precedence over team, organization, and Grafana default preferences. For more information, see [Grafana preferences](../../organization-preferences/).
- **UI theme** determines whether Grafana appears in light mode or dark mode. By default, UI theme is set to dark mode.
- **Home dashboard** refers to the dashboard you see when you sign in to Grafana. By default, this is set to the Home dashboard.
@@ -85,7 +85,7 @@ Every user is a member of at least one organization. You can have different role
1. Click the user icon in the top right corner of the page and select **Profile**.
1. Scroll down to the Organizations section and review the following information:
- **Name**: The name of the organizations of which you are a member.
- - **Role**: The role to which you are assigned in the organization. For more information about roles and permissions, refer to [Organization users and permissions]({{< relref "../../roles-and-permissions/#organization-users-and-permissions" >}}).
+ - **Role**: The role to which you are assigned in the organization. For more information about roles and permissions, refer to [Organization users and permissions](../../roles-and-permissions/#organization-users-and-permissions).
- **Current**: Grafana indicates the organization that you are currently signed into as _Current_. If you are a member of multiple organizations, you can click **Select** to switch to that organization.
## View your Grafana sessions
diff --git a/docs/sources/alerting/_index.md b/docs/sources/alerting/_index.md
index 601ae34e4e1..8362360d188 100644
--- a/docs/sources/alerting/_index.md
+++ b/docs/sources/alerting/_index.md
@@ -25,7 +25,7 @@ cards:
items:
- title: Introduction
href: ./fundamentals/
- description: Learn more about the fundamentals and available features that help you create, manage, and respond to alerts; and improve your team’s ability to resolve issues quickly.
+ description: Learn more about the fundamentals and available features that help you create, manage, and respond to alerts; and improve your team's ability to resolve issues quickly.
height: 24
- title: Configure alert rules
href: ./alerting-rules/
@@ -55,7 +55,8 @@ Monitor your incoming metrics data or log entries and set up your Grafana Alerti
In this way, you eliminate the need for manual monitoring and provide a first line of defense against system outages or changes that could turn into major incidents.
-Using Grafana Alerting, you create queries and expressions from multiple data sources — no matter where your data is stored — giving you the flexibility to combine your data and alert on your metrics and logs in new and unique ways. You can then create, manage, and take action on your alerts from a single, consolidated view, and improve your team’s ability to identify and resolve issues quickly.
+Using Grafana Alerting, you create queries and expressions from multiple data sources, no matter where you store your data, giving you the flexibility to combine your data and alert on your metrics and logs in new and unique ways.
+You can then create, manage, and take action on your alerts from a single, consolidated view, and improve your team's ability to identify and resolve issues quickly.
## Explore
diff --git a/docs/sources/alerting/alerting-rules/create-grafana-managed-rule.md b/docs/sources/alerting/alerting-rules/create-grafana-managed-rule.md
index 2ad18a60ab6..3b30819b328 100644
--- a/docs/sources/alerting/alerting-rules/create-grafana-managed-rule.md
+++ b/docs/sources/alerting/alerting-rules/create-grafana-managed-rule.md
@@ -118,15 +118,17 @@ refs:
# Configure Grafana-managed alert rules
-Grafana-managed rules can query data from multiple data sources in a single alert rule. They are the most flexible [alert rule type](ref:alert-rules). You can also add expressions to transform your data, set alert conditions, and images in alert notifications.
+Grafana-managed rules can query data from multiple data sources in a single alert rule.
+They're the most flexible [alert rule type](ref:alert-rules).
+You can also add expressions to transform your data, set alert conditions, and images in alert notifications.
-{{% admonition type="note" %}}
+{{< admonition type="note" >}}
In Grafana Cloud, the number of Grafana-managed alert rules you can create depends on your Grafana Cloud plan.
- Free Forever plan: You can create up to 100 free alert rules, with each alert rule having a maximum of 1000 alert instances.
- All paid plans (Pro and Advanced): They have a soft limit of 2000 alert rules and support unlimited alert instances. To increase the limit, open a support ticket from the [Cloud portal](/docs/grafana-cloud/account-management/support/).
-{{% /admonition %}}
+{{< /admonition >}}
To create or edit Grafana-managed alert rules, follow the instructions below. For a practical example, check out our [tutorial on getting started with Grafana alerting](http://grafana.com/tutorials/alerting-get-started/).
@@ -144,11 +146,11 @@ Only users with **Edit** permissions for the folder storing the rules can edit o
You can use default or advanced options for Grafana-managed alert rule creation. The default options streamline rule creation with a cleaner header and a single query and condition. For more complex rules, use advanced options to add multiple queries and expressions.
-You can toggle between the two options. Once you have created an alert rule, the system defaults to your previous choice for the next alert rule.
+You can toggle between the two options.
+After you have created an alert rule, the system defaults to your previous choice for the next alert rule.
-Switching from advanced to default may result in queries and expressions that cannot be converted. In this case, a warning message asks if you want to continue to reset to default settings.
-
-Default and advanced options are enabled by default for Grafana Cloud users and this feature is being rolled out progressively. OSS users can enable them via the [`alertingQueryAndExpressionsStepMode` feature toggle](/setup-grafana/configure-grafana/feature-toggles/).
+Switching from advanced to default may result in queries and expressions that can't be converted.
+In this case, a warning message asks if you want to continue to reset to default settings.
{{< docs/shared lookup="alerts/configure-alert-rule-name.md" source="grafana" version="" >}}
@@ -171,9 +173,10 @@ You can toggle between **Default** and **Advanced** options. If the [Default vs.
{{< collapse title="Advanced options" >}}
1. Select a data source.
-1. From the **Options** dropdown, specify a [time range](ref:time-units-and-relative-ranges).
+1. From the **Options** drop-down menu, specify a [time range](ref:time-units-and-relative-ranges).
- Note that Grafana Alerting only supports fixed relative time ranges, for example, `now-24hr: now`. It does not support absolute time ranges: `2021-12-02 00:00:00 to 2021-12-05 23:59:592` or semi-relative time ranges: `now/d to: now`.
+ Note that Grafana Alerting only supports fixed relative time ranges, for example, `now-24hr: now`.
+ It doesn't support absolute time ranges: `2021-12-02 00:00:00 to 2021-12-05 23:59:592` or semi-relative time ranges: `now/d to: now`.
1. Add a query.
@@ -224,7 +227,8 @@ To do this, you need to make sure that your alert rule is in the right evaluatio
The pending period is the period in which an alert rule can be in breach of the condition until it fires.
- Once a condition is met, the alert goes into the **Pending** state. If the condition remains active for the duration specified, the alert transitions to the **Firing** state, else it reverts to the **Normal** state.
+ After a condition is met, the alert goes into the **Pending** state.
+ If the condition remains active for the duration specified, the alert transitions to the **Firing** state, else it reverts to the **Normal** state.
1. Turn on pause alert notifications, if required.
@@ -255,20 +259,16 @@ Complete the following steps to set up notifications.
1. Choose this option to select an existing [contact point](ref:contact-points).
- All notifications for this alert rule are sent to this contact point automatically and notification policies are not used.
+ All notifications for this alert rule are sent to this contact point automatically and notification policies aren't used.
1. You can also optionally select a mute timing as well as groupings and timings to define when not to send notifications.
- {{< admonition type="note" >}}
- An auto-generated notification policy is generated. Only admins can view these auto-generated policies from the **Notification policies** list view. Any changes have to be made in the alert rules form. {{< /admonition >}}
-
**Use notification policy**
- 1. Choose this option to use the [notification policy tree](ref:notification-policies) to direct your notifications.
+ 1. Choose this option to use the [notification policy tree](ref:notification-policies) to handle alert notifications.
- {{< admonition type="note" >}}
- All alert rules and instances, irrespective of their labels, match the default notification policy. If there are no nested policies, or no nested policies match the labels in the alert rule or alert instance, then the default notification policy is the matching policy.
- {{< /admonition >}}
+ All notifications for this alert rule are managed by the notification policy tree, which routes alerts based on their labels.
+ If an alert doesn't match a specific policy, the default notification policy applies, ensuring all alerts are handled.
1. Preview your alert instance routing set up.
diff --git a/docs/sources/alerting/alerting-rules/link-alert-rules-to-panels.md b/docs/sources/alerting/alerting-rules/link-alert-rules-to-panels.md
index aeaddf1e405..746cb778052 100644
--- a/docs/sources/alerting/alerting-rules/link-alert-rules-to-panels.md
+++ b/docs/sources/alerting/alerting-rules/link-alert-rules-to-panels.md
@@ -44,6 +44,10 @@ Grafana allows you to link an alert rule to a dashboard panel. This can help you
An alert rule is linked to a panel by setting the [`dashboardUId` and `panelId` annotations](ref:annotations). Both annotations must be set together.
+{{% admonition type="tutorial" %}}
+For a hands-on example of integrating alert rules with dashboards, check out [Part 5 of our Get Started with Grafana Alerting tutorial](http://www.grafana.com/tutorials/alerting-get-started-pt5/).
+{{% /admonition %}}
+
## Link alert rules to panels
When configuring the alert rule, you can set the dashboard and panel annotations as shown in this [video](https://youtu.be/ClLp-iSoaSY?si=qKWnvSVaQuvYcuw9&t=170).
diff --git a/docs/sources/alerting/alerting-rules/templates/_index.md b/docs/sources/alerting/alerting-rules/templates/_index.md
index cf211fed7b6..f6da85e1977 100644
--- a/docs/sources/alerting/alerting-rules/templates/_index.md
+++ b/docs/sources/alerting/alerting-rules/templates/_index.md
@@ -190,9 +190,7 @@ low
In this example, the value of the `severity` label is determined by the query value, and the possible options are `critical`, `high`, `medium`, or `low`. You can then use the `severity` label to change their notifications—for instance, sending `critical` alerts immediately or routing `low` alerts to a specific team for further review.
-{{% admonition type="note" %}}
-You should avoid displaying query values in labels, as this may create numerous unique alert instances—one for each distinct label value. Instead, use annotations for query values.
-{{% /admonition %}}
+{{< docs/shared lookup="alerts/note-dynamic-labels.md" source="grafana" version="" >}}
### How to template a label
diff --git a/docs/sources/alerting/alerting-rules/templates/examples.md b/docs/sources/alerting/alerting-rules/templates/examples.md
index c8c6f9dbb40..e9ee1a8015b 100644
--- a/docs/sources/alerting/alerting-rules/templates/examples.md
+++ b/docs/sources/alerting/alerting-rules/templates/examples.md
@@ -209,9 +209,7 @@ In this example, the `severity` label is determined by the query value:
You can then use the `severity` label to control how alerts are handled. For instance, you could send `critical` alerts immediately, while routing `low` severity alerts to a team for further investigation.
-{{% admonition type="note" %}}
-You should avoid displaying query values in labels, as this may create many alert instances—one for each distinct label value. Instead, use annotations to convey query values.
-{{% /admonition %}}
+{{< docs/shared lookup="alerts/note-dynamic-labels.md" source="grafana" version="" >}}
### Based on query label
diff --git a/docs/sources/alerting/configure-notifications/create-silence.md b/docs/sources/alerting/configure-notifications/create-silence.md
index 6f781a60ce3..5cf6f4a9c04 100644
--- a/docs/sources/alerting/configure-notifications/create-silence.md
+++ b/docs/sources/alerting/configure-notifications/create-silence.md
@@ -61,7 +61,7 @@ refs:
# Configure silences
-Silences stop notifications from getting created and last for only a specified window of time. Use them to temporarily prevent alert notifications, such as during incident response or a maintenance window.
+Silences stop notifications from being created for a specified time window but do not interrupt alert evaluation. Use them to temporarily prevent alert notifications, such as during incident response or a maintenance window.
{{< admonition type="note" >}}
Silences are assigned to a [specific Alertmanager](ref:alertmanager-architecture) and only suppress notifications for alerts managed by that Alertmanager.
diff --git a/docs/sources/alerting/configure-notifications/manage-contact-points/_index.md b/docs/sources/alerting/configure-notifications/manage-contact-points/_index.md
index ce35c4c75e8..215ed1926dc 100644
--- a/docs/sources/alerting/configure-notifications/manage-contact-points/_index.md
+++ b/docs/sources/alerting/configure-notifications/manage-contact-points/_index.md
@@ -86,12 +86,7 @@ refs:
destination: /docs/grafana//alerting/configure-notifications/manage-contact-points/integrations/configure-mqtt/
- pattern: /docs/grafana-cloud/
destination: /docs/grafana-cloud/alerting-and-irm/alerting/configure-notifications/manage-contact-points/integrations/configure-mqtt/
- alertmanager-architecture:
- - pattern: /docs/grafana/
- destination: /docs/grafana//alerting/configure-notifications/#alertmanager-architecture
- - pattern: /docs/grafana-cloud/
- destination: /docs/grafana-cloud/alerting-and-irm/alerting/configure-notifications/#alertmanager-architecture
- external-alertmanager:
+ configure-alertmanager:
- pattern: /docs/grafana/
destination: /docs/grafana//alerting/set-up/configure-alertmanager/
- pattern: /docs/grafana-cloud/
@@ -101,13 +96,23 @@ refs:
destination: /docs/grafana//alerting/configure-notifications/template-notifications/manage-notification-templates/
- pattern: /docs/grafana-cloud/
destination: /docs/grafana-cloud/alerting-and-irm/alerting/configure-notifications/template-notifications/manage-notification-templates/
+ configure-grafana-alerts:
+ - pattern: /docs/grafana/
+ destination: /docs/grafana//alerting/alerting-rules/create-grafana-managed-rule/
+ - pattern: /docs/grafana-cloud/
+ destination: /docs/grafana-cloud/alerting-and-irm/alerting/alerting-rules/create-grafana-managed-rule/
+ configure-contact-points:
+ - pattern: /docs/grafana/
+ destination: /docs/grafana//alerting/configure-notifications/manage-contact-points/
+ - pattern: /docs/grafana-cloud/
+ destination: /docs/grafana-cloud/alerting-and-irm/alerting/configure-notifications/manage-contact-points/
---
# Configure contact points
Use contact points to specify where to receive alert notifications. Contact points contain the configuration for sending alert notifications, including destinations like email, Slack, OnCall, webhooks, and their notification messages.
-A contact point can have one or multiple destinations, known as [contact point integrations](#list-of-supported-integrations). Alert notifications are sent to each integration within the chosen contact point.
+A contact point can have one or multiple destinations, known as [contact point integrations](#supported-contact-point-integrations). Alert notifications are sent to each integration within the chosen contact point.
On the **Contact Points** tab, you can:
@@ -119,9 +124,42 @@ On the **Contact Points** tab, you can:
- Delete contact points. Note that you cannot delete contact points that are in use by a notification policy. To proceed, either delete the notification policy or update it to use another contact point.
{{% admonition type="note" %}}
-Contact points are assigned to a [specific Alertmanager](ref:alertmanager-architecture) and cannot be used by notification policies in other Alertmanagers.
+Contact points are assigned to a [specific Alertmanager](ref:configure-alertmanager) and cannot be used by notification policies in other Alertmanagers.
{{% /admonition %}}
+## Supported contact point integrations
+
+Each contact point integration has its own configuration options and setup process. The following list shows the contact point integrations supported by Grafana.
+
+{{< column-list >}}
+
+- Alertmanager
+- [AWS SNS](ref:sns)
+- Cisco Webex Teams
+- DingDing
+- [Discord](ref:discord)
+- [Email](ref:email)
+- [Google Chat](ref:gchat)
+- [Grafana OnCall](ref:oncall)
+- Kafka REST Proxy
+- Line
+- [Microsoft Teams](ref:teams)
+- [MQTT](ref:mqtt)
+- [Opsgenie](ref:opsgenie)
+- [PagerDuty](ref:pagerduty)
+- Pushover
+- Sensu Go
+- [Slack](ref:slack)
+- [Telegram](ref:telegram)
+- Threema Gateway
+- VictorOps
+- [Webhook](ref:webhook)
+- WeCom
+
+{{< /column-list >}}
+
+Some of the integrations above are not supported by Prometheus Alertmanager. For the list of supported integrations, refer to the [Prometheus Alertmanager receiver settings](https://prometheus.io/docs/alerting/latest/configuration/#receiver-integration-settings).
+
## Add a contact point
Complete the following steps to add a contact point.
@@ -132,7 +170,7 @@ Complete the following steps to add a contact point.
1. On the **Contact Points** tab, click **+ Add contact point**.
1. Enter a descriptive name for the contact point.
1. From **Integration**, select a type and fill out mandatory fields. For example, if you choose email, enter the email addresses. Or if you choose Slack, enter the Slack channel and users who should be contacted.
-1. Some contact point integrations, like email or Webhook, have optional settings. In **Optional settings**, specify additional settings for the selected contact point integration.
+1. Some [contact point integrations](#supported-contact-point-integrations), like email or Webhook, have optional settings. In **Optional settings**, specify additional settings for the selected contact point integration.
1. In Notification settings, optionally select **Disable resolved message** if you do not want to be notified when an alert resolves.
1. Save your changes.
@@ -148,6 +186,16 @@ To add another integration to a contact point, complete the following steps.
- In **Optional settings**, specify additional settings for the selected contact point integration.
1. Save your changes.
+## Customize notification messages
+
+In contact points, you can also customize notification messages. For example, when setting up an email contact point integration, click **Message** or **Subject** to modify it.
+
+By default, notification messages include common alert details, which are usually sufficient for most cases.
+
+If necessary, you can customize the content and format of notification messages. You can create a custom notification template, which can then be applied to one or more contact points.
+
+On the **Notification templates** tab, you can view, edit, copy or delete notification templates. Refer to [manage notification templates](ref:manage-notification-templates) for instructions on selecting or creating a template for a contact point.
+
## Test a contact point
Testing a contact point is only available for Grafana Alertmanager. Complete the following steps to test a contact point.
@@ -159,45 +207,9 @@ Testing a contact point is only available for Grafana Alertmanager. Complete the
1. Choose whether to send a predefined test notification or choose custom to add your own custom annotations and labels to include in the notification.
1. Click **Send test notification** to fire the alert.
-## Customize notification messages
+## Enable notifications for a contact point
-In contact points, you can also customize notification messages. For example, when setting up an email contact point integration, click **Message** or **Subject** to modify it.
+After creating a contact point, you can enable it to receive alert notifications using one of the following methods:
-By default, notification messages include common alert details, which are usually sufficient for most cases.
-
-If necessary, you can customize the content and format of notification messages. You can create a custom notification template, which can then be applied to one or more contact points.
-
-On the **Notification templates** tab, you can view, edit, copy or delete notification templates. Refer to [manage notification templates](ref:manage-notification-templates) for instructions on selecting or creating a template for a contact point.
-
-## List of supported integrations
-
-Each contact point integration has its own configuration options and setup process. In most cases, this involves providing an API key or a Webhook URL.
-
-The following table lists the contact point integrations supported by Grafana.
-
-| Name | Type |
-| ---------------------------- | ------------------------- |
-| Alertmanager | `prometheus-alertmanager` |
-| [Amazon SNS](ref:sns) | `sns` |
-| Cisco Webex Teams | `webex` |
-| DingDing | `dingding` |
-| [Discord](ref:discord) | `discord` |
-| [Email](ref:email) | `email` |
-| [Google Chat](ref:gchat) | `googlechat` |
-| [Grafana Oncall](ref:oncall) | `oncall` |
-| Kafka REST Proxy | `kafka` |
-| Line | `line` |
-| [Microsoft Teams](ref:teams) | `teams` |
-| [MQTT](ref:mqtt) | `mqtt` |
-| [Opsgenie](ref:opsgenie) | `opsgenie` |
-| [Pagerduty](ref:pagerduty) | `pagerduty` |
-| Pushover | `pushover` |
-| Sensu Go | `sensugo` |
-| [Slack](ref:slack) | `slack` |
-| [Telegram](ref:telegram) | `telegram` |
-| Threema Gateway | `threema` |
-| VictorOps | `victorops` |
-| [Webhook](ref:webhook) | `webhook` |
-| WeCom | `wecom` |
-
-Some of these integrations are not compatible with [external Alertmanagers](ref:external-alertmanager). For the list of Prometheus Alertmanager integrations, refer to the [Prometheus Alertmanager receiver settings](https://prometheus.io/docs/alerting/latest/configuration/#receiver-integration-settings).
+- **Assign it to alert rules** – Select the contact point in the [notifications options for Grafana-managed alert rules](ref:configure-grafana-alerts) to directly associate it with specific alerts.
+- **Assign it to notification policies** – Add the contact point to one or more [notification policies](ref:configure-contact-points), which manage the alert notifications you want the contact point to receive.
diff --git a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-amazon-sns.md b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-amazon-sns.md
index 84274e64043..9c449640511 100644
--- a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-amazon-sns.md
+++ b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/configure-amazon-sns.md
@@ -14,11 +14,32 @@ labels:
menuTitle: Amazon SNS
title: Configure Amazon SNS for Alerting
weight: 100
+refs:
+ notification-templates:
+ - pattern: /docs/grafana/
+ destination: /docs/grafana//alerting/configure-notifications/template-notifications/
+ - pattern: /docs/grafana-cloud/
+ destination: /docs/grafana-cloud/alerting-and-irm/alerting/configure-notifications/template-notifications/
+ configure-contact-points:
+ - pattern: /docs/grafana/
+ destination: /docs/grafana//alerting/configure-notifications/manage-contact-points/
+ - pattern: /docs/grafana-cloud/
+ destination: /docs/grafana-cloud/alerting-and-irm/alerting/configure-notifications/manage-contact-points/
+ test-contact-point:
+ - pattern: /docs/grafana/
+ destination: /docs/grafana//alerting/configure-notifications/manage-contact-points/#test-a-contact-point
+ - pattern: /docs/grafana-cloud/
+ destination: /docs/grafana-cloud/alerting-and-irm/alerting/configure-notifications/manage-contact-points/#test-a-contact-point
+ enable-contact-point-notifications:
+ - pattern: /docs/grafana/
+ destination: /docs/grafana//alerting/configure-notifications/manage-contact-points/#enable-notifications-for-a-contact-point
+ - pattern: /docs/grafana-cloud/
+ destination: /docs/grafana-cloud/alerting-and-irm/alerting/configure-notifications/manage-contact-points/#enable-notifications-for-a-contact-point
---
-# Configure Amazon SNS for Alerting
+# Configure Amazon SNS notifications
-Use the Grafana Alerting - Amazon SNS integration to send notifications to Amazon SNS when your alerts are firing. You can receive notifications via the various subscriber channels supported by SNS.
+Use the Amazon SNS integration in a contact point to send alert notifications to a SNS topic. Then, configure the SNS topic to forward notifications to distinct subscriber channels used in your SNS account.
## Before you begin
@@ -27,71 +48,51 @@ Before you begin, ensure you have the following:
- **AWS SNS Topic**: An SNS topic to send notifications to.
- **AWS IAM Identity with necessary access**: An IAM identity (e.g. user, role) with the necessary permissions to publish messages to the SNS topic.
-For an example setup, see [Example Minimal Setup Using Assumed IAM Role]({{< relref "#example-minimal-setup-using-assumed-iam-role" >}}).
+For a minimal setup, refer to [Example using an Access Key](#example-using-an-access-key).
-## Adding the SNS Contact Point in Grafana
+## Configure Amazon SNS for a contact point
-With AWS resources configured, proceed to add SNS as a contact point in Grafana.
+To create a contact point with a SNS integration, complete the following steps.
-- Navigate to **Alerts & IRM** -> **Alerting** -> **Contact points**.
-- Click on **"Add contact point"**.
-- **Name**: Enter a descriptive name (e.g., `AWS SNS`).
-- Choose **"AWS SNS"** from the list of contact point types.
+1. Navigate to **Alerts & IRM** -> **Alerting** -> **Contact points**.
+1. Click **+ Add contact point**.
+1. Enter a name for the contact point.
+1. From the **Integration** list, select **AWS SNS**.
+1. Set up the required [settings](#sns-settings) for your SNS configuration.
+1. Click **Save contact point**.
-### 2. Configure SNS Settings
+For more details on contact points, including how to test them and enable notifications, refer to [Configure contact points](ref:configure-contact-points).
-#### SNS Settings
+## SNS Settings
- **The Amazon SNS API URL**: (Optional) The SNS API URL, e.g., `https://sns.us-east-2.amazonaws.com`. If not specified, the SNS API URL from the SNS SDK will be used.
- **Signature Version (sigv4)**: Configures AWS's Signature Verification 4 signing process to sign requests.
- **Region**: (Optional) The AWS region. If blank, the region from the default credentials chain is used.
- - **Access Key**: The AWS API access key.
- - **Secret Key**: The AWS API secret key.
+ - **Access Key** : (Optional) The AWS API access key.
+ - **Secret Key**: (Optional) The AWS API secret key.
+ > Both `Access Key` and `Secret Key` must be provided together or left blank together.
+ >
+ > If left blank, Grafana searches for credentials using the default credentials chain, including environment variables (`AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`), the shared credential file, and EC2 instance roles.
- **Profile**: (Optional) Named AWS profile used to authenticate.
- **Role ARN**: (Optional) The ARN of an AWS IAM role to assume for authentication, serving as an alternative to using AWS API keys.
- **SNS topic ARN**: (Optional) If you don't specify this value, you must specify a value for the `Phone number` or `Target ARN`. If you are using a FIFO SNS topic you should set a message group interval longer than 5 minutes to prevent messages with the same group key being deduplicated by the SNS default deduplication window.
- **Phone number**: (Optional) Phone number if message is delivered via SMS in E.164 format. If you don't specify this value, you must specify a value for the `SNS topic ARN` or `Target ARN`.
- **Target ARN**: (Optional) The mobile platform endpoint ARN if message is delivered via mobile notifications. If you don't specify this value, you must specify a value for the `SNS topic ARN` or `Phone number`.
-- **Subject**: (Optional) Customize the subject line or use the default template. This field is templateable.
-- **Message**: (Optional) Customize the message content or use the default template. This field is templateable.
+- **Subject**: (Optional) Customize the subject. This field supports [notification templates](ref:notification-templates) and, by default, uses the default title template (`default.title`). It **cannot be an empty string**.
+- **Message**: (Optional) Customize the message. This field supports [notification templates](ref:notification-templates) and, by default, uses the default message template (`default.message`).
- **Attributes**: (Optional) Add any SNS message attributes.
-{{< admonition type="note" >}}
-Both `Access Key` and `Secret Key` must be provided together or left blank together. If blank it defaults to a chain of credential
-providers to search for credentials in environment variables, shared credential file, and EC2 Instance Roles.
+## Example using an Access Key
-Environment variables: `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`.
-{{< /admonition >}}
+This section outlines a minimal setup to configure Amazon SNS with Alerting.
-### 3. Test & Save the Contact Point
-
-- Click **"Test"** to verify that the SNS configuration is working correctly.
-- After the test is successful, click **"Save contact point"** to add the SNS contact point.
-
-### 4. Next steps
-
-The SNS contact point is ready to receive alert notifications.
-
-To add this contact point to your alert, complete the following steps.
-
-1. In Grafana, navigate to **Alerting** > **Alert rules**.
-1. Edit or create a new alert rule.
-1. Scroll down to the **Configure labels and notifications** section.
-1. Under Notifications click **Select contact point**.
-1. From the drop-down menu, select the previously created contact point.
-1. **Click Save rule and exit**.
-
-## Example Minimal Setup Using Assumed IAM Role
-
-This section outlines a minimal setup to configure SNS with Grafana using an assumed IAM Role.
-
-### 1. Create an SNS Topic
+### 1. Create an SNS Topic and Email Subscriber
1. **Navigate to SNS in AWS Console**:
- Go to the [Amazon SNS Console](https://console.aws.amazon.com/sns/v3/home).
-2. **Create a new topic** [[AWS Documentation](https://docs.aws.amazon.com/sns/latest/dg/sns-create-topic.html)]:
+2. **Create a new topic**:
- On the **Topics** page, choose **"Create topic"**.
- Select **"Standard"** as the type.
@@ -99,105 +100,70 @@ This section outlines a minimal setup to configure SNS with Grafana using an ass
- **Encryption**: Leave disabled for this minimal setup.
- Click **"Create topic"**.
-3. (Optional) **Add an email subscriber to help test** [[AWS Documentation](https://docs.aws.amazon.com/sns/latest/dg/sns-email-notifications.html)]:
+3. (Optional) **Add an email subscriber to help test**:
- Within your newly created topic, click on **"Create subscription"**.
- **Protocol**: Choose `Email`.
- **Endpoint**: Enter your email address to receive test notifications.
- Click **"Create subscription"**.
- **Confirm Subscription**: Check your email and confirm the subscription by clicking the provided link.
-### 2. Create an IAM Role
+### 2. Create an IAM Policy, User, and Access Key
1. **Navigate to IAM in AWS Console**:
- Go to the [IAM Console](https://console.aws.amazon.com/iam/home).
-2. **Create a new role** [[AWS Documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-user.html)]:
+2. **Create a new policy**:
- - On the **Roles** page, choose **"Create role"**.
- - **Trusted Entity**: Select **"This account"**.
- - Click **"Next"** until the end, name it (e.g., `GrafanaSNSRole`), and click **"Create role"**.
-
-3. **Attach Inline Policy**:
-
- - After creating the role, select it and navigate to the **"Permissions"** tab.
- - Click on **"Add permission"** > **"Create inline policy"**.
+ - On the **Policies** page, choose **"Create policy"**.
- Switch to the **"JSON"** tab and paste the following policy, replacing `Resource` with your SNS topic ARN:
- ```json
- {
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Action": ["sns:Publish", "sns:GetTopicAttributes"],
- "Resource": "arn:aws:sns:::"
- }
- ]
- }
- ```
+ ```json
+ {
+ "Version": "2012-10-17",
+ "Statement": [
+ {
+ "Effect": "Allow",
+ "Action": ["sns:Publish", "sns:GetTopicAttributes"],
+ "Resource": "arn:aws:sns:::"
+ }
+ ]
+ }
+ ```
- Click **"Next"**, name it (e.g., `SNSPublishPolicy`), and click **"Create policy"**.
-### 3. Create an IAM Policy
-
-1. **Create a new policy to allow assuming the above IAM role** [[AWS Documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_create-console.html)]:
-
- - In the IAM Console, on the **Policies** page, choose **"Create policy"**.
- - Switch to the **"JSON"** tab and paste the following policy, replacing `Resource` with the ARN of the role you created earlier:
-
- ```json
- {
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Action": "sts:AssumeRole",
- "Resource": "arn:aws:iam:::role/GrafanaSNSRole"
- }
- ]
- }
- ```
-
-2. **Review and Create**:
- - Click **"Next"**, name it (e.g., `AssumeSNSRolePolicy`), and click **"Create policy"**.
-
-### 4. Create an IAM User
-
-1. **Create a new IAM user to assume the above role** [[AWS Documentation](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_create.html)]:
+3. **Create a new IAM user and assign the policy**
- In the IAM Console, on the **Users** page, choose **"Create user"**.
- - Enter a **User name**, e.g., `grafana-sns-user`.
+ - Enter a **User name**, e.g., `alerting-sns-user`.
- Click **"Next"**.
- - Select **"Attach policies directly"**.
- - Search for the policy you created earlier (`AssumeSNSRolePolicy`) and select it.
+ - In **Set permissions**, select **"Attach policies directly"**.
+ - Search for the policy you created earlier (`SNSPublishPolicy`) and select it.
- Click **"Next"** , and click **"Create user"**.
-2. **Generate credentials**:
+4. **Create an Access Key**:
- Within your newly created user, click on **"Create access key"**.
- Select an appropriate use-case, e.g., `Application running outside AWS`.
- Click **"Next"** , and click **"Create access key"**.
- - **Save Credentials**: Note the **Access key ID** and **Secret access key**. You'll need these for Grafana's configuration.
+ - **Save Credentials**: Note the **Access key ID** and **Secret access key** that are required in the next step.
-### 5. Add the SNS Contact Point in Grafana
+### 3. Configure the SNS Contact Point in Grafana
-After creating the IAM user and obtaining the necessary credentials, proceed to [configure the SNS contact point in Grafana]({{< relref "#adding-the-sns-contact-point-in-grafana" >}}) using the following details:
+Follow the steps in [configure Amazon SNS for a contact point](#configure-amazon-sns-for-a-contact-point), using the settings below and replacing the placeholders with the SNS and IAM values created in the previous steps.
-- **The Amazon SNS API URL**: `https://sns.us-east-1.amazonaws.com`
+- **The Amazon SNS API URL**: `https://sns..amazonaws.com`
- **Signature Version (sigv4)**:
- - **Region**: `us-east-1`
+ - **Region**: ``
- **Access Key**: ``.
- **Secret Key**: ``
- - **Role ARN**: `arn:aws:iam:::role/GrafanaSNSRole`
-- **SNS topic ARN**: `arn:aws:sns:::My-Topic`
+- **SNS topic ARN**: `arn:aws:sns:::`
-{{< admonition type="note" >}}
-Replace the placeholder values (`https://sns.us-east-1.amazonaws.com`, `us-east-1`, ``, ``, `arn:aws:iam:::role/GrafanaSNSRole`, `arn:aws:sns:::My-Topic`) with your actual AWS credentials and ARNs.
-{{< /admonition >}}
+[Test the contact point](ref:test-contact-point) to ensure it's working, or [enable notifications](ref:enable-contact-point-notifications) for it.
## Additional Resources
+- [Configure contact points](ref:configure-contact-points)
- [Amazon SNS Documentation](https://docs.aws.amazon.com/sns/index.html)
-- [AWS IAM Documentation](https://docs.aws.amazon.com/iam/index.html)
-- [Prometheus Alertmanager SNS Integration](https://prometheus.io/docs/alerting/configuration/#sns_config)
-- [Cloudwatch AWS Authentication]({{< relref "../../../../datasources/aws-cloudwatch/aws-authentication" >}})
+- [Amazon IAM Documentation](https://docs.aws.amazon.com/iam/index.html)
+- [Prometheus Alertmanager SNS Configuration](https://prometheus.io/docs/alerting/configuration/#sns_config)
diff --git a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/webhook-notifier.md b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/webhook-notifier.md
index 6562b948095..e7741ac3b56 100644
--- a/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/webhook-notifier.md
+++ b/docs/sources/alerting/configure-notifications/manage-contact-points/integrations/webhook-notifier.md
@@ -28,13 +28,83 @@ refs:
destination: /docs/grafana//alerting/configure-notifications/template-notifications/
- pattern: /docs/grafana-cloud/
destination: /docs/grafana-cloud/alerting-and-irm/alerting/configure-notifications/template-notifications/
+ configure-contact-points:
+ - pattern: /docs/grafana/
+ destination: /docs/grafana//alerting/configure-notifications/manage-contact-points/
+ - pattern: /docs/grafana-cloud/
+ destination: /docs/grafana-cloud/alerting-and-irm/alerting/configure-notifications/manage-contact-points/
---
-# Configure the webhook notifier for Alerting
+# Configure webhook notifications
-The webhook notification is a simple way to send information about a state change over HTTP to a custom endpoint. Using this notification you could integrate Grafana into a system of your choosing.
+Use the webhook integration in contact points to send alert notifications to your webhook.
-## Webhook JSON payload
+The webhook integration is a flexible way to integrate alerts into your system. When a notification is triggered, it sends a JSON request with alert details and additional data to the webhook endpoint.
+
+## Configure webhook for a contact point
+
+To create a contact point with webhook integration, complete the following steps.
+
+1. Navigate to **Alerts & IRM** -> **Alerting** -> **Contact points**.
+1. Click **+ Add contact point**.
+1. Enter a name for the contact point.
+1. From the **Integration** list, select **Webhook**.
+1. In the **URL** field, copy in your Webhook URL.
+1. (Optional) Configure [additional settings](#webhook-settings).
+1. Click **Save contact point**.
+
+For more details on contact points, including how to test them and enable notifications, refer to [Configure contact points](ref:configure-contact-points).
+
+## Webhook settings
+
+| Option | Description |
+| ------ | ---------------- |
+| URL | The Webhook URL. |
+
+#### Optional settings
+
+| Option | Description |
+| --------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
+| HTTP Method | Specifies the HTTP method to use: `POST` or `PUT`. |
+| Basic Authentication Username | Username for HTTP Basic Authentication. |
+| Basic Authentication Password | Password for HTTP Basic Authentication. |
+| Authentication Header Scheme | Scheme for the `Authorization` Request Header. Default is `Bearer`. |
+| Authentication Header Credentials | Credentials for the `Authorization` Request header. |
+| Max Alerts | Maximum number of alerts to include in a notification. Any alerts exceeding this limit are ignored. `0` means no limit. |
+| TLS | TLS configuration options, including CA certificate, client certificate, and client key. |
+
+{{< admonition type="note" >}}
+
+You can configure either HTTP Basic Authentication or the Authorization request header, but not both.
+
+{{< /admonition >}}
+
+#### Optional settings using templates
+
+Use the following settings to include custom data within the [JSON payload](#body). Both options support using [notification templates](ref:notification-templates).
+
+| Option | Description |
+| ------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
+| Title | Sends the value as a string in the `title` field of the [JSON payload](#body). Supports [notification templates](ref:notification-templates). |
+| Message | Sends the value as a string in the `message` field of the [JSON payload](#body). Supports [notification templates](ref:notification-templates). |
+
+{{< admonition type="note" >}}
+You can customize the `title` and `message` options to include custom messages and notification data using notification templates. These fields are always sent as strings in the JSON payload.
+
+However, you cannot customize the webhook data structure, such as adding or changing other JSON fields and HTTP headers, or sending data in a different format like XML.
+
+If you need to format these fields as JSON or modify other webhook request options, consider sending webhook notifications to a proxy server that adjusts the webhook request before forwarding it to the final destination.
+{{< /admonition >}}
+
+#### Optional notification settings
+
+| Option | Description |
+| ------------------------ | ------------------------------------------------------------------- |
+| Disable resolved message | Enable this option to prevent notifications when an alert resolves. |
+
+## JSON payload
+
+The following example shows the payload of a webhook notification containing information about two firing alerts:
```json
{
@@ -106,76 +176,47 @@ The webhook notification is a simple way to send information about a state chang
}
```
-## Webhook fields
-
### Body
-| Key | Type | Description |
-| ----------------- | ------------------------- | ------------------------------------------------------------------------------- |
-| receiver | string | Name of the webhook |
-| status | string | Current status of the alert, `firing` or `resolved` |
-| orgId | number | ID of the organization related to the payload |
-| alerts | array of [alerts](#alert) | Alerts that are triggering |
-| groupLabels | object | Labels that are used for grouping, map of string keys to string values |
-| commonLabels | object | Labels that all alarms have in common, map of string keys to string values |
-| commonAnnotations | object | Annotations that all alarms have in common, map of string keys to string values |
-| externalURL | string | External URL to the Grafana instance sending this webhook |
-| version | string | Version of the payload |
-| groupKey | string | Key that is used for grouping |
-| truncatedAlerts | number | Number of alerts that were truncated |
-| title | string | Custom title |
-| state | string | State of the alert group (either `alerting` or `ok`) |
-| message | string | Custom message |
+The JSON payload of webhook notifications includes the following key-value pairs:
+
+| Key | Type | Description |
+| ------------------- | ------------------------- | -------------------------------------------------------------------------------- |
+| `receiver` | string | Name of the contact point. |
+| `status` | string | Current status of the alert, `firing` or `resolved`. |
+| `orgId` | number | ID of the organization related to the payload. |
+| `alerts` | array of [alerts](#alert) | Alerts that are triggering. |
+| `groupLabels` | object | Labels that are used for grouping, map of string keys to string values. |
+| `commonLabels` | object | Labels that all alarms have in common, map of string keys to string values. |
+| `commonAnnotations` | object | Annotations that all alarms have in common, map of string keys to string values. |
+| `externalURL` | string | External URL to the Grafana instance sending this webhook. |
+| `version` | string | Version of the payload structure. |
+| `groupKey` | string | Key that is used for grouping. |
+| `truncatedAlerts` | number | Number of alerts that were truncated. |
+| `state` | string | State of the alert group (either `alerting` or `ok`). |
+
+The following key-value pairs are also included in the JSON payload and can be configured in the [webhook settings using notification templates](#optional-settings-using-templates).
+
+| Key | Type | Description |
+| --------- | ------ | -------------------------------------------------------------------------------------------------------------------- |
+| `title` | string | Custom title. Configurable in [webhook settings using notification templates](#optional-settings-using-templates). |
+| `message` | string | Custom message. Configurable in [webhook settings using notification templates](#optional-settings-using-templates). |
### Alert
-| Key | Type | Description |
-| ------------ | ------ | ---------------------------------------------------------------------------------- |
-| status | string | Current status of the alert, `firing` or `resolved` |
-| labels | object | Labels that are part of this alert, map of string keys to string values |
-| annotations | object | Annotations that are part of this alert, map of string keys to string values |
-| startsAt | string | Start time of the alert |
-| endsAt | string | End time of the alert, default value when not resolved is `0001-01-01T00:00:00Z` |
-| values | object | Values that triggered the current status |
-| generatorURL | string | URL of the alert rule in the Grafana UI |
-| fingerprint | string | The labels fingerprint, alarms with the same labels will have the same fingerprint |
-| silenceURL | string | URL to silence the alert rule in the Grafana UI |
-| dashboardURL | string | A link to the Grafana Dashboard if the alert has a Dashboard UID annotation |
-| panelURL | string | A link to the panel if the alert has a Panel ID annotation |
-| imageURL | string | URL of a screenshot of a panel assigned to the rule that created this notification |
+The Alert object represents an alert included in the notification group, as provided by the [`alerts` field](#body).
-{{< admonition type="note" >}}
-
-You can customize the `title` and `message` fields using [notification templates](ref:notification-templates).
-
-However, you cannot customize webhook data structure or format, including JSON fields or sending data in XML, nor can you change the webhook HTTP headers.
-
-{{< /admonition >}}
-
-## Procedure
-
-To create your Webhook integration in Grafana Alerting, complete the following steps.
-
-1. Navigate to **Alerts & IRM** -> **Alerting** -> **Contact points**.
-1. Click **+ Add contact point**.
-1. Enter a contact point name.
-1. From the Integration list, select **Webhook**.
-1. In the **URL** field, copy in your Webhook URL.
-1. Click **Test** to check that your integration works.
-
- ** For Grafana Alertmanager only.**
-
-1. Click **Save contact point**.
-
-## Next steps
-
-The Webhook contact point is ready to receive alert notifications.
-
-To add this contact point to your alert, complete the following steps.
-
-1. In Grafana, navigate to **Alerting** > **Alert rules**.
-1. Edit or create a new alert rule.
-1. Scroll down to the **Configure labels and notifications** section.
-1. Under Notifications, click **Select contact point**.
-1. From the drop-down menu, select the previously created contact point.
-1. **Click Save rule and exit**.
+| Key | Type | Description |
+| -------------- | ------ | ----------------------------------------------------------------------------------- |
+| `status` | string | Current status of the alert, `firing` or `resolved`. |
+| `labels` | object | Labels that are part of this alert, map of string keys to string values. |
+| `annotations` | object | Annotations that are part of this alert, map of string keys to string values. |
+| `startsAt` | string | Start time of the alert. |
+| `endsAt` | string | End time of the alert, default value when not resolved is `0001-01-01T00:00:00Z`. |
+| `values` | object | Values that triggered the current status. |
+| `generatorURL` | string | URL of the alert rule in the Grafana UI. |
+| `fingerprint` | string | The labels fingerprint, alarms with the same labels will have the same fingerprint. |
+| `silenceURL` | string | URL to silence the alert rule in the Grafana UI. |
+| `dashboardURL` | string | A link to the Grafana Dashboard if the alert has a Dashboard UID annotation. |
+| `panelURL` | string | A link to the panel if the alert has a Panel ID annotation. |
+| `imageURL` | string | URL of a screenshot of a panel assigned to the rule that created this notification. |
diff --git a/docs/sources/alerting/configure-notifications/mute-timings.md b/docs/sources/alerting/configure-notifications/mute-timings.md
index 1ef726267e3..79be30654e0 100644
--- a/docs/sources/alerting/configure-notifications/mute-timings.md
+++ b/docs/sources/alerting/configure-notifications/mute-timings.md
@@ -39,7 +39,9 @@ refs:
# Configure mute timings
-A mute timing is a recurring interval of time when no new notifications for a policy are generated or sent. Use them to prevent alerts from firing a specific and reoccurring period, for example, a regular maintenance period or weekends.
+A mute timing is a recurring interval that stops notifications for one or multiple notification policies during a specified period. It suppresses notifications but does not interrupt alert evaluation.
+
+Use mute timings to temporarily pause notifications for a specific recurring period, such as a regular maintenance window or weekends.
{{< admonition type="note" >}}
Mute timings are assigned to a [specific Alertmanager](ref:alertmanager-architecture) and only suppress notifications for alerts managed by that Alertmanager.
diff --git a/docs/sources/alerting/configure-notifications/template-notifications/reference.md b/docs/sources/alerting/configure-notifications/template-notifications/reference.md
index e20d31ee77b..905ad86e264 100644
--- a/docs/sources/alerting/configure-notifications/template-notifications/reference.md
+++ b/docs/sources/alerting/configure-notifications/template-notifications/reference.md
@@ -96,25 +96,25 @@ You can execute this template by passing the dot (`.`):
`Alert` contains data for an individual alert:
-| Name | Type | Description |
-| -------------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
-| `Status` | string | Firing or resolved. |
-| `Labels` | [KV](#kv) | The labels for this alert. It includes all [types of labels](ref:label-types). |
-| `Annotations` | [KV](#kv) | The annotations for this alert. |
-| `StartsAt` | [Time](#time) | The time the alert fired |
-| `EndsAt` | [Time](#time) | Only set if the end time of an alert is known. Otherwise set to a configurable timeout period from the time since the last alert was received. |
-| `GeneratorURL` | string | A link to Grafana, or the source of the alert if using an external alert generator. |
-| `Fingerprint` | string | A unique string that identifies the alert. |
+| Name | Type | Description |
+| -------------- | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `Status` | string | Firing or resolved. |
+| `Labels` | [KV](#kv) | The labels associated with this alert.
It includes all [types of labels](ref:label-types), but only query labels used in the alert condition. |
+| `Annotations` | [KV](#kv) | The annotations for this alert. |
+| `StartsAt` | [Time](#time) | The time the alert fired |
+| `EndsAt` | [Time](#time) | Only set if the end time of an alert is known. Otherwise set to a configurable timeout period from the time since the last alert was received. |
+| `GeneratorURL` | string | A link to Grafana, or the source of the alert if using an external alert generator. |
+| `Fingerprint` | string | A unique string that identifies the alert. |
Grafana-managed alerts include these additional properties:
-| Name | Type | Description |
-| -------------- | --------- | ------------------------------------------------------------------------------------ |
-| `DashboardURL` | string | A link to the Grafana Dashboard if the alert has a Dashboard UID annotation. |
-| `PanelURL` | string | A link to the panel if the alert has a Panel ID annotation. |
-| `SilenceURL` | string | A link to silence the alert. |
-| `Values` | [KV](#kv) | The values of all expressions, including Classic Conditions. |
-| `ValueString` | string | A string that contains the labels and value of each reduced expression in the alert. |
+| Name | Type | Description |
+| -------------- | --------- | -------------------------------------------------------------------------------------------------- |
+| `DashboardURL` | string | A link to the Grafana Dashboard if the alert has a Dashboard UID annotation. |
+| `PanelURL` | string | A link to the panel if the alert has a Panel ID annotation. |
+| `SilenceURL` | string | A link to silence the alert. |
+| `Values` | [KV](#kv) | The values of expressions used to evaluate the alert condition. Only relevant values are included. |
+| `ValueString` | string | A string that contains the labels and value of each reduced expression in the alert. |
This example iterates over the list of firing and resolved alerts (`.Alerts`) in the notification and prints the data for each alert:
diff --git a/docs/sources/alerting/fundamentals/_index.md b/docs/sources/alerting/fundamentals/_index.md
index 934f019cfd3..147a5e36d2d 100644
--- a/docs/sources/alerting/fundamentals/_index.md
+++ b/docs/sources/alerting/fundamentals/_index.md
@@ -132,7 +132,7 @@ Each notification policy decides where to send the alert (contact point) and whe
### Silences and mute timings
-[Silences](ref:silences) and [mute timings](ref:mute-timings) allow you to pause notifications for specific alerts or even entire notification policies. Use a silence to pause notifications on an ad-hoc basis, such as during a maintenance window; and use mute timings to pause notifications at regular intervals, such as evenings and weekends.
+[Silences](ref:silences) and [mute timings](ref:mute-timings) allow you to pause notifications without interrupting alert rule evaluation. Use a silence to pause notifications on a one-time basis, such as during a maintenance window; and use mute timings to pause notifications at regular intervals, such as evenings and weekends.
### Architecture
diff --git a/docs/sources/alerting/fundamentals/alert-rule-evaluation/state-and-health.md b/docs/sources/alerting/fundamentals/alert-rule-evaluation/state-and-health.md
index cb4f932a5f6..4c871e2d6e7 100644
--- a/docs/sources/alerting/fundamentals/alert-rule-evaluation/state-and-health.md
+++ b/docs/sources/alerting/fundamentals/alert-rule-evaluation/state-and-health.md
@@ -68,7 +68,7 @@ Alert instances will be routed for [notifications](ref:notifications) when they
### `No Data` and `Error` alerts
-When evaluation of an alert rule produces state `No Data` or `Error`, Grafana Alerting generates a new alert instance that have the following additional labels:
+When an alert rule evaluation results in a `No Data` or `Error` state, Grafana Alerting immediately creates a new alert instance —skipping the pending period—with the following additional labels:
- `alertname`: Either `DatasourceNoData` or `DatasourceError` depending on the state.
- `datasource_uid`: The UID of the data source that caused the state.
@@ -87,7 +87,7 @@ In [Configure no data and error handling](ref:no-data-and-error-handling), you c
Note that `No Data` and `Error` states are supported only for Grafana-managed alert rules.
-{{< figure src="/media/docs/alerting/alert-rule-configure-no-data-and-error.png" alt="A screenshot of the `Configure no data and error handling` option in Grafana Alerting." max-width="500px" >}}
+{{< figure src="/media/docs/alerting/alert-rule-configure-no-data-and-error-v2.png" alt="A screenshot of the `Configure no data and error handling` option in Grafana Alerting." max-width="500px" >}}
{{< docs/shared lookup="alerts/table-configure-no-data-and-error.md" source="grafana" version="" >}}
diff --git a/docs/sources/alerting/fundamentals/alert-rules/_index.md b/docs/sources/alerting/fundamentals/alert-rules/_index.md
index 47e410b8564..439c56b130c 100644
--- a/docs/sources/alerting/fundamentals/alert-rules/_index.md
+++ b/docs/sources/alerting/fundamentals/alert-rules/_index.md
@@ -25,9 +25,17 @@ refs:
destination: /docs/grafana-cloud/connect-externally-hosted/data-sources/prometheus/configure-prometheus-data-source/#alerting
queries-and-conditions:
- pattern: /docs/grafana/
- destination: /docs/grafana//alerting/fundamentals/alert-rules/queries-conditions/
+ destination: /docs/grafana//alerting/fundamentals/alert-rules/queries-conditions/#data-source-queries
- pattern: /docs/grafana-cloud/
- destination: /docs/grafana-cloud/alerting-and-irm/alerting/fundamentals/alert-rules/queries-conditions/
+ destination: /docs/grafana-cloud/alerting-and-irm/alerting/fundamentals/alert-rules/queries-conditions/#data-source-queries
+ alert-condition:
+ - pattern: /docs/grafana/
+ destination: /docs/grafana//alerting/fundamentals/alert-rules/queries-conditions/#alert-condition
+ - pattern: /docs/grafana-cloud/
+ destination: /docs/grafana-cloud/alerting-and-irm/alerting/fundamentals/alert-rules/queries-conditions/#alert-condition
+ recorded-queries:
+ - pattern: /docs/
+ destination: /docs/grafana//administration/recorded-queries/
notification-images:
- pattern: /docs/grafana/
destination: /docs/grafana//alerting/configure-notifications/template-notifications/images-in-notifications/
@@ -45,14 +53,9 @@ refs:
destination: /docs/grafana-cloud/alerting-and-irm/alerting/alerting-rules/create-recording-rules/
expression-queries:
- pattern: /docs/grafana/
- destination: /docs/grafana//alerting/fundamentals/alert-rules/queries-conditions/#expression-queries
+ destination: /docs/grafana//alerting/fundamentals/alert-rules/queries-conditions/#advanced-options-expressions
- pattern: /docs/grafana-cloud/
- destination: /docs/grafana-cloud/alerting-and-irm/alerting/fundamentals/alert-rules/queries-conditions/#expression-queries
- alert-condition:
- - pattern: /docs/grafana/
- destination: /docs/grafana//alerting/fundamentals/alert-rules/queries-conditions/#alert-condition
- - pattern: /docs/grafana-cloud/
- destination: /docs/grafana-cloud/alerting-and-irm/alerting/fundamentals/alert-rules/queries-conditions/#alert-condition
+ destination: /docs/grafana-cloud/alerting-and-irm/alerting/fundamentals/alert-rules/queries-conditions/#advanced-options-expressions
alert-rule-evaluation:
- pattern: /docs/grafana/
destination: /docs/grafana//alerting/fundamentals/alert-rules/rule-evaluation/
@@ -64,8 +67,8 @@ refs:
An alert rule is a set of evaluation criteria for when an alert rule should fire. An alert rule consists of:
-- Queries and expressions that select the data set to evaluate.
-- A condition (the threshold) that the query must meet or exceed to trigger the alert instance.
+- [Queries](ref:queries-and-conditions) that select the dataset to evaluate.
+- An [alert condition](ref:alert-condition) (the threshold) that the query must meet or exceed to trigger the alert instance.
- An interval that specifies the frequency of [alert rule evaluation](ref:alert-rule-evaluation) and a duration indicating how long the condition must be met to trigger the alert instance.
- Other customizable options, for example, setting what should happen in the absence of data, notification messages, and more.
diff --git a/docs/sources/alerting/fundamentals/alert-rules/queries-conditions.md b/docs/sources/alerting/fundamentals/alert-rules/queries-conditions.md
index 229816db306..175306e8ef1 100644
--- a/docs/sources/alerting/fundamentals/alert-rules/queries-conditions.md
+++ b/docs/sources/alerting/fundamentals/alert-rules/queries-conditions.md
@@ -17,21 +17,16 @@ labels:
title: Queries and conditions
weight: 104
refs:
- data-sources:
- - pattern: /docs/grafana/
- destination: /docs/grafana//datasources/
- - pattern: /docs/grafana-cloud/
- destination: /docs/grafana-cloud/connect-externally-hosted/data-sources/
data-source-alerting:
- pattern: /docs/grafana/
destination: /docs/grafana//alerting/fundamentals/alert-rules/#supported-data-sources
- pattern: /docs/grafana-cloud/
destination: /docs/grafana-cloud/alerting-and-irm/alerting/fundamentals/alert-rules/#supported-data-sources
- alert-rule-evaluation:
+ state-and-health:
- pattern: /docs/grafana/
- destination: /docs/grafana//alerting/fundamentals/alert-rule-evaluation/
+ destination: /docs/grafana//alerting/fundamentals/state-and-health/
- pattern: /docs/grafana-cloud/
- destination: /docs/grafana-cloud/alerting-and-irm/alerting/fundamentals/alert-rule-evaluation/
+ destination: /docs/grafana-cloud/alerting-and-irm/alerting/fundamentals/state-and-health/
query-transform-data:
- pattern: /docs/grafana/
destination: /docs/grafana//panels-visualizations/query-transform-data/
@@ -41,71 +36,122 @@ refs:
# Queries and conditions
-In Grafana, queries fetch and transform data from [data sources,](ref:data-sources) which include databases like MySQL or PostgreSQL, time series databases like Prometheus or InfluxDB, and services like Amazon CloudWatch or Azure Monitor.
+In Grafana, queries fetch and transform data from data sources, which include databases like MySQL or PostgreSQL, time series databases like Prometheus or InfluxDB, and services like Amazon CloudWatch or Azure Monitor.
-A query specifies the data to extract from a data source, with the syntax varying based on the type of data source used.
+An alert rule defines the following components:
-In Alerting, an alert rule defines of one or more queries and expressions that select the data you want to measure and a [condition](#alert-condition) that needs to be met before an alert rule fires.
+- A [query](#data-source-queries) that specifies the data to retrieve from a data source, with the syntax depending on the type of data source used.
+- A [condition](#alert-condition) that must be met before the alert rule fires.
+- Optional [expressions](#advanced-options-expressions) to perform transformations on the retrieved data.
+
+Alerting periodically runs the queries and expressions, evaluating the condition. If the condition is breached, an alert instance is triggered for each time series.
## Data source queries
-Alerting queries are the same type of queries available in Grafana panels. Queries in Grafana can be applied in various ways, depending on the data source and query language being used. However, not all [data sources support Alerting](ref:data-source-alerting).
+Alerting queries are the same as the queries used in Grafana panels, but Grafana-managed alerts are limited to querying [data sources that have Alerting enabled](ref:data-source-alerting).
-Each data source’s query editor provides a customized user interface to help you write queries that take advantage of its unique capabilities. For additional information about queries in Grafana, refer to [Query and transform data](ref:query-transform-data).
+Queries in Grafana can be applied in various ways, depending on the data source and query language being used. Each data source’s query editor provides a customized user interface to help you write queries that take advantage of its unique capabilities.
-Some common types of query components include:
+For more details about queries in Grafana, refer to [Query and transform data](ref:query-transform-data).
-**Metrics or data fields**: Specify the specific metrics or data fields you want to retrieve, such as CPU usage, network traffic, or sensor readings.
+{{< figure src="/media/docs/alerting/alerting-query-conditions-default-options.png" max-width="750px" caption="Define alert query and alert condition" >}}
-**Time range**: Define the time range for which you want to fetch data, such as the last hour, a specific day, or a custom time range.
+## Alert condition
-**Filters**: Apply filters to narrow down the data based on specific criteria, such as filtering data by a specific tag, host, or application.
+The alert condition is the query or expression that determines whether the alert fires or not depending whether the value satisfies the specified comparison. There can be only one condition which determines the triggering of the alert.
-**Aggregations**: Perform aggregations on the data to calculate metrics like averages, sums, or counts over a given time period.
+If the queried data meets the defined condition, Grafana fires the alert.
-**Grouping**: Group the data by specific dimensions or tags to create aggregated views or breakdowns.
+When using **Default options**, the `When` input [reduces the query data](#reduce), and the last input defines the threshold condition.
-{{% admonition type="note" %}}
-Grafana doesn't support alert queries with template variables. More details [here](https://community.grafana.com/t/template-variables-are-not-supported-in-alert-queries-while-setting-up-alert/2514).
-{{% /admonition %}}
+When using **Advanced options**, you have to choose one of your queries or expressions as the alert condition.
-## Expression queries
+## Advanced options: Expressions
-In Grafana, an expression is used to perform calculations, transformations, or aggregations on the data source queried data. It allows you to create custom metrics or modify existing metrics based on mathematical operations, functions, or logical expressions.
+Expressions are only available for Grafana-managed alerts and when the **Advanced options** are enabled.
-By leveraging expression queries, users can perform tasks such as calculating the percentage change between two values, applying functions like logarithmic or trigonometric functions, aggregating data over specific time ranges or dimensions, and implementing conditional logic to handle different scenarios.
+In Grafana, expressions allow you to perform calculations, transformations, or aggregations on queried data. They modify existing metrics through mathematical operations, functions, or logical expressions.
-In Alerting, you can only use expressions for Grafana-managed alert rules. For each expression, you can choose from the math, reduce, and resample expressions. These are called multi-dimensional rules, because they generate an alert instance for each series.
+With expression queries, you can perform tasks such as calculating the percentage change between two values, applying functions like logarithmic or trigonometric functions, aggregating data over specific time ranges or dimensions, and implementing conditional logic to handle different scenarios.
-**Reduce**
+{{< figure src="/media/docs/alerting/alert-rule-expressions.png" max-width="750px" caption="Alert rule expressions" >}}
-Aggregates time series values in the selected time range into a single value. It's not necessary for [rules using numeric data](#alert-on-numeric-data).
+The following expressions are available:
-**Math**
+### Reduce
-Performs free-form math functions/operations on time series and number data. Can be used to preprocess time series data or to define an alert condition for number data. For example:
+Aggregates time series values within the selected time range into a single number.
+
+Reduce takes one or more time series and transform each series into a single number, which can then be compared in the alert condition.
+
+The following aggregations functions are included: `Min`, `Max`, `Mean`, `Mediam`, `Sum`, `Count`, and `Last`.
+
+### Math
+
+Performs free-form math functions/operations on time series data and numbers. For instance, `$A + 1` or `$A * 100`.
+
+You can also use a Math expression to define the alert condition for numbers. For example:
- `$B > 70` should fire if the value of B (query or expression) is more than 70.
- `$B < $C * 100` should fire if the value of B is less than the value of C multiplied by 100.
If queries being compared have multiple series in their results, series from different queries are matched if they have the same labels or one is a subset of the other.
-**Resample**
+### Resample
Realigns a time range to a new set of timestamps, this is useful when comparing time series data from different data sources where the timestamps would otherwise not align.
-**Threshold**
+### Threshold
-Checks if any time series data matches the threshold condition.
+Compares single numbers from previous queries or expressions (e.g., `$A`, `$B`) to a specified condition. It's often used to define the alert condition.
-The threshold expression allows you to compare two single values. It returns `0` when the condition is false and `1` if the condition is true. The following threshold functions are available:
+The threshold expression allows the comparison between two single values. Available threshold functions are:
-- Is above (x > y)
-- Is below (x < y)
-- Is within range (x > y1 AND x < y2)
-- Is outside range (x < y1 AND x > y2)
+- **Is above**: `$A > 5`
+- **Is below**: `$B < 3`
+- **Is equal to**: `$A == 2`
+- **Is not equal to**: `$B =! 4`
+- **Is above or equal to**: `$A >= 8`
+- **Is below or equal to**: `$B <= 16`
+- **Is within range**: `$A > 0 AND $A < 10`
+- **Is outside range**: `$B < 0 OR $B > 100`
+- **Is within range included**: `$A >= 0 AND $A <= 10`
+- **Is outside range included**: `$B <= 0 OR $B >= 100`
-**Classic condition (legacy)**
+A threshold returns `0` when the condition is false and `1` when true.
+
+If the threshold is set as the alert condition, the alert fires when the threshold returns `1`.
+
+#### Recovery threshold
+
+To reduce the noise from flapping alerts, you can set a recovery threshold different to the alert threshold.
+
+Flapping alerts occur when a metric hovers around the alert threshold condition and may lead to frequent state changes, resulting in too many notifications.
+
+The value of a flapping metric can continually go above and below a threshold, resulting in a series of firing-resolved-firing notifications and a noisy alert state history.
+
+For example, if you have an alert for latency with a threshold of 1000ms and the number fluctuates around 1000 (say 980 -> 1010 -> 990 -> 1020, and so on), then each of those might trigger a notification:
+
+- 980 -> 1010 triggers a firing alert.
+- 1010 -> 990 triggers a resolving alert.
+- 990 -> 1020 triggers a firing alert again.
+
+To prevent this, you can set a recovery threshold to define two thresholds instead of one:
+
+1. An alert is triggered when the first threshold is crossed.
+1. An alert is resolved only when the second (recovery) threshold is crossed.
+
+In the previous example, setting the recovery threshold to 900ms means the alert only resolves when the latency falls below 900ms:
+
+- 980 -> 1010 triggers a firing alert.
+- 1010 -> 990 does not resolve the alert, keeping it in the firing state.
+- 990 -> 1020 keeps the alert in the firing state.
+
+The recovery threshold mitigates unnecessary alert state changes and reduces alert noise.
+
+{{< collapse title="Classic condition (legacy)" >}}
+
+#### Classic condition (legacy)
Classic conditions exist mainly for compatibility reasons and should be avoided if possible.
@@ -113,66 +159,35 @@ Classic condition checks if any time series data matches the alert condition. It
| Condition operators | How it works |
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| and | Two conditions before and after must be true for the overall condition to be true. |
-| or | If one of conditions before and after are true, the overall condition is true. |
-| logic-or | If the condition before `logic-or` is true, the overall condition is immediately true, without evaluating subsequent conditions. For instance, `TRUE and TRUE logic-or FALSE and FALSE` evaluate to `TRUE`, because the preceding condition returns `TRUE`. |
+| `and` | Two conditions before and after must be true for the overall condition to be true. |
+| `or` | If one of conditions before and after are true, the overall condition is true. |
+| `logic-or` | If the condition before `logic-or` is true, the overall condition is immediately true, without evaluating subsequent conditions. For instance, `TRUE and TRUE logic-or FALSE and FALSE` evaluate to `TRUE`, because the preceding condition returns `TRUE`. |
-## Aggregations
+The following aggregation functions are also available to further refine your query.
-Grafana Alerting provides the following aggregation functions to enable you to further refine your query.
+| Function | What it does |
+| ------------------ | ------------------------------------------------------------------------------- |
+| `avg` | Displays the average of the values |
+| `min` | Displays the lowest value |
+| `max` | Displays the highest value |
+| `sum` | Displays the sum of all values |
+| `count` | Counts the number of values in the result |
+| `last` | Displays the last value |
+| `median` | Displays the median value |
+| `diff` | Displays the difference between the newest and oldest value |
+| `diff_abs` | Displays the absolute value of diff |
+| `percent_diff` | Displays the percentage value of the difference between newest and oldest value |
+| `percent_diff_abs` | Displays the absolute value of `percent_diff` |
+| `count_non_null` | Displays a count of values in the result set that aren't `null` |
-These functions are available for **Reduce** and **Classic condition** expressions only.
-
-| Function | Expression | What it does |
-| ---------------- | ---------------- | ------------------------------------------------------------------------------- |
-| avg | Reduce / Classic | Displays the average of the values |
-| min | Reduce / Classic | Displays the lowest value |
-| max | Reduce / Classic | Displays the highest value |
-| sum | Reduce / Classic | Displays the sum of all values |
-| count | Reduce / Classic | Counts the number of values in the result |
-| last | Reduce / Classic | Displays the last value |
-| median | Reduce / Classic | Displays the median value |
-| diff | Classic | Displays the difference between the newest and oldest value |
-| diff_abs | Classic | Displays the absolute value of diff |
-| percent_diff | Classic | Displays the percentage value of the difference between newest and oldest value |
-| percent_diff_abs | Classic | Displays the absolute value of percent_diff |
-| count_non_null | Classic | Displays a count of values in the result set that aren't `null` |
-
-## Alert condition
-
-An alert condition is the query or expression that determines whether the alert fires or not depending on the value it yields. There can be only one condition which determines the triggering of the alert.
-
-After you have defined your queries and expressions, choose one of them as the alert rule condition. By default, the last expression added is used as the alert condition.
-
-When the queried data satisfies the defined condition, Grafana triggers the associated alert, which can be configured to send notifications through various channels like email, Slack, or PagerDuty.
-
-For details about how the alert evaluation triggers notifications, refer to [Alert rule evaluation](ref:alert-rule-evaluation).
-
-## Recovery threshold
-
-To reduce the noise of flapping alerts, you can set a recovery threshold different to the alert threshold.
-
-Flapping alerts occur when a metric hovers around the alert threshold condition and may lead to frequent state changes, resulting in too many notifications being generated.
-
-It can be tricky to create an alert rule for a noisy metric. That is, when the value of a metric continually goes above and below a threshold. This is called flapping and results in a series of firing - resolved - firing notifications and a noisy alert state history.
-
-For example, if you have an alert for latency with a threshold of 1000ms and the number fluctuates around 1000 (say 980 ->1010 -> 990 -> 1020, and so on) then each of those triggers a notification.
-
-To solve this problem, you can set a (custom) recovery threshold, which basically means having two thresholds instead of one:
-
-1. An alert is triggered when the first threshold is crossed.
-2. An alert is resolved only when the second threshold is crossed.
-
-For example, you could set a threshold of 1000ms and a recovery threshold of 900ms. This way, an alert rule only stops firing when it goes under 900ms and flapping is reduced.
-
-For details about how the alert evaluation triggers notifications, refer to [Alert rule evaluation](ref:alert-rule-evaluation).
+{{< /collapse >}}
## Alert on numeric data
Among certain data sources numeric data that is not time series can be directly alerted on, or passed into Server Side Expressions (SSE). This allows for more processing and resulting efficiency within the data source, and it can also simplify alert rules.
-When alerting on numeric data instead of time series data, there is no need to reduce each labeled time series into a single number. Instead labeled numbers are returned to Grafana instead.
+When alerting on numeric data instead of time series data, there is no need to [reduce](#reduce) each labeled time series into a single number. Instead labeled numbers are returned to Grafana instead.
-### Tabular Data
+#### Tabular Data
This feature is supported with backend data sources that query tabular data:
diff --git a/docs/sources/alerting/fundamentals/notifications/_index.md b/docs/sources/alerting/fundamentals/notifications/_index.md
index 538eaa0d00a..4c85da09ef6 100644
--- a/docs/sources/alerting/fundamentals/notifications/_index.md
+++ b/docs/sources/alerting/fundamentals/notifications/_index.md
@@ -126,7 +126,7 @@ Grafana Alerting provides advanced notification capabilities that you’ll find
For instance, you can customize notifications with shared [templates](ref:templates) that provide actionable alert information and can be reused for multiple notifications.
-Additionally, you can use [silences](ref:silences) and [mute timings](ref:mute-timings) to pause notifications for a given time window or at regular intervals, respectively.
+Additionally, you can use [silences](ref:silences) and [mute timings](ref:mute-timings) to pause or suppress notifications without interrupting alert evaluation.
## Architecture
diff --git a/docs/sources/alerting/fundamentals/notifications/notification-policies.md b/docs/sources/alerting/fundamentals/notifications/notification-policies.md
index 48a4bd70e37..ae8d53f1520 100644
--- a/docs/sources/alerting/fundamentals/notifications/notification-policies.md
+++ b/docs/sources/alerting/fundamentals/notifications/notification-policies.md
@@ -76,7 +76,7 @@ Each policy consists of a set of label matchers (0 or more) that specify which a
{{< figure src="/media/docs/alerting/notification-routing.png" max-width="750px" caption="Matching alert instances with notification policies" alt="Example of a notification policy tree" >}}
{{< admonition type="tip" >}}
-For a practical example of routing with notification policies, refer to our [Getting Started with Alert Instances and Notification Routing tutorial](https://grafana.com/tutorials/alerting-get-started-pt4/).
+For a practical example of routing with notification policies, refer to our [Getting Started with Alert Instances and Notification Routing tutorial](https://grafana.com/tutorials/alerting-get-started-pt2/).
{{< /admonition >}}
## Routing
diff --git a/docs/sources/alerting/monitor-status/view-alert-rules.md b/docs/sources/alerting/monitor-status/view-alert-rules.md
index 8bc68611a2d..293faf3a0cf 100644
--- a/docs/sources/alerting/monitor-status/view-alert-rules.md
+++ b/docs/sources/alerting/monitor-status/view-alert-rules.md
@@ -5,7 +5,7 @@ aliases:
- ../../alerting/alerting-rules/rule-list/ # /docs/grafana//alerting/alerting-rules/rule-list
- ../../alerting/manage-notifications/view-alert-rules/ # /docs/grafana//alerting/manage-notifications/view-alert-rules/
canonical: https://grafana.com/docs/grafana/latest/alerting/monitor-status/view-alert-rules/
-description: View alert rules
+description: View alert rules, compare their versions, and restore previous alert rules.
keywords:
- grafana
- alerting
@@ -43,6 +43,8 @@ This view includes filters to simplify managing large volumes of alerts.
You can filter by data sources, dashboards, and alert rule properties such as state, type, health, and contact points. The **Search** input allows you to filter by additional parameters like folders, evaluation groups, labels, and more.
+## Change alert rules list view
+
You can also change how the rule list is displayed using the **View as** option.
- **Grouped**: Displays Grafana rules grouped by folder and evaluation group, and data-source rules by namespace and evaluation group. This is the default view.
@@ -56,3 +58,14 @@ Select a group to expand it and view the list of alert rules within that group.
{{< figure src="/media/docs/alerting/view-alert-rule-list-with-actions.png" max-width="750px" alt="View alert rule state and alert rule health in Grafana Alerting" >}}
For details on how rule states and alert instance states are displayed, refer to [View alert state](ref:view-alert-state).
+
+## View and compare alert rules versions.
+
+To view previous alert rules for an alert, complete the following steps.
+
+1. Navigate to **Alerts & IRM -> Alerting -> Alert rules**.
+1. Select an alert rule and click **View**.
+1. Click the **Versions** tab.
+ The page displays a list of the previous rule versions.
+
+On the Alert rule's Versions page you can view and compare the previous rule versions.
diff --git a/docs/sources/alerting/set-up/meta-monitoring.md b/docs/sources/alerting/set-up/meta-monitoring.md
index 4c29f6ac4a9..46d8c517f8c 100644
--- a/docs/sources/alerting/set-up/meta-monitoring.md
+++ b/docs/sources/alerting/set-up/meta-monitoring.md
@@ -2,6 +2,7 @@
aliases:
- ../meta-monitoring/ # /docs/grafana//alerting/meta-monitoring/
- ../monitoring/ # /docs/grafana//alerting/monitoring/
+ - ../monitor/ # /docs/grafana//alerting/monitor/
canonical: https://grafana.com/docs/grafana/latest/alerting/set-up/meta-monitoring
description: Monitor your alerting metrics to ensure you identify potential issues before they become critical.
keywords:
diff --git a/docs/sources/alerting/set-up/performance-limitations/index.md b/docs/sources/alerting/set-up/performance-limitations/index.md
index 69becbad450..b8524e4c8a7 100644
--- a/docs/sources/alerting/set-up/performance-limitations/index.md
+++ b/docs/sources/alerting/set-up/performance-limitations/index.md
@@ -61,7 +61,13 @@ For more information, refer to [this GitHub issue](https://github.com/grafana/gr
If you have a high number of alert instances, it can happen that the load on the database gets very high, as each state
transition of an alert instance is saved in the database.
-This can be prevented by writing to the database periodically. For this the feature flag `alertingSaveStatePeriodic` needs
+### Compressed alert state
+
+When the `alertingSaveStateCompressed` feature toggle is enabled, Grafana saves the alert rule state in a compressed form, reducing database overhead for alerts with many instances.
+
+### Save state periodically
+
+High load can be also prevented by writing to the database periodically. For this the feature flag `alertingSaveStatePeriodic` needs
to be enabled. By default, it saves the states every 5 minutes to the database and on each shutdown. The periodic interval
can also be configured using the `state_periodic_save_interval` configuration flag. During this process, Grafana deletes all existing alert instances from the
database and then writes the entire current set of instances back in batches in a single transacton.
diff --git a/docs/sources/alerting/set-up/provision-alerting-resources/file-provisioning/index.md b/docs/sources/alerting/set-up/provision-alerting-resources/file-provisioning/index.md
index b7eb4b841fa..850600cc074 100644
--- a/docs/sources/alerting/set-up/provision-alerting-resources/file-provisioning/index.md
+++ b/docs/sources/alerting/set-up/provision-alerting-resources/file-provisioning/index.md
@@ -511,6 +511,8 @@ settings:
#
endpointUrl: https://custom_url/api/chat.postMessage
#
+ color: {{ if eq .Status "firing" }}#D63232{{ else }}#36a64f{{ end }}
+ #
title: |
{{ template "slack.default.title" . }}
text: |
diff --git a/docs/sources/breaking-changes/_index.md b/docs/sources/breaking-changes/_index.md
index af76c612b89..fa0628a51d9 100644
--- a/docs/sources/breaking-changes/_index.md
+++ b/docs/sources/breaking-changes/_index.md
@@ -25,7 +25,7 @@ For our purposes, a breaking change is any change that requires users or operato
{{% admonition type="note" %}}
-To learn what's available in a Grafana release, refer to the [What's new ]({{< relref "../whatsnew/" >}}) page for each version. For the steps we recommend when you upgrade, check out the [Upgrade guide]({{< relref "../upgrade-guide/" >}}) for each version.
+To learn what's available in a Grafana release, refer to the [What's new ](../whatsnew/) page for each version. For the steps we recommend when you upgrade, check out the [Upgrade guide](../upgrade-guide/) for each version.
{{% /admonition %}}
diff --git a/docs/sources/breaking-changes/breaking-changes-v10-0.md b/docs/sources/breaking-changes/breaking-changes-v10-0.md
index 946ba52c93c..8250dba93d2 100644
--- a/docs/sources/breaking-changes/breaking-changes-v10-0.md
+++ b/docs/sources/breaking-changes/breaking-changes-v10-0.md
@@ -34,7 +34,7 @@ For each change, the provided information:
- Guides you in how to mitigate for the change or migrate
- Provides more learning resources
-For release highlights and deprecations, refer to our [v10.0 What’s new]({{< relref "../whatsnew/whats-new-in-v10-0/" >}}). For the specific steps we recommend when you upgrade to v10.0, check out our [Upgrade guide]({{< relref "../upgrade-guide/upgrade-v10.0/index.md" >}}).
+For release highlights and deprecations, refer to our [v10.0 What’s new](../../whatsnew/whats-new-in-v10-0/). For the specific steps we recommend when you upgrade to v10.0, check out our [Upgrade guide](../../upgrade-guide/upgrade-v10.0/).
| Option | Description |
| ------ | ----------- |
-| Source dashboard | Select the dashboard from which you want to generate the report. |
-| [Template variables (optional)](#template-variables) | Select the variable values for the selected dashboard. This option is only displayed if the dashboard has variables. |
-| [Time range (optional)](#time-range) | By default, reports use the saved time range of the dashboard. Optionally, you can change the time range of the report. |
-| Add another dashboard | Add more dashboards to the report. Additional dashboards will be rendered as new pages in the same PDF file, or additional images if you chose to embed images in your report email. You can't add the same dashboard to a report multiple times. |
+| Source dashboard (required) | Select the dashboard from which you want to generate the report. |
+| [Template variables](#template-variables) | Select the variable values for the selected dashboard. This option is only displayed if the dashboard has variables. |
+| [Time range](#time-range) | If you leave the field empty, reports use the saved time range of the dashboard. Optionally, you can change the time range of the report. |
+| Add another dashboard | Add more dashboards to the report. |
@@ -179,30 +149,39 @@ At this step, select the dashboard or dashboards on which the report is based, a
This option is only displayed if the dashboard has variables.
-You can configure report-specific template variables for the dashboard on the report page. The variables that you select will override the variables from the dashboard, and they are used when rendering a PDF file of the report. For detailed information about using template variables, refer to the [Templates and variables](ref:templates-and-variables) section.
+You can configure report-specific template variables for the dashboard on the report page.
+The variables that you select override the variables from the dashboard.
+For detailed information about using template variables, refer to [Variables](ref:templates-and-variables).
-The query variables saved with a report might become out of date if the results of that query change. For example, if your template variable queries for a list of hostnames and a new hostname is added, then it will not be included in the report. If that occurs, the selected variables must be manually updated in the report. If you select the **All** value for the template variable or if you keep the dashboard's original variable selection, then the report stays up-to-date as new values are added.
+The query variables saved with a report might become out-of-date if the results of that query change.
+For example, if your template variable queries for a list of hostnames and a new hostname is added, then it won't be included in the report.
+If that occurs, the selected variables must be manually updated in the report.
+If you select the **All** value for the template variable or if you keep the dashboard's original variable selection, then the report stays up-to-date as new values are added.
#### Time range
-By default, reports use the saved time range of the dashboard. Optionally, you can change the time range of the report by:
-
-- Saving a modified time range to the dashboard. Changing the dashboard time range without saving it doesn't change the time zone of the report.
-- Setting a time range via the **Time range** field in the report form. If specified, the custom time range overrides the time range from the report's dashboard.
+If you leave the **Time range** field empty, reports use the saved time range of the dashboard.
+Optionally, you can change the time range of the report by setting it in the **Time range** field.
+If specified, the custom time range overrides the time range from the report's dashboard.
The page header of the report displays the time range for the dashboard's data queries.
##### Report time zones
-Reports use the time zone of the dashboard from which they’re generated. You can control the time zone for your reports by setting the dashboard to a specific time zone. Note that this affects the display of the dashboard for all users.
+Reports use the time zone of the dashboard from which they're generated.
+You can control the time zone for your reports by setting the dashboard to a specific time zone.
+Note that this affects the display of the dashboard for all users.
-If a dashboard has the **Browser Time** setting, the reports generated from that dashboard use the time zone of the Grafana server. As a result, this time zone might not match the time zone of users creating or receiving the report.
+If a dashboard has the **Browser Time** setting, the reports generated from that dashboard use the time zone of the Grafana server.
+As a result, this time zone might not match the time zone of users creating or receiving the report.
+If you want to use a specific time zone, save the dashboard with a fixed time zone instead of **Browser Time**
-If the time zone is set differently between your Grafana server and its remote image renderer, then the time ranges in the report might be different between the page header and the time axes in the panels. To avoid this, set the time zone to UTC for dashboards when using a remote renderer. Each dashboard's time zone setting is visible in the [time range controls](ref:time-range-controls).
+Each dashboard's time zone setting is visible in the [time range controls](ref:time-range-controls).
### 2. Format report
-At this step, set the report formatting options. You can select multiple options:
+At this step, select one or more report formatting options.
+You can select multiple options, but you must select _at least one_:
- [Attach the report as a PDF](#attach-the-report-as-a-pdf)
- [Include table data as PDF appendix](#table-data-in-pdf) (Public preview only)
@@ -212,13 +191,18 @@ At this step, set the report formatting options. You can select multiple options
#### Attach the report as a PDF
-If you selected the PDF format option, under the **Style the PDF** section, set the following options:
+If you selected the PDF format option under the **Style the PDF** section, you can configure the following options:
-- **Show template variables** - Click the checkbox to select this option.
+- **Configure multiple PDFs** - Click the **Combine all dashboard PDFs in one file** checkbox if you want to generate one PDF file for all the dashboards included in the report. This option is only displayed if your report includes multiple dashboards.
+- **Configure report header** - Click the **Show template variables** checkbox to show dashboard variables.
- **Orientation** - Set the report orientation in **Portrait** or **Landscape**. Refer to the [Layout and orientation table](#layout-and-orientation) to see examples.
- **Layout** - Select one of the following:
- - **Simple** - Renders each panel as full-width across the PDF. Refer to the [Layout and orientation table](#layout-and-orientation) to see examples.
- - **Grid** - Renders the PDF with the same panel arrangement and width as the source dashboard. Refer to the [Layout and orientation table](#layout-and-orientation) to see examples.
+
+ - **Simple** - Renders each panel as full-width across the PDF.
+ - **Grid** - Renders the PDF with the same panel arrangement and width as the source dashboard.
+
+ Refer to the [Layout and orientation table](#layout-and-orientation) to see examples.
+
- **Zoom** - Zoom in to enlarge text in your PDF, or zoom out to see more data (like table columns) per panel.
Click **Preview PDF** in the top-right corner of the screen to view a rendered PDF with the options you selected.
@@ -238,50 +222,40 @@ Click **Preview PDF** in the top-right corner of the screen to view a rendered P
#### Embed a dashboard as an image in the email
-You can send a report email with an image of the dashboard embedded in the email instead of attached as a PDF. In this case, the email recipients can see the dashboard at a glance instead of having to open the PDF.
+You can send a report email with an image of the dashboard embedded in the email.
+This lets the email recipients see the dashboard at a glance.
#### Attach a CSV file of the table panel data
-{{< admonition type="note" >}}
-To use this feature in Grafana Enterprise, you must have [Grafana image renderer plugin](/grafana/plugins/grafana-image-renderer) v3.0.
-{{< /admonition >}}
+You can attach a CSV file to the report email for each table panel on the selected dashboard.
-You can attach a CSV file to the report email for each table panel on the selected dashboard, along with the PDF report. By default, CSV files larger than 10Mb are not sent, which keeps email servers from rejecting the email. You can increase or decrease this limit in the [reporting configuration](ref:rendering-configuration).
-
-This feature relies on the same plugin that supports the [image rendering](ref:image-rendering) features.
-
-When the CSV file is generated, it is temporarily written to the `csv` folder in the Grafana `data` folder.
-
-A background job runs every 10 minutes and removes temporary CSV files. You can configure how long a CSV file should be stored before being removed by configuring the [temp-data-lifetime](ref:temp-data-lifetime) setting. This setting also affects how long a renderer PNG file should be stored.
-
-Click **Download CSV** in the top-right corner of the screen to see the file.
+Click **Download CSV** in the top-right corner of the screen to download a zipped file of the CSV files for your selected dashboard.
#### Table data in PDF
-{{% admonition type="note" %}}
-Available in public preview (`pdfTables` feature toggle) in [Grafana Enterprise](ref:grafana-enterprise) v10.3+ with the [Grafana image renderer plugin](/grafana/plugins/grafana-image-renderer) v3.0+, as well as [Grafana Cloud](/docs/grafana-cloud/).
-{{% /admonition %}}
+{{< admonition type="note" >}}
+Available in public preview (`pdfTables` feature toggle) in [Grafana Enterprise](ref:grafana-enterprise) v10.3+ with the [Grafana image renderer plugin](/grafana/plugins/grafana-image-renderer) v3.0+, as well as in [Grafana Cloud](/docs/grafana-cloud/).
+{{< /admonition >}}
When there's more data in your table visualizations than can be shown in the dashboard PDF, you can select one of these two options to access all table visualization data as PDF in your reports:
-- **Include table data as PDF appendix** - Adds an appendix to the main dashboard PDF.
+- **Include table data as PDF appendix** - Adds an appendix to the dashboard PDF.
- **Attach a separate PDF of table data** - Generates a separate PDF file.
-This feature relies on the same plugin that supports the [image rendering](ref:image-rendering) features.
-
### 3. Schedule
-At this step, set scheduling information. Options vary depending on the frequency you select.
+At this step, set scheduling information.
+Options vary depending on the frequency you select.
| Option | Description |
| ------ | ----------- |
-| Frequency | Scheduled reports can be sent once, or repeated on an hourly, daily, weekly, or monthly basis, or sent at custom intervals. You can also disable scheduling by selecting **Never**, for example to send the report using the API. |
+| Frequency | You can schedule reports to be sent once, or repeated on an hourly, daily, weekly, or monthly basis, or sent at custom intervals. You can also disable scheduling by selecting **Never**. For example, you might want to [send the report using the API](#send-a-report-using-the-api). |
| Time | Choose one of the following:- **Send now** sends the report immediately after you save it. To stop sending the report at some point in the future, add an end date.
- **Send later** schedules a report for a later date. When you select this option, the required **Start date**, **Start time**, and **Time zone** options are displayed.
|
-| End date | If you leave the end date empty, the report is sent out indefinitely. |
+| End date | If you leave this field empty, the report is sent out indefinitely. |
| Send only from Monday to Friday | For reports that have an hourly or daily frequency, you can choose to send them only from Monday to Friday. |
-| Send on the last day of the month | When you schedule a report with a monthly frequency, and set the start date between the 29th and the 31st of the month, the report is only sent during the months that have those dates. If you want the report to be sent every month, select this option instead. This way, the report is sent on the last day of every month regardless of how many days there are in any given month. |
+| Send on the last day of the month | When you schedule a report with a monthly frequency, and set the start date between the 29th and the 31st of the month, the report is only sent during the months that have those dates. If you want the report to be sent every month, select the **Send on the last day of the month** option. This way, the report is sent on the last day of every month regardless of how many days there are in the month. |
@@ -289,23 +263,29 @@ At this step, set scheduling information. Options vary depending on the frequenc
At this step, enter information related to sharing the report:
+
+
| Option | Description |
| ------ | ----------- |
-| Report name | Name of the report as you want it to appear in the **Reports** list. The report name also populates the email subject line. |
-| Recipients | Enter the email addresses of the people or teams that you want to receive the report, separated by commas or semicolons. |
+| Report name (required) | The name of the report as you want it to appear in the **Reports** list. The report name also populates the email subject line. |
+| Recipients (required) | Enter the email addresses of the people or teams that you want to receive the report, separated by commas or semicolons. |
| Reply-to email address | The address that appears in the **Reply to** field of the email. |
-| Message | Message body in the email with the report. |
-| Include a dashboard link | Include a link to the dashboard from within the report email. |
+| Message | The body of the message in the email with the report. |
+| Include a dashboard link | Include a links to the dashboards in the report email. |
-Click **Send test email** in the top-right corner of the screen to verify that the configuration works as expected and to verify that emails are working. You can choose to send this email to the recipients configured for the report, or to a different set of email addresses only used for testing. The last saved version of the report will be sent to selected emails.
+
+
+Click **Send test email** in the top-right corner of the screen to verify that the configuration works as expected and to verify that emails are working.
+You can choose to send this email to the recipients configured for the report, or to a different set of email addresses only used for testing.
### 5. Confirm
-At this step, the confirmation page displays all your the settings. Review them and confirm that they're correct or click the provided **Edit** links for each section to make updates.
+At this step, the confirmation page displays all the report settings.
+Review them and confirm that they're correct or click the provided **Edit** links for each section to make updates.
Then, click **Send now** or **Schedule send**.
@@ -313,7 +293,7 @@ You can also save the report as a draft or discard it. Discarding the report is
## Send a report using the API
-You can send reports programmatically with the [send report](ref:send-report) endpoint in the [HTTP APIs](ref:http-apis).
+You can send reports programmatically with the [send report](ref:send-report) endpoint using the HTTP API.
## Manage reports
@@ -321,7 +301,7 @@ On the **Reports** page, you can view and manage your existing reports or create

-### Edit
+### Edit reports
To edit a report, follow these steps:
@@ -331,9 +311,10 @@ To edit a report, follow these steps:
1. When you've finished making changes, click **Confirm** at the top of the screen to go to the last step.
1. Click **Update report**.
-### Pause or resume a report
+### Pause or resume reports {#pause-a-report}
-You can pause and resume sending reports from the report list view. To do this, follow these steps:
+You can pause and resume sending reports from the report list view.
+To do this, follow these steps:
1. In the main menu, click **Dashboards > Reporting**.
1. On the row of the report you want to update, do one of the following:
@@ -341,11 +322,22 @@ You can pause and resume sending reports from the report list view. To do this,
- Click the pause icon - The report won't be sent according to its schedule until it's resumed.
- Click the resume icon - The report resumes on its previous schedule.
+### Delete reports
+
+To delete a report, follow these steps:
+
+1. In the main menu, click **Dashboards > Reporting**.
+1. On the row of the report you want to update, click the trash can icon.
+1. Click **Delete** to confirm.
+
+Deleting a report is irreversible.
+
## Troubleshoot Reporting
-To troubleshoot and get more log information, enable debug logging in the configuration file. Refer to [Configuration](ref:configuration) for more information.
+To troubleshoot and get more log information, enable debug logging in the configuration file.
+Refer to the [log filters configuration documentation](ref:log-filters) for more information.
```bash
[log]
-filters = report:debug
+filters = rendering:debug,report.api:debug,report.render:debug,report.scheduler:debug,report.sender:debug,report.service:debug
```
diff --git a/docs/sources/dashboards/create-reports/report-settings/index.md b/docs/sources/dashboards/create-reports/report-settings/index.md
index c442a4346a8..b878953b71a 100644
--- a/docs/sources/dashboards/create-reports/report-settings/index.md
+++ b/docs/sources/dashboards/create-reports/report-settings/index.md
@@ -12,21 +12,17 @@ title: Reporting settings
description: Manage organizational Reporting settings
weight: 700
refs:
- grafana-enterprise:
+ change-ui-theme:
- pattern: /docs/grafana/
- destination: /docs/grafana//introduction/grafana-enterprise/
+ destination: /docs/grafana//administration/organization-preferences/#change-grafana-ui-theme
- pattern: /docs/grafana-cloud/
- destination: /docs/grafana//introduction/grafana-enterprise/
- configuration:
- - pattern: /docs/grafana/
- destination: /docs/grafana//setup-grafana/configure-grafana/#filters
- - pattern: /docs/grafana-cloud/
- destination: /docs/grafana//setup-grafana/configure-grafana/#filters
+ destination: /docs/grafana//administration/organization-preferences/#change-grafana-ui-theme
---
# Reporting settings
-You can configure organization-wide report settings and branding options in **Dashboards > Reporting > Settings**. Settings are applied to all the reports for the current organization.
+You can configure organization-wide report settings and branding options in **Dashboards > Reporting > Settings**.
+Settings are applied to all the reports for the current organization.
## Attachment settings
@@ -34,13 +30,22 @@ The options in this section control the branding and theming of the report attac
### PDF
-- **Company logo** - Company logo displayed in the report PDF. It can be configured by specifying a URL, or by uploading a file. The maximum file size is 16 MB. Defaults to the Grafana logo.
+- **Company logo** - Company logo displayed in the report PDF.
+ Configure it by specifying a URL or uploading a file.
+ The maximum file size is 16 MB.
+ Defaults to the Grafana logo.
-- **Theme** - Theme of the PDF attached to the report. Defaults to **Light**. The selected theme is also applied to the PDFs generated when you click **Preview PDF** during report creation or select the **Export as PDF** option on a dashboard. If **Current** is selected, the PDF in the report will be in the instance theme of the Admin, but the preview and exported PDFs will be in the user's instance theme.
+- **Theme** - Theme of the PDF attached to the report.
+ The selected theme is also applied to the PDFs generated when you click **Preview PDF** during report creation or select the **Export as PDF** option on a dashboard.
+
+ If **Current** is selected, the PDF in the report is in the instance theme of the report creator, but the preview and exported PDFs are in the user's instance theme.
+ Defaults to **Light**.
### Embedded Image
-- **Theme** - Theme of the dashboard image embedded in the email. Defaults to **Dark**.
+- **Theme** - Theme of the dashboard image embedded in the email.
+ If **Current** is selected, the image in the report is in the instance theme of the report creator. If the report creator doesn't have a theme set, then the team, organization, or server theme is used. For more information refer to [Change Grafana UI theme](ref:change-ui-theme).
+ Defaults to **Dark**.
@@ -48,9 +53,10 @@ The options in this section control the branding and theming of the report attac
-- **Company logo** - Company logo displayed in the report email. It can be configured by specifying a URL, or by uploading a file. The maximum file size is 16 MB. Defaults to the Grafana logo.
+- **Company logo** - Company logo displayed in the report email. Configure it by specifying a URL or uploading a file. The maximum file size is 16 MB. Defaults to the Grafana logo.
- **Email footer** - Toggle to enable the report email footer. Select **Sent by** or **None**.
- **Footer link text** - Text of the link in the report email footer. Defaults to `Grafana`.
- **Footer link URL** - Link of the report email footer.
-Currently, the API does not allow for the simultaneous upload of files with identical names for both the email logo and report logo. You can still upload the same file for each logo separately in two distinct steps.
+Currently, the API does not allow for the simultaneous upload of files with identical names for both the email logo and report logo.
+You can still upload the same file for each logo separately in two distinct steps.
diff --git a/docs/sources/dashboards/share-dashboards-panels/_index.md b/docs/sources/dashboards/share-dashboards-panels/_index.md
index b9d84b58ab6..d424a4b75fb 100644
--- a/docs/sources/dashboards/share-dashboards-panels/_index.md
+++ b/docs/sources/dashboards/share-dashboards-panels/_index.md
@@ -44,9 +44,9 @@ refs:
destination: /docs/grafana/grafana-cloud/visualizations/dashboards/share-dashboards-panels/shared-dashboards/
configure-report:
- pattern: /docs/grafana/
- destination: /docs/grafana//dashboards/create-reports/#create-or-update-a-report
+ destination: /docs/grafana//dashboards/create-reports/#create-a-report
- pattern: /docs/grafana-cloud/
- destination: /docs/grafana-cloud/visualizations/dashboards/create-reports/#create-or-update-a-report
+ destination: /docs/grafana-cloud/visualizations/dashboards/create-reports/#create-a-report
image-rendering-config:
- pattern: /docs/grafana/
destination: /docs/grafana//setup-grafana/image-rendering/#configuration
@@ -81,8 +81,6 @@ Grafana enables you to share dashboards and panels with other users within your
- Reports
- Library panels
-You can also invite new members to your organization from the **Share** menu. For more information, refer to [Invite new members](#invite-new-members).
-
You must have an authorized viewer permission to see an image rendered by a direct link. The same permission is also required to view embedded links unless you have anonymous access permission enabled for your Grafana instance.
{{< admonition type="note" >}}
@@ -140,7 +138,7 @@ Learn how to configure and manage externally shared dashboards in [Externally sh
### Schedule a report
{{< admonition type="note" >}}
-This feature is only available in Grafana Enterprise.
+This feature is only available on Grafana Enterprise.
{{< /admonition >}}
To share your dashboard as a report, follow these steps:
@@ -204,6 +202,10 @@ In addition to sharing dashboards as links, reports, and snapshots, you can expo
### Export a dashboard as PDF
+{{< admonition type="note" >}}
+This feature is only available on Grafana Enterprise.
+{{< /admonition >}}
+
To export a dashboard in its current state as a PDF, follow these steps:
1. Click **Dashboards** in the main menu.
@@ -365,23 +367,3 @@ To delete existing snapshots, follow these steps:
1. Click the red **x** next to the snapshot URL that you want to delete.
The snapshot is immediately deleted. You may need to clear your browser cache or use a private or incognito browser to confirm this.
-
-## Invite new members
-
-{{< admonition type="note" >}}
-This feature is only available on Grafana Cloud.
-{{< /admonition >}}
-
-You can invite new members to your organization using the **Share** drop-down menu. You must have the `OrgUsersAdd` permission to use this feature.
-
-To invite a new member to your organization, follow these steps:
-
-1. Click **Dashboards** in the main menu and open any dashboard.
-1. Click the **Share** drop-down list in the top-right corner and select **Invite new member**.
-
- The **Members** page of your Grafana Cloud Portal opens.
-
-1. Enter the email address of the new member in the provided field.
-1. Make a selection in the **Role** drop-down list.
-1. (Optional) Select the **Receive billing emails** checkbox, if applicable.
-1. Click **Invite**.
diff --git a/docs/sources/dashboards/variables/add-template-variables/index.md b/docs/sources/dashboards/variables/add-template-variables/index.md
index fa4e49ef5a4..54dc20e2d47 100644
--- a/docs/sources/dashboards/variables/add-template-variables/index.md
+++ b/docs/sources/dashboards/variables/add-template-variables/index.md
@@ -89,6 +89,8 @@ refs:
# Add variables
+
+
The following table lists the types of variables shipped with Grafana.
| Variable type | Description |
@@ -134,11 +136,13 @@ To create a variable, follow these steps:
- [Interval](#add-an-interval-variable)
- [Ad hoc filters](#add-ad-hoc-filters)
+
+
## Add a query variable
Query variables enable you to write a data source query that can return a list of metric names, tag values, or keys. For example, a query variable might return a list of server names, sensor IDs, or data centers. The variable values change as they dynamically fetch options with a data source query.
-Query variables are generally only supported for strings. If your query returns numbers or any other data type, you might need to convert them to strings in order to use them as variables. For the Azure data source, for example, you can use the [tostring](https://docs.microsoft.com/en-us/azure/data-explorer/kusto/query/tostringfunction) function for this purpose.
+Query variables are generally only supported for strings. If your query returns numbers or any other data type, you might need to convert them to strings to use them as variables. For the Azure data source, for example, you can use the [`tostring`](https://docs.microsoft.com/en-us/azure/data-explorer/kusto/query/tostringfunction) function for this purpose.
Query expressions can contain references to other variables and in effect create linked variables. Grafana detects this and automatically refreshes a variable when one of its linked variables change.
@@ -168,7 +172,7 @@ Query expressions are different for each data source. For more information, refe
- Some data sources let you provide custom "display names" for the values. For instance, the PostgreSQL, MySQL, and Microsoft SQL Server plugins handle this by looking for fields named `__text` and `__value` in the result. Other data sources may look for `text` and `value` or use a different approach. Always remember to double-check the documentation for the data source.
- If you need more room in a single input field query editor, then hover your cursor over the lines in the lower right corner of the field and drag downward to expand.
-1. (Optional) In the **Regex** field, type a regex expression to filter or capture specific parts of the names returned by your data source query. To see examples, refer to [Filter variables with regex](#filter-variables-with-regex).
+1. (Optional) In the **Regex** field, type a regular expression to filter or capture specific parts of the names returned by your data source query. To see examples, refer to [Filter variables with a regular expression](#filter-variables-with-regex).
1. In the **Sort** drop-down list, select the sort order for values to be displayed in the dropdown list. The default option, **Disabled**, means that the order of options returned by your data source query is used.
1. Under **Refresh**, select when the variable should update options:
@@ -240,7 +244,7 @@ _Data source_ variables enable you to quickly change the data source for an enti
1. [Enter general options](#enter-general-options).
1. Under the **Data source options** section of the page, in the **Type** drop-down list, select the target data source for the variable.
-1. (Optional) In **Instance name filter**, enter a regex filter for which data source instances to choose from in the variable value drop-down list.
+1. (Optional) In **Instance name filter**, enter a regular expression filter for which data source instances to choose from in the variable value drop-down list.
Leave this field empty to display all instances.
@@ -289,6 +293,9 @@ The following example shows a more complex Graphite example, from the [Graphite
groupByNode(summarize(movingAverage(apps.$app.$server.counters.requests.count, 5), '$interval', 'sum', false), 2, 'sum')
```
+
+
+
## Add ad hoc filters
_Ad hoc filters_ are one of the most complex and flexible variable options available.
@@ -298,10 +305,10 @@ Ad hoc filters let you add label/value filters that are automatically added to a
Unlike other variables, you don't use ad hoc filters in queries.
Instead, you use ad hoc filters to write filters for existing queries.
-{{% admonition type="note" %}}
+{{< admonition type="note" >}}
Not all data sources support ad hoc filters.
Examples of those that do include Prometheus, Loki, InfluxDB, and Elasticsearch.
-{{% /admonition %}}
+{{< /admonition >}}
To create an ad hoc filter, follow these steps:
@@ -318,6 +325,9 @@ To create an ad hoc filter, follow these steps:
Now you can [filter data on the dashboard](ref:filter-dashboard).
+
+
+
## Configure variable selection options
**Selection Options** are a feature you can use to manage variable option selections. All selection options are optional, and they are off by default.
@@ -326,9 +336,9 @@ Now you can [filter data on the dashboard](ref:filter-dashboard).
Interpolating a variable with multiple values selected is tricky as it is not straight forward how to format the multiple values into a string that is valid in the given context where the variable is used. Grafana tries to solve this by allowing each data source plugin to inform the templating interpolation engine what format to use for multiple values.
-{{% admonition type="note" %}}
+{{< admonition type="note" >}}
The **Custom all value** option on the variable must be blank for Grafana to format all values into a single string. If it is left blank, then Grafana concatenates (adds together) all the values in the query. Something like `value1,value2,value3`. If a custom `all` value is used, then instead the value is something like `*` or `all`.
-{{% /admonition %}}
+{{< /admonition >}}
#### Multi-value variables with a Graphite data source
@@ -336,17 +346,17 @@ Graphite uses glob expressions. A variable with multiple values would, in this c
#### Multi-value variables with a Prometheus or InfluxDB data source
-InfluxDB and Prometheus use regex expressions, so the same variable would be interpolated as `(host1|host2|host3)`. Every value would also be regex escaped. If not, a value with a regex control character would break the regex expression.
+InfluxDB and Prometheus use regular expressions, so the same variable would be interpolated as `(host1|host2|host3)`. Every value would also be regular expression escaped. If not, a value with a regular expression control character would break the regular expression.
#### Multi-value variables with an Elastic data source
-Elasticsearch uses lucene query syntax, so the same variable would be formatted as `("host1" OR "host2" OR "host3")`. In this case, every value must be escaped so that the value only contains lucene control words and quotation marks.
+Elasticsearch uses Lucene query syntax, so the same variable would be formatted as `("host1" OR "host2" OR "host3")`. In this case, every value must be escaped so that the value only contains Lucene control words and quotation marks.
#### Troubleshoot multi-value variables
-Automatic escaping and formatting can cause problems and it can be tricky to grasp the logic behind it. Especially for InfluxDB and Prometheus where the use of regex syntax requires that the variable is used in regex operator context.
+Automatic escaping and formatting can cause problems and it can be tricky to grasp the logic behind it. Especially for InfluxDB and Prometheus where the use of regular expression syntax requires that the variable is used in regular expression operator context.
-If you do not want Grafana to do this automatic regex escaping and formatting, then you must do one of the following:
+If you do not want Grafana to do this automatic regular expression escaping and formatting, then you must do one of the following:
- Turn off the **Multi-value** or **Include All option** options.
- Use the [raw variable format](ref:raw-variable-format).
@@ -359,28 +369,28 @@ Grafana adds an `All` option to the variable dropdown list. If a user selects th
This option is only visible if the **Include All option** is selected.
-Enter regex, globs, or lucene syntax in the **Custom all value** field to define the value of the `All` option.
+Enter regular expressions, globs, or Lucene syntax in the **Custom all value** field to define the value of the `All` option.
-By default the `All` value includes all options in combined expression. This can become very long and can have performance problems. Sometimes it can be better to specify a custom all value, like a wildcard regex.
+By default the `All` value includes all options in combined expression. This can become very long and can have performance problems. Sometimes it can be better to specify a custom all value, like a wildcard regular expression.
-In order to have custom regex, globs, or lucene syntax in the **Custom all value** option, it is never escaped so you have to think about what is a valid value for your data source.
+In order to have custom regular expression, globs, or Lucene syntax in the **Custom all value** option, it is never escaped so you have to think about what is a valid value for your data source.
## Global variables
Grafana has global built-in variables that can be used in expressions in the query editor. This topic lists them in alphabetical order and defines them. These variables are useful in queries, dashboard links, panel links, and data links.
-### $\_\_dashboard
+### `$__dashboard`
This variable is the name of the current dashboard.
-### $\_\_from and $\_\_to
+### `$__from` and `$__to`
Grafana has two built-in time range variables: `$__from` and `$__to`. They are currently always interpolated as epoch milliseconds by default, but you can control date formatting.
| Syntax | Example result | Description |
| ------------------------ | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `${__from}` | 1594671549254 | Unix millisecond epoch |
-| `${__from:date}` | 2020-07-13T20:19:09.254Z | No args, defaults to ISO 8601/RFC 3339 |
+| `${__from:date}` | 2020-07-13T20:19:09.254Z | No arguments, defaults to ISO 8601/RFC 3339 |
| `${__from:date:iso}` | 2020-07-13T20:19:09.254Z | ISO 8601/RFC 3339 |
| `${__from:date:seconds}` | 1594671549 | Unix seconds epoch |
| `${__from:date:YYYY-MM}` | 2020-07 | Any custom [date format](https://momentjs.com/docs/#/displaying/) that does not include the `:` character. Uses browser time. Use `:date` or `:date:iso` for UTC |
@@ -389,7 +399,7 @@ The syntax above also works with `${__to}`.
You can use this variable in URLs, as well. For example, you can send a user to a dashboard that shows a time range from six hours ago until now: https://play.grafana.org/d/000000012/grafana-play-home?viewPanel=2&orgId=1?from=now-6h&to=now
-### $\_\_interval
+### `$__interval`
You can use the `$__interval` variable as a parameter to group by time (for InfluxDB, MySQL, Postgres, MSSQL), Date histogram interval (for Elasticsearch), or as a _summarize_ function parameter (for Graphite).
@@ -403,42 +413,42 @@ In the InfluxDB data source, the legacy variable `$interval` is the same variabl
The InfluxDB and Elasticsearch data sources have `Group by time interval` fields that are used to hard code the interval or to set the minimum limit for the `$__interval` variable (by using the `>` syntax -> `>10m`).
-### $\_\_interval_ms
+### `$__interval_ms`
This variable is the `$__interval` variable in milliseconds, not a time interval formatted string. For example, if the `$__interval` is `20m` then the `$__interval_ms` is `1200000`.
-### $\_\_name
+### `$__name`
-This variable is only available in the Singlestat panel and can be used in the prefix or suffix fields on the Options tab. The variable is replaced with the series name or alias.
+This variable is only available in the **Singlestat** panel and can be used in the prefix or suffix fields on the Options tab. The variable is replaced with the series name or alias.
-{{% admonition type="note" %}}
-The Singlestat panel is no longer available from Grafana 8.0.
-{{% /admonition %}}
+{{< admonition type="note" >}}
+The **Singlestat** panel is no longer available from Grafana 8.0.
+{{< /admonition >}}
-### $\_\_org
+### `$__org`
This variable is the ID of the current organization.
`${__org.name}` is the name of the current organization.
-### $\_\_user
+### `$__user`
`${__user.id}` is the ID of the current user.
`${__user.login}` is the login handle of the current user.
`${__user.email}` is the email for the current user.
-### $\_\_range
+### `$__range`
Currently only supported for Prometheus and Loki data sources. This variable represents the range for the current dashboard. It is calculated by `to - from`. It has a millisecond and a second representation called `$__range_ms` and `$__range_s`.
-### $\_\_rate_interval
+### `$__rate_interval`
Currently only supported for Prometheus data sources. The `$__rate_interval` variable is meant to be used in the rate function. Refer to [Prometheus query variables](ref:prometheus-query-variables) for details.
-### $\_\_rate_interval_ms
+### `$__rate_interval_ms`
This variable is the `$__rate_interval` variable in milliseconds, not a time-interval-formatted string. For example, if the `$__rate_interval` is `20m` then the `$__rate_interval_ms` is `1200000`.
-### $timeFilter or $\_\_timeFilter
+### `$timeFilter` or `$__timeFilter`
The `$timeFilter` variable returns the currently selected time range as an expression. For example, the time range interval `Last 7 days` expression is `time > now() - 7d`.
@@ -449,7 +459,7 @@ This is used in several places, including:
- SQL queries in MySQL, Postgres, and MSSQL.
- The `$__timeFilter` variable is used in the MySQL data source.
-### $\_\_timezone
+### `$__timezone`
The `$__timezone` variable returns the currently selected time zone, either `utc` or an entry of the IANA time zone database (for example, `America/New_York`).
@@ -485,9 +495,9 @@ In this example, there are several applications. Each application has a differen
Now, you could make separate variables for each metric source, but then you have to know which server goes with which app. A better solution is to use one variable to filter another. In this example, when the user changes the value of the `app` variable, it changes the dropdown options returned by the `server` variable. Both variables use the **Multi-value** option and **Include all option**, enabling users to select some or all options presented at any time.
-##### app variable
+##### `app` variable
-The query for this variable basically says, "Give me all the applications that exist."
+The query for this variable basically says, "Find all the applications that exist."
```
apps.*
@@ -495,9 +505,9 @@ apps.*
The values returned are `backend`, `country`, `fakesite`, and `All`.
-##### server variable
+##### `server` variable
-The query for this variable basically says, "Give me all servers for the currently chosen application."
+The query for this variable basically says, "Find all servers for the currently chosen application."
```
apps.$app.*
@@ -521,9 +531,9 @@ The query returns all servers associated with `fakesite`, including `web_server_
##### More variables
-{{% admonition type="note" %}}
+{{< admonition type="note" >}}
This example is theoretical. The Graphite server used in the example does not contain CPU metrics.
-{{% /admonition %}}
+{{< /admonition >}}
The dashboard stops at two levels, but you could keep going. For example, if you wanted to get CPU metrics for selected servers, you could copy the `server` variable and extend the query so that it reads:
@@ -531,7 +541,7 @@ The dashboard stops at two levels, but you could keep going. For example, if you
apps.$app.$server.cpu.*
```
-This query basically says, "Show me the CPU metrics for the selected server."
+This query basically says, "Find the CPU metrics for the selected server."
Depending on what variable options the user selects, you could get queries like:
@@ -547,9 +557,9 @@ In this example, you have several data centers. Each data center has a different
In this example, when the user changes the value of the `datacenter` variable, it changes the dropdown options returned by the `host` variable. The `host` variable uses the **Multi-value** option and **Include all option**, allowing users to select some or all options presented at any time. The `datacenter` does not use either option, so you can only select one data center at a time.
-##### datacenter variable
+##### `datacenter` variable
-The query for this variable basically says, "Give me all the data centers that exist."
+The query for this variable basically says, "Find all the data centers that exist."
```
SHOW TAG VALUES WITH KEY = "datacenter"
@@ -557,9 +567,9 @@ SHOW TAG VALUES WITH KEY = "datacenter"
The values returned are `America`, `Africa`, `Asia`, and `Europe`.
-##### host variable
+##### `host` variable
-The query for this variable basically says, "Give me all hosts for the currently chosen data center."
+The query for this variable basically says, "Find all hosts for the currently chosen data center."
```
SHOW TAG VALUES WITH KEY = "hostname" WHERE "datacenter" =~ /^$datacenter$/
@@ -583,9 +593,9 @@ The query returns all servers associated with `Europe`, including `server3`, `se
##### More variables
-{{% admonition type="note" %}}
+{{< admonition type="note" >}}
This example is theoretical. The InfluxDB server used in the example does not contain CPU metrics.
-{{% /admonition %}}
+{{< /admonition >}}
The dashboard stops at two levels, but you could keep going. For example, if you wanted to get CPU metrics for selected hosts, you could copy the `host` variable and extend the query so that it reads:
@@ -593,7 +603,7 @@ The dashboard stops at two levels, but you could keep going. For example, if you
SHOW TAG VALUES WITH KEY = "cpu" WHERE "datacenter" =~ /^$datacenter$/ AND "host" =~ /^$host$/
```
-This query basically says, "Show me the CPU metrics for the selected host."
+This query basically says, "Find the CPU metrics for the selected host."
Depending on what variable options the user selects, you could get queries like:
@@ -607,7 +617,7 @@ SHOW TAG VALUES WITH KEY = "cpu" WHERE "datacenter" =~ /^Europe/ AND "host" =~ /
The following practices make your dashboards and variables easier to use.
-#### Creating new linked variables
+#### New linked variables creation
- Chaining variables create parent/child dependencies. You can envision them as a ladder or a tree.
- The easiest way to create a new chained variable is to copy the variable that you want to base the new one on. In the variable list, click the **Duplicate variable** icon to the right of the variable entry to create a copy. You can then add on to the query for the parent variable.
@@ -627,13 +637,17 @@ The more layers of dependency you have in variables, the longer it takes to upda
For example, if you have a series of four linked variables (country, region, server, metric) and you change a root variable value (country), then Grafana must run queries for all the dependent variables before it updates the visualizations in the dashboard.
-## Filter variables with regex
+
-Using the Regex Query option, you filter the list of options returned by the variable query or modify the options returned.
+## Filter variables with regular expressions {#filter-variables-with-regex}
-This page shows how to use regex to filter/modify values in the variable dropdown.
+
-Using the Regex Query Option, you filter the list of options returned by the Variable query or modify the options returned. For more information, refer to the Mozilla guide on [Regular expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions).
+Using the **Regex** query option, you filter the list of options returned by the variable query or modify the options returned.
+
+This page shows how to use a regular expression to filter/modify values in the variable dropdown.
+
+Using the **Regex** query option, you filter the list of options returned by the Variable query or modify the options returned. For more information, refer to the Mozilla guide on [Regular expressions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions).
Examples of filtering on the following list of options:
@@ -646,7 +660,7 @@ backend_04
### Filter so that only the options that end with `01` or `02` are returned:
-Regex:
+**Regex**:
```regex
/(01|02)$/
@@ -659,9 +673,9 @@ backend_01
backend_02
```
-### Filter and modify the options using a regex capture group to return part of the text:
+### Filter and modify the options using a regular expression to capture group to return part of the text:
-Regex:
+**Regex**:
```regex
/.*(01|02)/
@@ -684,7 +698,7 @@ up{instance="demo.robustperception.io:9093",job="alertmanager"} 1 1521630638000
up{instance="demo.robustperception.io:9100",job="node"} 1 1521630638000
```
-Regex:
+**Regex**:
```regex
/.*instance="([^"]*).*/
@@ -711,7 +725,7 @@ node_hwmon_chip_names{chip="0000:d7:00_0_0000:d8:00_2",chip_name="enp216s0f0np2"
node_hwmon_chip_names{chip="0000:d7:00_0_0000:d8:00_3",chip_name="enp216s0f0np3"} 1
```
-Passed through the following Regex:
+Passed through the following regular expression:
```regex
/chip_name="(?[^"]+)|chip="(?[^"]+)/g
diff --git a/docs/sources/datasources/_index.md b/docs/sources/datasources/_index.md
index 89fe11e36e5..5543b37434a 100644
--- a/docs/sources/datasources/_index.md
+++ b/docs/sources/datasources/_index.md
@@ -117,7 +117,7 @@ Grafana includes three special data sources:
### Grafana
-A built-in data source that generates random walk data and can poll the [Testdata]({{< relref "./testdata/" >}}) data source. Additionally, it can list files and get other data from a Grafana installation. This can be helpful for testing visualizations and running experiments.
+A built-in data source that generates random walk data and can poll the [Testdata](testdata/) data source. Additionally, it can list files and get other data from a Grafana installation. This can be helpful for testing visualizations and running experiments.
### Mixed
@@ -140,24 +140,24 @@ These built-in core data sources are also included in the Grafana documentation:
{{< column-list >}}
-- [Alertmanager]({{< relref "./alertmanager" >}})
-- [AWS CloudWatch]({{< relref "./aws-cloudwatch" >}})
-- [Azure Monitor]({{< relref "./azure-monitor" >}})
-- [Elasticsearch]({{< relref "./elasticsearch" >}})
-- [Google Cloud Monitoring]({{< relref "./google-cloud-monitoring" >}})
-- [Graphite]({{< relref "./graphite" >}})
-- [InfluxDB]({{< relref "./influxdb" >}})
-- [Jaeger]({{< relref "./jaeger" >}})
-- [Loki]({{< relref "./loki" >}})
-- [Microsoft SQL Server (MSSQL)]({{< relref "./mssql" >}})
-- [MySQL]({{< relref "./mysql" >}})
-- [OpenTSDB]({{< relref "./opentsdb" >}})
-- [PostgreSQL]({{< relref "./postgres" >}})
-- [Prometheus]({{< relref "./prometheus" >}})
-- [Pyroscope]({{< relref "./pyroscope" >}})
-- [Tempo]({{< relref "./tempo" >}})
-- [Testdata]({{< relref "./testdata" >}})
-- [Zipkin]({{< relref "./zipkin" >}})
+- [Alertmanager](alertmanager/)
+- [AWS CloudWatch](aws-cloudwatch/)
+- [Azure Monitor](azure-monitor/)
+- [Elasticsearch](elasticsearch/)
+- [Google Cloud Monitoring](google-cloud-monitoring/)
+- [Graphite](graphite/)
+- [InfluxDB](influxdb/)
+- [Jaeger](jaeger/)
+- [Loki](loki/)
+- [Microsoft SQL Server (MSSQL)](mssql/)
+- [MySQL](mysql/)
+- [OpenTSDB](opentsdb/)
+- [PostgreSQL](postgres/)
+- [Prometheus](prometheus/)
+- [Pyroscope](pyroscope/)
+- [Tempo](tempo/)
+- [Testdata](testdata/)
+- [Zipkin](zipkin/)
{{< /column-list >}}
diff --git a/docs/sources/datasources/aws-cloudwatch/_index.md b/docs/sources/datasources/aws-cloudwatch/_index.md
index 6e5d3a0618e..82aff4fb4ee 100644
--- a/docs/sources/datasources/aws-cloudwatch/_index.md
+++ b/docs/sources/datasources/aws-cloudwatch/_index.md
@@ -66,7 +66,7 @@ For instructions on how to add a data source to Grafana, refer to the [administr
Only users with the organization administrator role can add data sources.
Administrators can also [provision the data source](#provision-the-data-source) with Grafana's provisioning system, and should [control pricing](#control-pricing) and [manage service quotas](#manage-service-quotas) accordingly.
-Once you've added the data source, you can [configure it](#configure-the-data-source) so that your Grafana instance's users can create queries in its [query editor]({{< relref "./query-editor" >}}) when they [build dashboards](ref:build-dashboards) and use [Explore](ref:explore).
+Once you've added the data source, you can [configure it](#configure-the-data-source) so that your Grafana instance's users can create queries in its [query editor](query-editor/) when they [build dashboards](ref:build-dashboards) and use [Explore](ref:explore).
{{% admonition type="note" %}}
To troubleshoot issues while setting up the CloudWatch data source, check the `/var/log/grafana/grafana.log` file.
@@ -86,12 +86,12 @@ To troubleshoot issues while setting up the CloudWatch data source, check the `/
A Grafana plugin's requests to AWS are made on behalf of an AWS Identity and Access Management (IAM) role or IAM user.
The IAM user or IAM role must have the associated policies to perform certain API actions.
-For authentication options and configuration details, refer to [AWS authentication]({{< relref "./aws-authentication" >}}).
+For authentication options and configuration details, refer to [AWS authentication](aws-authentication/).
#### IAM policy examples
To read CloudWatch metrics and EC2 tags, instances, regions, and alarms, you must grant Grafana permissions via IAM.
-You can attach these permissions to the IAM role or IAM user you configured in [AWS authentication]({{< relref "./aws-authentication" >}}).
+You can attach these permissions to the IAM role or IAM user you configured in [AWS authentication](aws-authentication/).
##### Metrics-only permissions
@@ -354,7 +354,11 @@ datasources:
The CloudWatch data source can query data from both CloudWatch metrics and CloudWatch Logs APIs, each with its own specialized query editor.
-For details, see the [query editor documentation]({{< relref "./query-editor" >}}).
+For details, see the [query editor documentation](query-editor/).
+
+## Query caching
+
+When you enable [query and resource caching](/docs/grafana//administration/data-source-management/#query-and-resource-caching), Grafana temporarily stores the results of data source queries and resource requests. Query caching is available in CloudWatch Metrics in Grafana Cloud and Grafana Enterprise. It is not available in CloudWatch Logs Insights due to how query results are polled from AWS.
## Use template variables
@@ -362,7 +366,7 @@ Instead of hard-coding details such as server, application, and sensor names in
Grafana lists these variables in dropdown select boxes at the top of the dashboard to help you change the data displayed in your dashboard.
Grafana refers to such variables as template variables.
-For details, see the [template variables documentation]({{< relref "./template-variables" >}}).
+For details, see the [template variables documentation](template-variables/).
## Import pre-configured dashboards
@@ -438,7 +442,7 @@ For more information, refer to the AWS documentation for [Service Quotas](https:
The CloudWatch plugin enables you to monitor and troubleshoot applications across multiple regional accounts. Using cross-account observability, you can seamlessly search, visualize and analyze metrics and logs without worrying about account boundaries.
-To use this feature, configure in the [AWS console under Cloudwatch Settings](https://aws.amazon.com/blogs/aws/new-amazon-cloudwatch-cross-account-observability/), a monitoring and source account, and then add the necessary IAM permissions as described above.
+To use this feature, configure in the [AWS console under CloudWatch Settings](https://aws.amazon.com/blogs/aws/new-amazon-cloudwatch-cross-account-observability/), a monitoring and source account, and then add the necessary IAM permissions as described above.
## CloudWatch Logs data protection
diff --git a/docs/sources/datasources/aws-cloudwatch/aws-authentication/index.md b/docs/sources/datasources/aws-cloudwatch/aws-authentication/index.md
index 58c02f1ccb0..9ae64f44856 100644
--- a/docs/sources/datasources/aws-cloudwatch/aws-authentication/index.md
+++ b/docs/sources/datasources/aws-cloudwatch/aws-authentication/index.md
@@ -79,7 +79,7 @@ For example, you may have one set of long term credentials for all of your AWS d
Instead, using the assume role functionality, you could have one set of AWS credentials for all of your AWS data sources that has only one permission—the permission to assume a role with STS. Then you could create a separate IAM role for each data source that specifies which permissions that data source can temporarily assume. Since IAM roles are not credentials, there's no need to rotate them and they may be easier to manage.
-The Grafana Assume Role also helps facilitate this. Using this role, Grafana's AWS account acts as the primary credential, having only the permission to assume roles in other accounts. You can then create IAM roles for Grafana's account to assume. For more information, refer to [Use Grafana assume role]({{< relref "#use-grafana-assume-role" >}}).
+The Grafana Assume Role also helps facilitate this. Using this role, Grafana's AWS account acts as the primary credential, having only the permission to assume roles in other accounts. You can then create IAM roles for Grafana's account to assume. For more information, refer to [Use Grafana assume role](#use-grafana-assume-role).
If the **Assume Role ARN** field is left empty, Grafana uses the provided credentials from the selected authentication method directly, and permissions to AWS data must be attached directly to those credentials. The **Assume Role ARN** field is optional for all authentication methods except for Grafana Assume Role.
@@ -160,7 +160,7 @@ securityContext:
## Use Grafana Assume Role
{{% admonition type="note" %}}
-Grafana Assume Role is currently in [private preview]({{< relref "https://grafana.com/docs/release-life-cycle" >}}) for Grafana Cloud.
+Grafana Assume Role is currently in [private preview](https://grafana.com/docs/release-life-cycle/) for Grafana Cloud.
It's currently only available for Amazon CloudWatch.
diff --git a/docs/sources/datasources/aws-cloudwatch/query-editor/index.md b/docs/sources/datasources/aws-cloudwatch/query-editor/index.md
index b65bd308e77..f7cbce5a547 100644
--- a/docs/sources/datasources/aws-cloudwatch/query-editor/index.md
+++ b/docs/sources/datasources/aws-cloudwatch/query-editor/index.md
@@ -67,7 +67,7 @@ If you enable `Match Exact`, you must also specify all dimensions of the metric
If `Match Exact` is disabled, you can specify any number of dimensions on which you'd like to filter. With `Match Exact` disabled the query returns any metrics that match the namespace, metric name, and all defined dimensions, whether or not they have additional dimensions.
The data source returns up to 100 metrics matching your filter criteria.
-You can also augment queries by using [template variables]({{< relref "./template-variables" >}}).
+You can also augment queries by using [template variables](../template-variables/).
#### Create dynamic queries with dimension wildcards
@@ -157,7 +157,7 @@ For details about the Metrics Insights syntax, refer to the [AWS reference docum
For information about Metrics Insights limits, refer to the [AWS feature documentation](https://docs.aws.amazon.com/console/cloudwatch/metricsinsights).
-You can also augment queries by using [template variables]({{< relref "./template-variables" >}}).
+You can also augment queries by using [template variables](../template-variables/).
#### Use Metrics Insights keywords
@@ -226,7 +226,7 @@ The label field allows you to override the default name of the metric legend usi
## Query CloudWatch Logs
The logs query editor helps you write CloudWatch Logs Query Language queries across defined regions and log groups.
-It supports querying Cloudwatch logs with Logs Insights Query Language, OpenSearch PPL and OpenSearch SQL.
+It supports querying CloudWatch logs with Logs Insights Query Language, OpenSearch PPL and OpenSearch SQL.
### Create a CloudWatch Logs query
@@ -237,7 +237,7 @@ It supports querying Cloudwatch logs with Logs Insights Query Language, OpenSear
Region and log groups are mandatory fields when querying with Logs Insights QL and OpenSearch PPL. Log group selection is not necessary when querying with OpenSearch SQL. However, selecting log groups simplifies writing logs queries by populating syntax suggestions with discovered log group fields.
{{< /admonition >}}
-1. Use the main input area to write your logs query. AWS Cloudwatch only supports a subset of OpenSearch SQL and PPL commands. To find out more about the syntax supported, consult [Amazon CloudWatch Logs documentation](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/CWL_AnalyzeLogData_Languages.html)
+1. Use the main input area to write your logs query. AWS CloudWatch only supports a subset of OpenSearch SQL and PPL commands. To find out more about the syntax supported, consult [Amazon CloudWatch Logs documentation](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/CWL_AnalyzeLogData_Languages.html)
#### Querying Log groups with OpenSearch SQL
@@ -270,7 +270,7 @@ To enable cross-account observability, complete the following steps:
1. Go to the [Amazon CloudWatch docs](http://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch-Unified-Cross-Account.html) and follow the instructions on enabling cross-account observability.
-1. Add [two API actions]({{< relref "../../aws-cloudwatch#cross-account-observability-permissions" >}}) to the IAM policy attached to the role/user running the plugin.
+1. Add [two API actions](../#cross-account-observability-permissions) to the IAM policy attached to the role/user running the plugin.
Cross-account querying is available in the plugin through the **Logs**, **Metric search**, and **Metric Insights** modes.
After you have it configured, you'll see a **Monitoring account** badge in the query editor header.
diff --git a/docs/sources/datasources/azure-monitor/_index.md b/docs/sources/datasources/azure-monitor/_index.md
index cdc50ba8993..7814af16326 100644
--- a/docs/sources/datasources/azure-monitor/_index.md
+++ b/docs/sources/datasources/azure-monitor/_index.md
@@ -74,7 +74,7 @@ This topic explains configuring and querying specific to the Azure Monitor data
For instructions on how to add a data source to Grafana, refer to the [administration documentation](ref:data-source-management).
Only users with the organization administrator role can add data sources.
-Once you've added the Azure Monitor data source, you can [configure it](#configure-the-data-source) so that your Grafana instance's users can create queries in its [query editor]({{< relref "./query-editor" >}}) when they [build dashboards](ref:build-dashboards) and use [Explore](ref:explore).
+Once you've added the Azure Monitor data source, you can [configure it](#configure-the-data-source) so that your Grafana instance's users can create queries in its [query editor](query-editor/) when they [build dashboards](ref:build-dashboards) and use [Explore](ref:explore).
The Azure Monitor data source supports visualizing data from four Azure services:
@@ -338,7 +338,7 @@ If a user tries to create an alert for a resource that the fallback credentials
The Azure Monitor data source can query data from Azure Monitor Metrics and Logs, the Azure Resource Graph, and Application Insights Traces. Each source has its own specialized query editor.
-For details, see the [query editor documentation]({{< relref "./query-editor" >}}).
+For details, see the [query editor documentation](query-editor/).
## Use template variables
@@ -346,7 +346,7 @@ Instead of hard-coding details such as server, application, and sensor names in
Grafana lists these variables in dropdown select boxes at the top of the dashboard to help you change the data displayed in your dashboard.
Grafana refers to such variables as template variables.
-For details, see the [template variables documentation]({{< relref "./template-variables" >}}).
+For details, see the [template variables documentation](template-variables/).
## Application Insights and Insights Analytics (removed)
diff --git a/docs/sources/datasources/azure-monitor/query-editor/index.md b/docs/sources/datasources/azure-monitor/query-editor/index.md
index 28256b66000..662685ce7db 100644
--- a/docs/sources/datasources/azure-monitor/query-editor/index.md
+++ b/docs/sources/datasources/azure-monitor/query-editor/index.md
@@ -85,7 +85,7 @@ Optionally, you can apply further aggregations or filter by dimensions.
The available options change depending on what is relevant to the selected metric.
-You can also augment queries by using [template variables]({{< relref "./template-variables" >}}).
+You can also augment queries by using [template variables](../template-variables/).
### Format legend aliases
@@ -146,7 +146,7 @@ The Azure Monitor data source also supports querying of [Basic Logs](https://lea
1. Enter your KQL query.
-You can also augment queries by using [template variables]({{< relref "./template-variables" >}}).
+You can also augment queries by using [template variables](../template-variables/).
**To create a Basic Logs query:**
@@ -364,7 +364,7 @@ Selecting the trace format will filter events with the `trace` type.
1. Specify event types to filter by.
1. Specify event properties to filter by.
-You can also augment queries by using [template variables]({{< relref "./template-variables" >}}).
+You can also augment queries by using [template variables](../template-variables/).
## Working with large Azure resource data sets
diff --git a/docs/sources/datasources/azure-monitor/template-variables/index.md b/docs/sources/datasources/azure-monitor/template-variables/index.md
index 5eb2d9f983c..1db472a4251 100644
--- a/docs/sources/datasources/azure-monitor/template-variables/index.md
+++ b/docs/sources/datasources/azure-monitor/template-variables/index.md
@@ -48,19 +48,24 @@ For an introduction to templating and template variables, refer to the [Templati
You can specify these Azure Monitor data source queries in the Variable edit view's **Query Type** field.
-| Name | Description |
-| ------------------- | ------------------------------------------------------------------------------------------------------------------ |
-| **Subscriptions** | Returns subscriptions. |
-| **Resource Groups** | Returns resource groups for a specified. Supports multi-value. subscription. |
-| **Namespaces** | Returns metric namespaces for the specified subscription and resource group. |
-| **Regions** | Returns regions for the specified subscription |
-| **Resource Names** | Returns a list of resource names for a specified subscription, resource group and namespace. Supports multi-value. |
-| **Metric Names** | Returns a list of metric names for a resource. |
-| **Workspaces** | Returns a list of workspaces for the specified subscription. |
-| **Logs** | Use a KQL query to return values. |
-| **Resource Graph** | Use an ARG query to return values. |
+| Name | Description |
+| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
+| **Subscriptions** | Returns subscriptions. |
+| **Resource Groups** | Returns resource groups for a specified subscription. Supports multi-value. |
+| **Namespaces** | Returns metric namespaces for the specified subscription. If a resource group is provided, only the namespaces within that group are returned. |
+| **Regions** | Returns regions for the specified subscription |
+| **Resource Names** | Returns a list of resource names for a specified subscription, resource group and namespace. Supports multi-value. |
+| **Metric Names** | Returns a list of metric names for a resource. |
+| **Workspaces** | Returns a list of workspaces for the specified subscription. |
+| **Logs** | Use a KQL query to return values. |
+| **Custom Namespaces** | Returns metric namespaces for the specified resource. |
+| **Custom Metric Names** | Returns a list of custom metric names for the specified resource. |
-Any Log Analytics Kusto Query Language (KQL) query that returns a single list of values can also be used in the Query field.
+{{< admonition type="note" >}}
+Custom metrics cannot be emitted against a subscription or resource group. Select resources only when you need to retrieve custom metric namespaces or custom metric names associated with a specific resource.
+{{< /admonition >}}
+
+You can use any Log Analytics Kusto Query Language (KQL) query that returns a single list of values in the `Query` field.
For example:
| Query | List of values returned |
diff --git a/docs/sources/datasources/elasticsearch/_index.md b/docs/sources/datasources/elasticsearch/_index.md
index 69dcf9bf69a..e0bfbe560e7 100644
--- a/docs/sources/datasources/elasticsearch/_index.md
+++ b/docs/sources/datasources/elasticsearch/_index.md
@@ -48,8 +48,8 @@ The following will help you get started working with Elasticsearch and Grafana:
- [What is Elasticsearch?](https://www.elastic.co/guide/en/elasticsearch/reference/current/elasticsearch-intro.html)
- [Configure the Elasticsearch data source](/docs/grafana/latest/datasources/elasticsearch/configure-elasticsearch-data-source/)
-- [Elasticsearch query editor]({{< relref "./query-editor" >}})
-- [Elasticsearch template variables]({{< relref "./template-variables" >}})
+- [Elasticsearch query editor](query-editor/)
+- [Elasticsearch template variables](template-variables/)
## Supported Elasticsearch versions
@@ -124,7 +124,7 @@ For details on AWS SigV4, refer to the [AWS documentation](https://docs.aws.amaz
To sign requests to your Amazon Elasticsearch Service domain, you can enable SigV4 in Grafana's [configuration](ref:configuration).
Once AWS SigV4 is enabled, you can configure it on the Elasticsearch data source configuration page.
-For more information about AWS authentication options, refer to [AWS authentication]({{< relref "../aws-cloudwatch/aws-authentication" >}}).
+For more information about AWS authentication options, refer to [AWS authentication](../aws-cloudwatch/aws-authentication/).
{{< figure src="/static/img/docs/v73/elasticsearch-sigv4-config-editor.png" max-width="500px" class="docs-image--no-shadow" caption="SigV4 configuration for AWS Elasticsearch Service" >}}
@@ -132,7 +132,7 @@ For more information about AWS authentication options, refer to [AWS authenticat
You can select multiple metrics and group by multiple terms or filters when using the Elasticsearch query editor.
-For details, see the [query editor documentation]({{< relref "./query-editor" >}}).
+For details, see the [query editor documentation](query-editor/).
## Use template variables
@@ -140,4 +140,4 @@ Instead of hard-coding details such as server, application, and sensor names in
Grafana lists these variables in dropdown select boxes at the top of the dashboard to help you change the data displayed in your dashboard.
Grafana refers to such variables as template variables.
-For details, see the [template variables documentation]({{< relref "./template-variables" >}}).
+For details, see the [template variables documentation](template-variables/).
diff --git a/docs/sources/datasources/elasticsearch/configure-elasticsearch-data-source.md b/docs/sources/datasources/elasticsearch/configure-elasticsearch-data-source.md
index 9741f03d072..eacc91861df 100644
--- a/docs/sources/datasources/elasticsearch/configure-elasticsearch-data-source.md
+++ b/docs/sources/datasources/elasticsearch/configure-elasticsearch-data-source.md
@@ -160,7 +160,7 @@ For example, set this to `1m` if Elasticsearch writes data every minute.
You can also override this setting in a dashboard panel under its data source options. The default is `10s`.
-- **X-Pack enabled** - Toggle to enable `X-Pack`-specific features and options, which provide the [query editor]({{< relref "./query-editor" >}}) with additional aggregations, such as `Rate` and `Top Metrics`.
+- **X-Pack enabled** - Toggle to enable `X-Pack`-specific features and options, which provide the [query editor](../query-editor/) with additional aggregations, such as `Rate` and `Top Metrics`.
- **Include frozen indices** - Toggle on when the `X-Pack enabled` setting is active. Includes frozen indices in searches. You can configure Grafana to include [frozen indices](https://www.elastic.co/guide/en/elasticsearch/reference/7.13/frozen-indices.html) when performing search requests.
diff --git a/docs/sources/datasources/elasticsearch/query-editor/index.md b/docs/sources/datasources/elasticsearch/query-editor/index.md
index e6ed22b542f..0e7b37d4708 100644
--- a/docs/sources/datasources/elasticsearch/query-editor/index.md
+++ b/docs/sources/datasources/elasticsearch/query-editor/index.md
@@ -143,7 +143,7 @@ The option to run a **raw document query** is deprecated as of Grafana v10.1.
## Use template variables
-You can also augment queries by using [template variables]({{< relref "./template-variables/" >}}).
+You can also augment queries by using [template variables](../template-variables/).
Queries of `terms` have a 500-result limit by default.
To set a custom limit, set the `size` property in your query.
diff --git a/docs/sources/datasources/google-cloud-monitoring/_index.md b/docs/sources/datasources/google-cloud-monitoring/_index.md
index efa07545e60..94dfe06d7a3 100644
--- a/docs/sources/datasources/google-cloud-monitoring/_index.md
+++ b/docs/sources/datasources/google-cloud-monitoring/_index.md
@@ -53,7 +53,7 @@ This topic describes queries, templates, variables, and other configuration spec
For instructions on how to add a data source to Grafana, refer to the [administration documentation](ref:data-source-management).
Only users with the organization administrator role can add data sources.
-Once you've added the Google Cloud Monitoring data source, you can [configure it](#configure-the-data-source) so that your Grafana instance's users can create queries in its [query editor]({{< relref "./query-editor" >}}) and apply [annotations](#annotations) when they [build dashboards](ref:build-dashboards) and use [Explore](ref:explore).
+Once you've added the Google Cloud Monitoring data source, you can [configure it](#configure-the-data-source) so that your Grafana instance's users can create queries in its [query editor](query-editor/) and apply [annotations](#annotations) when they [build dashboards](ref:build-dashboards) and use [Explore](ref:explore).
## Configure the data source
@@ -78,19 +78,19 @@ To configure basic settings for the data source, complete the following steps:
Before you can request data from Google Cloud Monitoring, you must configure authentication.
All requests to Google APIs are performed on the server-side by the Grafana backend.
-For authentication options and configuration details, refer to [Google authentication]({{< relref "./google-authentication" >}}).
+For authentication options and configuration details, refer to [Google authentication](google-authentication/).
When configuring Google authentication, note these additional Google Cloud Monitoring-specific steps:
#### Configure a GCP Service Account
-When you [create a Google Cloud Platform (GCP) Service Account and key file]({{< relref "./google-authentication#create-a-gcp-service-account-and-key-file" >}}), the Service Account must have the **Monitoring Viewer** role (**Role > Select a role > Monitoring > Monitoring Viewer**):
+When you [create a Google Cloud Platform (GCP) Service Account and key file](google-authentication/#create-a-gcp-service-account-and-key-file), the Service Account must have the **Monitoring Viewer** role (**Role > Select a role > Monitoring > Monitoring Viewer**):
{{< figure src="/static/img/docs/v71/cloudmonitoring_service_account_choose_role.png" max-width="600px" class="docs-image--no-shadow" caption="Choose role" >}}
#### Grant the GCE Default Service Account scope
-If Grafana is running on a Google Compute Engine (GCE) virtual machine, then when you [Configure a GCE Default Service Account]({{< relref "./google-authentication#configure-a-gce-default-service-account" >}}), you must also grant that Service Account access to the "Cloud Monitoring API" scope.
+If Grafana is running on a Google Compute Engine (GCE) virtual machine, then when you [Configure a GCE Default Service Account](google-authentication/#configure-a-gce-default-service-account), you must also grant that Service Account access to the "Cloud Monitoring API" scope.
### Enable necessary Google Cloud Platform APIs
@@ -181,7 +181,7 @@ These curated dashboards are based on similar dashboards in the GCP dashboard sa
1. Select **Import** for the dashboard to import.
-The dashboards include a [template variable]({{< relref "./template-variables" >}}) populated with the projects accessible by the configured [Service Account]({{< relref "./google-authentication" >}}) each time you load the dashboard.
+The dashboards include a [template variable](template-variables/) populated with the projects accessible by the configured [Service Account](google-authentication/) each time you load the dashboard.
After Grafana loads the dashboard, you can select a project from the dropdown list.
**To customize an imported dashboard:**
@@ -193,7 +193,7 @@ If you don't, upgrading Grafana can overwrite the customized dashboard with the
The Google Cloud Monitoring query editor helps you build two types of queries: **Metric** and **Service Level Objective (SLO)**.
-For details, refer to the [query editor documentation]({{< relref "./query-editor" >}}).
+For details, refer to the [query editor documentation](query-editor/).
## Use template variables
@@ -201,4 +201,4 @@ Instead of hard-coding details such as server, application, and sensor names in
Grafana lists these variables in dropdown select boxes at the top of the dashboard to help you change the data displayed in your dashboard.
Grafana refers to such variables as template variables.
-For details, see the [template variables documentation]({{< relref "./template-variables" >}}).
+For details, see the [template variables documentation](template-variables/).
diff --git a/docs/sources/datasources/graphite/_index.md b/docs/sources/datasources/graphite/_index.md
index 7628935ae02..993f40b127d 100644
--- a/docs/sources/datasources/graphite/_index.md
+++ b/docs/sources/datasources/graphite/_index.md
@@ -56,7 +56,7 @@ This topic explains options, variables, querying, and other features specific to
For instructions on how to add a data source to Grafana, refer to the [administration documentation](ref:data-source-management).
Only users with the organization administrator role can add data sources.
-Once you've added the Graphite data source, you can [configure it](#configure-the-data-source) so that your Grafana instance's users can create queries in its [query editor]({{< relref "./query-editor" >}}) when they [build dashboards](ref:build-dashboards) and use [Explore](ref:explore).
+Once you've added the Graphite data source, you can [configure it](#configure-the-data-source) so that your Grafana instance's users can create queries in its [query editor](query-editor/) when they [build dashboards](ref:build-dashboards) and use [Explore](ref:explore).
{{< docs/play title="Graphite: Sample Website Dashboard" url="https://play.grafana.org/d/000000003/" >}}
@@ -124,7 +124,7 @@ Grafana includes a Graphite-specific query editor to help you build queries.
The query editor helps you quickly navigate the metric space, add functions, and change function parameters.
It can handle all types of Graphite queries, including complex nested queries through the use of query references.
-For details, refer to the [query editor documentation]({{< relref "./query-editor" >}}).
+For details, refer to the [query editor documentation](query-editor/).
## Use template variables
@@ -132,7 +132,7 @@ Instead of hard-coding details such as server, application, and sensor names in
Grafana lists these variables in dropdown select boxes at the top of the dashboard to help you change the data displayed in your dashboard.
Grafana refers to such variables as template variables.
-For details, see the [template variables documentation]({{< relref "./template-variables" >}}).
+For details, see the [template variables documentation](template-variables/).
## Get Grafana metrics into Graphite
diff --git a/docs/sources/datasources/jaeger/_index.md b/docs/sources/datasources/jaeger/_index.md
index 444635b638c..1aa5f777e23 100644
--- a/docs/sources/datasources/jaeger/_index.md
+++ b/docs/sources/datasources/jaeger/_index.md
@@ -375,7 +375,7 @@ To only show the spans you have matched, you can press the `Show matches only` t
You can link to Jaeger traces from logs in Loki, Elasticsearch, Splunk, and other logs data sources by configuring an internal link.
-To configure this feature, see the [Derived fields]({{< relref "../loki#configure-derived-fields" >}}) section of the Loki data source docs or the [Data links]({{< relref "../elasticsearch#data-links" >}}) section of the Elasticsearch or Splunk data source docs.
+To configure this feature, see the [Derived fields](../loki/#configure-derived-fields) section of the Loki data source docs or the [Data links](../elasticsearch/#data-links) section of the Elasticsearch or Splunk data source docs.
## Link to a trace ID from metrics
diff --git a/docs/sources/datasources/loki/_index.md b/docs/sources/datasources/loki/_index.md
index 1dc0024779d..38225509de1 100644
--- a/docs/sources/datasources/loki/_index.md
+++ b/docs/sources/datasources/loki/_index.md
@@ -56,7 +56,7 @@ The following guides will help you get started with Loki:
- [Loki best practices](/docs/loki/latest/best-practices/#best-practices)
- [Configure the Loki data source](/docs/grafana/latest/datasources/loki/configure-loki-data-source/)
- [LogQL](/docs/loki/latest/logql/)
-- [Loki query editor]({{< relref "./query-editor" >}})
+- [Loki query editor](query-editor/)
## Supported Loki versions
@@ -70,7 +70,7 @@ For instructions on how to add a data source to Grafana, refer to the [administr
Only users with the organization administrator role can add data sources.
Administrators can also [configure the data source via YAML](#provision-the-data-source) with Grafana's provisioning system.
-Once you've added the Loki data source, you can [configure it](#configure-the-data-source) so that your Grafana instance's users can create queries in its [query editor]({{< relref "./query-editor" >}}) when they [build dashboards](ref:build-dashboards), use [Explore](ref:explore), and [annotate visualizations]({{< relref "./query-editor#apply-annotations" >}}).
+Once you've added the Loki data source, you can [configure it](#configure-the-data-source) so that your Grafana instance's users can create queries in its [query editor](query-editor/) when they [build dashboards](ref:build-dashboards), use [Explore](ref:explore), and [annotate visualizations](query-editor/#apply-annotations).
{{% admonition type="note" %}}
To troubleshoot configuration and other issues, check the log file located at `/var/log/grafana/grafana.log` on Unix systems, or in `/data/log` on other platforms and manual installations.
@@ -149,7 +149,7 @@ datasources:
The Loki data source's query editor helps you create log and metric queries that use Loki's query language, [LogQL](/docs/loki/latest/logql/).
-For details, refer to the [query editor documentation]({{< relref "./query-editor" >}}).
+For details, refer to the [query editor documentation](query-editor/).
## Use template variables
@@ -157,4 +157,4 @@ Instead of hard-coding details such as server, application, and sensor names in
Grafana lists these variables in dropdown select boxes at the top of the dashboard to help you change the data displayed in your dashboard.
Grafana refers to such variables as template variables.
-For details, see the [template variables documentation]({{< relref "./template-variables" >}}).
+For details, see the [template variables documentation](template-variables/).
diff --git a/docs/sources/datasources/loki/query-editor/index.md b/docs/sources/datasources/loki/query-editor/index.md
index 4d638eb57db..ef3f8a55fe2 100644
--- a/docs/sources/datasources/loki/query-editor/index.md
+++ b/docs/sources/datasources/loki/query-editor/index.md
@@ -63,7 +63,7 @@ Each mode is synchronized, so you can switch between them without losing your wo
When you switch from Code mode to Builder mode with such a query, the editor displays a warning message that explains how you might lose parts of the query if you continue.
You can then decide whether you still want to switch to Builder mode.
-You can also augment queries by using [template variables]({{< relref "./template-variables" >}}).
+You can also augment queries by using [template variables](../template-variables/).
## Toolbar elements
@@ -173,9 +173,7 @@ The following options are the same for both **Builder** and **Code** mode:
- **Direction** - Determines the search order. **Backward** is a backward search starting at the end of the time range. **Forward** is a forward search starting at the beginning of the time range. The default is **Backward**
-- **Step** Sets the step parameter of Loki metrics queries. The default value equals to the value of `$__interval` variable, which is calculated using the time range and the width of the graph (the number of pixels).
-
-- **Resolution** Deprecated. Sets the step parameter of Loki metrics range queries. With a resolution of `1/1`, each pixel corresponds to one data point. `1/2` retrieves one data point for every other pixel, `1/10` retrieves one data point per 10 pixels, and so on. Lower resolutions perform better.
+- **Step** Sets the step parameter of Loki metrics queries. The default value equals to the value of `$__auto` variable, which is calculated using the time range and the width of the graph (the number of pixels).
## Create a log query
@@ -263,6 +261,6 @@ For more information about metric queries, refer to the [Loki metric queries doc
[Annotations](ref:annotate-visualizations) overlay rich event information on top of graphs.
You can add annotation queries in the Dashboard menu's Annotations view.
-You can use any non-metric Loki query as a source for annotations.
+You can only use log queries as a source for annotations.
Grafana automatically uses log content as annotation text and your log stream labels as tags.
You don't need to create any additional mapping.
diff --git a/docs/sources/datasources/mssql/_index.md b/docs/sources/datasources/mssql/_index.md
index cdc2a64812f..9909696daee 100644
--- a/docs/sources/datasources/mssql/_index.md
+++ b/docs/sources/datasources/mssql/_index.md
@@ -62,7 +62,7 @@ For instructions on how to add a data source to Grafana, refer to the [administr
Only users with the organization administrator role can add data sources.
Administrators can also [configure the data source via YAML](#provision-the-data-source) with Grafana's provisioning system.
-Once you've added the Microsoft SQL Server data source, you can [configure it](#configure-the-data-source) so that your Grafana instance's users can create queries in its [query editor]({{< relref "./query-editor" >}}) when they [build dashboards](ref:build-dashboards) and use [Explore](ref:explore).
+Once you've added the Microsoft SQL Server data source, you can [configure it](#configure-the-data-source) so that your Grafana instance's users can create queries in its [query editor](query-editor/) when they [build dashboards](ref:build-dashboards) and use [Explore](ref:explore).
## Configure the data source
@@ -185,7 +185,7 @@ datasources:
You can create queries with the Microsoft SQL Server data source's query editor when editing a panel that uses a MS SQL data source.
-For details, refer to the [query editor documentation]({{< relref "./query-editor" >}}).
+For details, refer to the [query editor documentation](query-editor/).
## Use template variables
@@ -193,4 +193,4 @@ Instead of hard-coding details such as server, application, and sensor names in
Grafana lists these variables in dropdown select boxes at the top of the dashboard to help you change the data displayed in your dashboard.
Grafana refers to such variables as template variables.
-For details, see the [template variables documentation]({{< relref "./template-variables" >}}).
+For details, see the [template variables documentation](template-variables/).
diff --git a/docs/sources/datasources/opentsdb/_index.md b/docs/sources/datasources/opentsdb/_index.md
index 560ba731bb5..07a5a66add0 100644
--- a/docs/sources/datasources/opentsdb/_index.md
+++ b/docs/sources/datasources/opentsdb/_index.md
@@ -62,7 +62,7 @@ To configure basic settings for the data source, complete the following steps:
| **Default** | Default data source that will be be pre-selected for new panels. |
| **URL** | The HTTP protocol, IP, and port of your OpenTSDB server (default port is usually 4242). |
| **Allowed cookies** | Listing of cookies to forward to the data source. |
-| **Version** | The OpenTSDB version. |
+| **Version** | The OpenTSDB version (supported versions are: 2.4, 2.3, 2.2 and versions less than 2.1). |
| **Resolution** | Metrics from OpenTSDB may have data points with either second or millisecond resolution. |
| **Lookup limit** | Default is 1000. |
@@ -98,9 +98,13 @@ can be used to query OpenTSDB. Fill Policy is also introduced in OpenTSDB 2.2.
While using OpenTSDB 2.2 data source, make sure you use either Filters or Tags as they are mutually exclusive. If used together, might give you weird results.
{{% /admonition %}}
+{{% admonition type="note" %}}
+When using OpenTSDB 2.4 with alerting, queries are executed with the parameter `arrays=true`. This causes OpenTSDB to return data points as an array of arrays instead of a map of key-value pairs. Grafana then converts this data into the appropriate data frame format.
+{{% /admonition %}}
+
### Auto complete suggestions
-As soon as you start typing metric names, tag names and tag values , you should see highlighted auto complete suggestions for them.
+As you begin typing metric names, tag names, or tag values, highlighted autocomplete suggestions will appear.
The autocomplete only works if the OpenTSDB suggest API is enabled.
## Templating queries
diff --git a/docs/sources/datasources/postgres/_index.md b/docs/sources/datasources/postgres/_index.md
index 3489b760f70..868a2bb7d9e 100644
--- a/docs/sources/datasources/postgres/_index.md
+++ b/docs/sources/datasources/postgres/_index.md
@@ -2,7 +2,7 @@
aliases:
- ../data-sources/postgres/
- ../features/datasources/postgres/
-description: Guide for using PostgreSQL in Grafana
+description: Introduction to the PostgreSQL data source in Grafana.
keywords:
- grafana
- postgresql
@@ -16,506 +16,58 @@ menuTitle: PostgreSQL
title: PostgreSQL data source
weight: 1200
refs:
- provisioning-data-sources:
- - pattern: /docs/grafana/
- destination: /docs/grafana//administration/provisioning/#datasources
- - pattern: /docs/grafana-cloud/
- destination: /docs/grafana//administration/provisioning/#datasources
- variables:
- - pattern: /docs/grafana/
- destination: /docs/grafana//dashboards/variables/
- - pattern: /docs/grafana-cloud/
- destination: /docs/grafana//dashboards/variables/
- add-template-variables-interval-ms:
- - pattern: /docs/grafana/
- destination: /docs/grafana//dashboards/variables/add-template-variables/#__interval_ms
- - pattern: /docs/grafana-cloud/
- destination: /docs/grafana//dashboards/variables/add-template-variables/#__interval_ms
- add-template-variables-interval:
- - pattern: /docs/grafana/
- destination: /docs/grafana//dashboards/variables/add-template-variables/#__interval
- - pattern: /docs/grafana-cloud/
- destination: /docs/grafana//dashboards/variables/add-template-variables/#__interval
annotate-visualizations:
- pattern: /docs/grafana/
destination: /docs/grafana//dashboards/build-dashboards/annotate-visualizations/
- pattern: /docs/grafana-cloud/
destination: /docs/grafana//dashboards/build-dashboards/annotate-visualizations/
- configure-standard-options-display-name:
+ configure-postgres-data-source:
- pattern: /docs/grafana/
- destination: /docs/grafana//panels-visualizations/configure-standard-options/#display-name
+ destination: /docs/grafana//datasources/postgres/configure/
- pattern: /docs/grafana-cloud/
- destination: /docs/grafana//panels-visualizations/configure-standard-options/#display-name
- data-source-management:
+ destination: /docs/grafana//datasources/postgres/configure/
+ postgres-query-editor:
- pattern: /docs/grafana/
- destination: /docs/grafana//administration/data-source-management/
+ destination: /docs/grafana//datasources/postgres/query-editor/
- pattern: /docs/grafana-cloud/
- destination: /docs/grafana//administration/data-source-management/
- variable-syntax-advanced-variable-format-options:
+ destination: /docs/grafana//datasources/postgres/query-editor/
+ alerting:
- pattern: /docs/grafana/
- destination: /docs/grafana//dashboards/variables/variable-syntax/#advanced-variable-format-options
+ destination: /docs/grafana//alerting/
- pattern: /docs/grafana-cloud/
- destination: /docs/grafana//dashboards/variables/variable-syntax/#advanced-variable-format-options
+ destination: /docs/grafana-cloud/alerting-and-irm/alerting/
+ transformations:
+ - pattern: /docs/grafana/
+ destination: /docs/grafana//panels-visualizations/query-transform-data/transform-data/
+ - pattern: /docs/grafana-cloud/
+ destination: /docs/grafana-cloud/visualizations/panels-visualizations/query-transform-data/transform-data/
+ visualizations:
+ - pattern: /docs/grafana/
+ destination: /docs/grafana//panels-visualizations/visualizations/
+ - pattern: /docs/grafana-cloud/
+ destination: /docs/grafana-cloud/visualizations/panels-visualizations/visualizations/
---
# PostgreSQL data source
-Grafana ships with a built-in PostgreSQL data source plugin that allows you to query and visualize data from a PostgreSQL compatible database.
+Grafana includes a built-in PostgreSQL data source plugin, enabling you to query and visualize data from any PostgreSQL-compatible database. You don't need to install a plugin to add the PostgreSQL data source to your Grafana instance.
-For instructions on how to add a data source to Grafana, refer to the [administration documentation](ref:data-source-management).
-Only users with the organization administrator role can add data sources.
-Administrators can also [configure the data source via YAML](#provision-the-data-source) with Grafana's provisioning system.
+Grafana offers several configuration options for this data source as well as a visual and code-based query editor.
+
+## Get started with the PostgreSQL data source
+
+The following documents will help you get started with the PostgreSQL data source in Grafana:
+
+- [Configure the PostgreSQL data source](ref:configure-postgres-data-source)
+- [PostgreSQL query editor](ref:postgres-query-editor)
+
+After you have configured the data source you can:
+
+- Create a variety of [visualizations](ref:visualizations)
+- Add [annotations](ref:annotate-visualizations)
+- Set up [alerting](ref:alerting)
+- Add [transformations](ref:transformations)
+
+View a PostgreSQL overview on Grafana Play:
{{< docs/play title="PostgreSQL Overview" url="https://play.grafana.org/d/ddvpgdhiwjvuod/postgresql-overview" >}}
-
-## PostgreSQL settings
-
-To configure basic settings for the data source, complete the following steps:
-
-1. Click **Connections** in the left-side menu.
-1. Under Your connections, click **Data sources**.
-1. Enter `PostgreSQL` in the search bar.
-1. Select **PostgreSQL**.
-
- The **Settings** tab of the data source is displayed.
-
-1. Set the data source's basic configuration options:
-
-| Name | Description |
-| --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| **Name** | The data source name. This is how you refer to the data source in panels and queries. |
-| **Default** | Default data source means that it will be pre-selected for new panels. |
-| **Host** | The IP address/hostname and optional port of your PostgreSQL instance. _Do not_ include the database name. The connection string for connecting to Postgres will not be correct and it may cause errors. |
-| **Database** | Name of your PostgreSQL database. |
-| **User** | Database user's login/username |
-| **Password** | Database user's password |
-| **SSL Mode** | Determines whether or with what priority a secure SSL TCP/IP connection will be negotiated with the server. When SSL Mode is disabled, SSL Method and Auth Details would not be visible. |
-| **SSL Auth Details Method** | Determines whether the SSL Auth details will be configured as a file path or file content. |
-| **SSL Auth Details Value** | File path or file content of SSL root certificate, client certificate and client key |
-| **Max open** | The maximum number of open connections to the database, default `100`. |
-| **Max idle** | The maximum number of connections in the idle connection pool, default `100`. |
-| **Auto (max idle)** | If set will set the maximum number of idle connections to the number of maximum open connections. Default is `true`. |
-| **Max lifetime** | The maximum amount of time in seconds a connection may be reused, default `14400`/4 hours. |
-| **Version** | Determines which functions are available in the query builder. |
-| **TimescaleDB** | A time-series database built as a PostgreSQL extension. When enabled, Grafana uses `time_bucket` in the `$__timeGroup` macro to display TimescaleDB specific aggregate functions in the query builder. For more information, see [TimescaleDB documentation](https://docs.timescale.com/timescaledb/latest/tutorials/grafana/grafana-timescalecloud/#connect-timescaledb-and-grafana). |
-
-### Min time interval
-
-A lower limit for the [`$__interval`](ref:add-template-variables-interval) and [`$__interval_ms`](ref:add-template-variables-interval-ms) variables.
-Recommended to be set to write frequency, for example `1m` if your data is written every minute.
-This option can also be overridden/configured in a dashboard panel under data source options. It's important to note that this value **needs** to be formatted as a
-number followed by a valid time identifier, e.g. `1m` (1 minute) or `30s` (30 seconds). The following time identifiers are supported:
-
-| Identifier | Description |
-| ---------- | ----------- |
-| `y` | year |
-| `M` | month |
-| `w` | week |
-| `d` | day |
-| `h` | hour |
-| `m` | minute |
-| `s` | second |
-| `ms` | millisecond |
-
-### Database user permissions (Important!)
-
-The database user you specify when you add the data source should only be granted SELECT permissions on
-the specified database and tables you want to query. Grafana does not validate that the query is safe. The query
-could include any SQL statement. For example, statements like `DELETE FROM user;` and `DROP TABLE user;` would be
-executed. To protect against this we **highly** recommend you create a specific PostgreSQL user with restricted permissions.
-
-Example:
-
-```sql
- CREATE USER grafanareader WITH PASSWORD 'password';
- GRANT USAGE ON SCHEMA schema TO grafanareader;
- GRANT SELECT ON schema.table TO grafanareader;
-```
-
-Make sure the user does not get any unwanted privileges from the public role.
-
-## Query builder
-
-{{< figure src="/static/img/docs/screenshot-postgres-query-editor.png" class="docs-image--no-shadow" caption="PostgreSQL query builder" >}}
-
-The PostgreSQL query builder is available when editing a panel using a PostgreSQL data source. The built query can be run by pressing the `Run query` button in the top right corner of the editor.
-
-### Format
-
-The response from PostgreSQL can be formatted as either a table or as a time series. To use the time series format one of the columns must be named `time`.
-
-### Dataset and table selection
-
-The dataset dropdown will be populated with the configured database to which the user has access.
-The table dropdown is populated with the tables that are available within that database.
-
-### Columns and Aggregation functions (SELECT)
-
-Using the dropdown, select a column to include in the data. You can also specify an optional aggregation function.
-
-Add further value columns by clicking the plus button and another column dropdown appears.
-
-{{< docs/shared source="grafana" lookup="datasources/sql-query-builder-macros.md" version="" >}}
-
-### Filter data (WHERE)
-
-To add a filter, toggle the **Filter** switch at the top of the editor.
-This reveals a **Filter by column value** section with two dropdown selectors.
-
-Use the first dropdown to choose whether all of the filters need to match (`AND`), or if only one of the filters needs to match (`OR`).
-Use the second dropdown to choose a filter.
-
-To filter on more columns, click the plus (`+`) button to the right of the condition dropdown.
-
-To remove a filter, click the `x` button next to that filter's dropdown.
-
-After selecting a date type column, you can choose Macros from the operators list and select timeFilter which will add the $\_\_timeFilter macro to the query with the selected date column.
-
-### Group By
-
-To group the results by column, flip the group switch at the top of the editor. You can then choose which column to group the results by. The group by clause can be removed by pressing the X button.
-
-### Preview
-
-By flipping the preview switch at the top of the editor, you can get a preview of the SQL query generated by the query builder.
-
-### Provision the data source
-
-It's now possible to configure data sources using config files with Grafana's provisioning system. You can read more about how it works and all the settings you can set for data sources on the [provisioning docs page](ref:provisioning-data-sources).
-
-#### Provisioning example
-
-```yaml
-apiVersion: 1
-
-datasources:
- - name: Postgres
- type: postgres
- url: localhost:5432
- user: grafana
- secureJsonData:
- password: 'Password!'
- jsonData:
- database: grafana
- sslmode: 'disable' # disable/require/verify-ca/verify-full
- maxOpenConns: 100
- maxIdleConns: 100
- maxIdleConnsAuto: true
- connMaxLifetime: 14400
- postgresVersion: 903 # 903=9.3, 904=9.4, 905=9.5, 906=9.6, 1000=10
- timescaledb: false
-```
-
-{{% admonition type="note" %}}
-In the above code, the `postgresVersion` value of `10` refers to version PostgreSQL 10 and above.
-{{% /admonition %}}
-
-#### Troubleshoot provisioning
-
-If you encounter metric request errors or other issues:
-
-- Make sure your data source YAML file parameters exactly match the example. This includes parameter names and use of quotation marks.
-- Make sure the `database` name is not included in the `url`.
-
-## Code editor
-
-{{< figure src="/static/img/docs/v92/sql_code_editor.png" class="docs-image--no-shadow" >}}
-
-To make advanced queries, switch to the code editor by clicking `code` in the top right corner of the editor. The code editor support autocompletion of tables, columns, SQL keywords, standard sql functions, Grafana template variables and Grafana macros. Columns cannot be completed before a table has been specified.
-
-You can expand the code editor by pressing the `chevron` pointing downwards in the lower right corner of the code editor.
-
-`CTRL/CMD + Return` works as a keyboard shortcut to run the query.
-
-## Macros
-
-Macros can be used within a query to simplify syntax and allow for dynamic parts.
-
-| Macro example | Description |
-| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| `$__time(dateColumn)` | Will be replaced by an expression to convert to a UNIX timestamp and rename the column to `time_sec`. For example, _UNIX_TIMESTAMP(dateColumn) as time_sec_ |
-| `$__timeEpoch(dateColumn)` | Will be replaced by an expression to convert to a UNIX timestamp and rename the column to `time_sec`. For example, _UNIX_TIMESTAMP(dateColumn) as time_sec_ |
-| `$__timeFilter(dateColumn)` | Will be replaced by a time range filter using the specified column name. For example, _dateColumn BETWEEN FROM_UNIXTIME(1494410783) AND FROM_UNIXTIME(1494410983)_ |
-| `$__timeFrom()` | Will be replaced by the start of the currently active time selection. For example, _FROM_UNIXTIME(1494410783)_ |
-| `$__timeTo()` | Will be replaced by the end of the currently active time selection. For example, _FROM_UNIXTIME(1494410983)_ |
-| `$__timeGroup(dateColumn,'5m')` | Will be replaced by an expression usable in GROUP BY clause. For example, *cast(cast(UNIX_TIMESTAMP(dateColumn)/(300) as signed)*300 as signed),\* |
-| `$__timeGroup(dateColumn,'5m', 0)` | Same as above but with a fill parameter so missing points in that series will be added by grafana and 0 will be used as value (only works with time series queries). |
-| `$__timeGroup(dateColumn,'5m', NULL)` | Same as above but NULL will be used as value for missing points (only works with time series queries). |
-| `$__timeGroup(dateColumn,'5m', previous)` | Same as above but the previous value in that series will be used as fill value if no value has been seen yet NULL will be used (only works with time series queries). |
-| `$__timeGroupAlias(dateColumn,'5m')` | Will be replaced identical to $\_\_timeGroup but with an added column alias. |
-| `$__unixEpochFilter(dateColumn)` | Will be replaced by a time range filter using the specified column name with times represented as Unix timestamp. For example, _dateColumn > 1494410783 AND dateColumn < 1494497183_ |
-| `$__unixEpochFrom()` | Will be replaced by the start of the currently active time selection as Unix timestamp. For example, _1494410783_ |
-| `$__unixEpochTo()` | Will be replaced by the end of the currently active time selection as Unix timestamp. For example, _1494497183_ |
-| `$__unixEpochNanoFilter(dateColumn)` | Will be replaced by a time range filter using the specified column name with times represented as nanosecond timestamp. For example, _dateColumn > 1494410783152415214 AND dateColumn < 1494497183142514872_ |
-| `$__unixEpochNanoFrom()` | Will be replaced by the start of the currently active time selection as nanosecond timestamp. For example, _1494410783152415214_ |
-| `$__unixEpochNanoTo()` | Will be replaced by the end of the currently active time selection as nanosecond timestamp. For example, _1494497183142514872_ |
-| `$__unixEpochGroup(dateColumn,'5m', [fillmode])` | Same as $\_\_timeGroup but for times stored as Unix timestamp (`fillMode` only works with time series queries). |
-| `$__unixEpochGroupAlias(dateColumn,'5m', [fillmode])` | Same as above but also adds a column alias (`fillMode` only works with time series queries). |
-
-## Table queries
-
-If the `Format as` query option is set to `Table` then you can basically do any type of SQL query. The table panel will automatically show the results of whatever columns and rows your query returns.
-
-Query editor with example query:
-
-
-
-The query:
-
-```sql
-SELECT
- title as "Title",
- "user".login as "Created By",
- dashboard.created as "Created On"
-FROM dashboard
-INNER JOIN "user" on "user".id = dashboard.created_by
-WHERE $__timeFilter(dashboard.created)
-```
-
-You can control the name of the Table panel columns by using regular `as ` SQL column selection syntax.
-
-The resulting table panel:
-
-
-
-## Time series queries
-
-If you set Format as to _Time series_, then the query must have a column named time that returns either a SQL datetime or any numeric datatype representing Unix epoch in seconds. In addition, result sets of time series queries must be sorted by time for panels to properly visualize the result.
-
-A time series query result is returned in a [wide data frame format](https://grafana.com/developers/plugin-tools/key-concepts/data-frames#wide-format). Any column except time or of type string transforms into value fields in the data frame query result. Any string column transforms into field labels in the data frame query result.
-
-> For backward compatibility, there's an exception to the above rule for queries that return three columns including a string column named metric. Instead of transforming the metric column into field labels, it becomes the field name, and then the series name is formatted as the value of the metric column. See the example with the metric column below.
-
-To optionally customize the default series name formatting, refer to [Standard options definitions](ref:configure-standard-options-display-name).
-
-**Example with `metric` column:**
-
-```sql
-SELECT
- $__timeGroupAlias("time_date_time",'5m'),
- min("value_double"),
- 'min' as metric
-FROM test_data
-WHERE $__timeFilter("time_date_time")
-GROUP BY time
-ORDER BY time
-```
-
-Data frame result:
-
-```text
-+---------------------+-----------------+
-| Name: time | Name: min |
-| Labels: | Labels: |
-| Type: []time.Time | Type: []float64 |
-+---------------------+-----------------+
-| 2020-01-02 03:05:00 | 3 |
-| 2020-01-02 03:10:00 | 6 |
-+---------------------+-----------------+
-```
-
-**Example using the fill parameter in the $\_\_timeGroupAlias macro to convert null values to be zero instead:**
-
-```sql
-SELECT
- $__timeGroupAlias("createdAt",'5m',0),
- sum(value) as value,
- hostname
-FROM test_data
-WHERE
- $__timeFilter("createdAt")
-GROUP BY time, hostname
-ORDER BY time
-```
-
-Given the data frame result in the following example and using the graph panel, you will get two series named _value 10.0.1.1_ and _value 10.0.1.2_. To render the series with a name of _10.0.1.1_ and _10.0.1.2_ , use a [Standard options definitions](ref:configure-standard-options-display-name) display value of `${__field.labels.hostname}`.
-
-Data frame result:
-
-```text
-+---------------------+---------------------------+---------------------------+
-| Name: time | Name: value | Name: value |
-| Labels: | Labels: hostname=10.0.1.1 | Labels: hostname=10.0.1.2 |
-| Type: []time.Time | Type: []float64 | Type: []float64 |
-+---------------------+---------------------------+---------------------------+
-| 2020-01-02 03:05:00 | 3 | 4 |
-| 2020-01-02 03:10:00 | 6 | 7 |
-+---------------------+---------------------------+---------------------------+
-```
-
-**Example with multiple columns:**
-
-```sql
-SELECT
- $__timeGroupAlias("time_date_time",'5m'),
- min("value_double") as "min_value",
- max("value_double") as "max_value"
-FROM test_data
-WHERE $__timeFilter("time_date_time")
-GROUP BY time
-ORDER BY time
-```
-
-Data frame result:
-
-```text
-+---------------------+-----------------+-----------------+
-| Name: time | Name: min_value | Name: max_value |
-| Labels: | Labels: | Labels: |
-| Type: []time.Time | Type: []float64 | Type: []float64 |
-+---------------------+-----------------+-----------------+
-| 2020-01-02 03:04:00 | 3 | 4 |
-| 2020-01-02 03:05:00 | 6 | 7 |
-+---------------------+-----------------+-----------------+
-```
-
-## Templating
-
-Instead of hard-coding things like server, application and sensor name in your metric queries you can use variables in their place. Variables are shown as dropdown select boxes at the top of the dashboard. These dropdowns make it easy to change the data being displayed in your dashboard.
-
-Refer to [Templates and variables](ref:variables) for an introduction to the templating feature and the different types of template variables.
-
-### Query variable
-
-If you add a template variable of the type `Query`, you can write a PostgreSQL query that can
-return things like measurement names, key names or key values that are shown as a dropdown select box.
-
-For example, you can have a variable that contains all values for the `hostname` column in a table if you specify a query like this in the templating variable _Query_ setting.
-
-```sql
-SELECT hostname FROM host
-```
-
-A query can return multiple columns and Grafana will automatically create a list from them. For example, the query below will return a list with values from `hostname` and `hostname2`.
-
-```sql
-SELECT host.hostname, other_host.hostname2 FROM host JOIN other_host ON host.city = other_host.city
-```
-
-To use time range dependent macros like `$__timeFilter(column)` in your query the refresh mode of the template variable needs to be set to _On Time Range Change_.
-
-```sql
-SELECT event_name FROM event_log WHERE $__timeFilter(time_column)
-```
-
-Another option is a query that can create a key/value variable. The query should return two columns that are named `__text` and `__value`. The `__text` column value should be unique (if it is not unique then the first value is used). The options in the dropdown will have a text and value that allows you to have a friendly name as text and an id as the value. An example query with `hostname` as the text and `id` as the value:
-
-```sql
-SELECT hostname AS __text, id AS __value FROM host
-```
-
-You can also create nested variables. Using a variable named `region`, you could have
-the hosts variable only show hosts from the current selected region with a query like this (if `region` is a multi-value variable then use the `IN` comparison operator rather than `=` to match against multiple values):
-
-```sql
-SELECT hostname FROM host WHERE region IN($region)
-```
-
-#### Using `__searchFilter` to filter results in Query Variable
-
-Using `__searchFilter` in the query field will filter the query result based on what the user types in the dropdown select box.
-When nothing has been entered by the user the default value for `__searchFilter` is `%`.
-
-> Important that you surround the `__searchFilter` expression with quotes as Grafana does not do this for you.
-
-The example below shows how to use `__searchFilter` as part of the query field to enable searching for `hostname` while the user types in the dropdown select box.
-
-Query
-
-```sql
-SELECT hostname FROM my_host WHERE hostname LIKE '$__searchFilter'
-```
-
-### Using Variables in Queries
-
-Template variable values are only quoted when the template variable is a `multi-value`.
-
-If the variable is a multi-value variable then use the `IN` comparison operator rather than `=` to match against multiple values.
-
-There are two syntaxes:
-
-`$` Example with a template variable named `hostname`:
-
-```sql
-SELECT
- atimestamp as time,
- aint as value
-FROM table
-WHERE $__timeFilter(atimestamp) and hostname in($hostname)
-ORDER BY atimestamp ASC
-```
-
-`[[varname]]` Example with a template variable named `hostname`:
-
-```sql
-SELECT
- atimestamp as time,
- aint as value
-FROM table
-WHERE $__timeFilter(atimestamp) and hostname in([[hostname]])
-ORDER BY atimestamp ASC
-```
-
-#### Disabling quoting for multi-value variables
-
-Grafana automatically creates a quoted, comma-separated string for multi-value variables. For example: if `server01` and `server02` are selected then it will be formatted as: `'server01', 'server02'`. To disable quoting, use the csv formatting option for variables:
-
-`${servers:csv}`
-
-Read more about variable formatting options in the [Variables](ref:variable-syntax-advanced-variable-format-options) documentation.
-
-## Annotations
-
-[Annotations](ref:annotate-visualizations) allow you to overlay rich event information on top of graphs. You add annotation queries via the Dashboard menu / Annotations view.
-
-**Example query using time column with epoch values:**
-
-```sql
-SELECT
- epoch_time as time,
- metric1 as text,
- concat_ws(', ', metric1::text, metric2::text) as tags
-FROM
- public.test_data
-WHERE
- $__unixEpochFilter(epoch_time)
-```
-
-**Example region query using time and timeend columns with epoch values:**
-
-```sql
-SELECT
- epoch_time as time,
- epoch_time_end as timeend,
- metric1 as text,
- concat_ws(', ', metric1::text, metric2::text) as tags
-FROM
- public.test_data
-WHERE
- $__unixEpochFilter(epoch_time)
-```
-
-**Example query using time column of native SQL date/time data type:**
-
-```sql
-SELECT
- native_date_time as time,
- metric1 as text,
- concat_ws(', ', metric1::text, metric2::text) as tags
-FROM
- public.test_data
-WHERE
- $__timeFilter(native_date_time)
-```
-
-| Name | Description |
-| --------- | ----------------------------------------------------------------------------------------------------------------- |
-| `time` | The name of the date/time field. Could be a column with a native SQL date/time data type or epoch value. |
-| `timeend` | Optional name of the end date/time field. Could be a column with a native SQL date/time data type or epoch value. |
-| `text` | Event description field. |
-| `tags` | Optional field name to use for event tags as a comma separated string. |
-
-## Alerting
-
-Time series queries should work in alerting conditions. Table formatted queries are not yet supported in alert rule
-conditions.
diff --git a/docs/sources/datasources/postgres/configure/_index.md b/docs/sources/datasources/postgres/configure/_index.md
new file mode 100644
index 00000000000..7b6a66c0a70
--- /dev/null
+++ b/docs/sources/datasources/postgres/configure/_index.md
@@ -0,0 +1,194 @@
+---
+description: This document provides instructions for configuring the PostgreSQL data source.
+keywords:
+ - grafana
+ - postgresql
+ - guide
+labels:
+ products:
+ - cloud
+ - enterprise
+ - oss
+menuTitle: Configure the PostgreSQL data source
+title: Configure the PostgreSQL data source
+weight: 10
+refs:
+ provisioning-data-sources:
+ - pattern: /docs/grafana/
+ destination: /docs/grafana//administration/provisioning/#datasources
+ - pattern: /docs/grafana-cloud/
+ destination: /docs/grafana//administration/provisioning/#datasources
+ variables:
+ - pattern: /docs/grafana/
+ destination: /docs/grafana//dashboards/variables/
+ - pattern: /docs/grafana-cloud/
+ destination: /docs/grafana//dashboards/variables/
+ add-template-variables-interval-ms:
+ - pattern: /docs/grafana/
+ destination: /docs/grafana//dashboards/variables/add-template-variables/#__interval_ms
+ - pattern: /docs/grafana-cloud/
+ destination: /docs/grafana//dashboards/variables/add-template-variables/#__interval_ms
+ add-template-variables-interval:
+ - pattern: /docs/grafana/
+ destination: /docs/grafana//dashboards/variables/add-template-variables/#__interval
+ - pattern: /docs/grafana-cloud/
+ destination: /docs/grafana//dashboards/variables/add-template-variables/#__interval
+ data-source-management:
+ - pattern: /docs/grafana/
+ destination: /docs/grafana//administration/data-source-management/
+ - pattern: /docs/grafana-cloud/
+ destination: /docs/grafana//administration/data-source-management/
+ variable-syntax-advanced-variable-format-options:
+ - pattern: /docs/grafana/
+ destination: /docs/grafana//dashboards/variables/variable-syntax/#advanced-variable-format-options
+ - pattern: /docs/grafana-cloud/
+ destination: /docs/grafana//dashboards/variables/variable-syntax/#advanced-variable-format-options
+---
+
+# Configure the PostgreSQL data source
+
+This document provides instructions for configuring the PostgreSQL data source and explains available configuration options. For general information on managing data sources refer to [Data source management](ref:data-source-management).
+
+## Before you begin
+
+You must have the `Organization administrator` role to configure the Postgres data source.
+Organization administrators can also [configure the data source via YAML](#provision-the-data-source) with the Grafana provisioning system.
+
+Grafana comes with a built-in PostgreSQL data source plugin, eliminating the need to install a plugin.
+
+{{< admonition type="note" >}}
+When adding a data source, the database user you specify should have only `SELECT` permissions on the relevant database and tables. Grafana does not validate the safety of queries, which means they can include potentially harmful SQL statements, such as `USE otherdb;` or `DROP TABLE user;`, that could be executed. To mitigate this risk, Grafana strongly recommends creating a dedicated PostgreSQL user with restricted permissions.
+{{< /admonition >}}
+
+Example:
+
+```sql
+ CREATE USER grafanareader WITH PASSWORD 'password';
+ GRANT USAGE ON SCHEMA schema TO grafanareader;
+ GRANT SELECT ON schema.table TO grafanareader;
+```
+
+## Add the PostgreSQL data source
+
+Complete the following steps to set up a new PostgreSQL data source:
+
+1. Click **Connections** in the left-side menu.
+1. Click **Add new connection**
+1. Type `PostgreSQL` in the search bar.
+1. Select the **PostgreSQL data source**.
+1. Click **Add new data source** in the upper right.
+
+You are taken to the **Settings** tab where you will configure the data source.
+
+## PostgreSQL configuration options
+
+Following is a list of PostgreSQL configuration options:
+
+- **Name** - Sets the name you use to refer to the data source in panels and queries. Examples: `PostgreSQL-DB-1`.
+- **Default** - Toggle to set this specific PostgreSQL data source as the default pre-selected data source in panels and visualizations.
+
+**Connection section:**
+
+- **Host URL** - The IP address/hostname and optional port of your PostgreSQL instance.
+- **Database name** - The name of your PostgreSQL database.
+
+**Authentication section:**
+
+- **Username** - Enter the username used to connect to your PostgreSQL database.
+- **Password** - Enter the password used to connect to the PostgreSQL database.
+- **TLS/SSL Mode** - Determines whether or with what priority a secure SSL TCP/IP connection will be negotiated with the server. When **TLS/SSL Mode** is disabled, **TLS/SSL Method** and **TLS/SSL Auth Details** aren't visible options.
+- **TLS/SSL Method** - Determines how TLS/SSL certificates are configured.
+ - **File system path** - This option allows you to configure certificates by specifying paths to existing certificates on the local file system where Grafana is running. Ensure this file is readable by the user executing the Grafana process.
+ - **Certificate content** - This option allows you to configure certificate by specifying their content. The content is stored and encrypted in the Grafana database. When connecting to the database, the certificates are saved as files, on the local filesystem, in the Grafana data path.
+
+**TLS/SSL Auth Details**
+
+If you select the TLS/SSL Mode options **require**, **verify-ca** or **verify-full** and **file system path** the following are required:
+
+- **TLS/SSL Root Certificate** - Specify the path to the root certificate file.
+- **TLS/SSL Client Certificate** - Specify the path to the client certificate and ensure the file is accessible to the user running the Grafana process.
+- **TLS/SSL Client Key** - Specify the path to the client key file and ensure the file is accessible to the user running the Grafana process.
+
+If you select the TLS/SSL Mode option **require** and TLS/SSL Method certificate content the following are required:
+
+- **TLS/SSL Client Certificate** - Provide the client certificate.
+- **TLS/SSL Client Key** - Provide the client key.
+
+If you select the TLS/SSL Mode options **verify-ca** or **verify-full** with the TLS/SSL Method certificate content the following are required:
+
+- **TLS/SSL Client Certificate** - Provide the client certificate.
+- **TLS/SSL Root Certificate** - Provide the root certificate.
+- **TLS/SSL Client Key** - Provide the client key.
+
+**PostgreSQL Options:**
+
+- **Version** - Determines which functions are available in the query builder. The default is the current version.
+- **Min time interval** - Defines a lower limit for the auto group by by time interval. Grafana recommends aligning this setting with the data write frequency. For example, set it to `1m` if your data is written every minute. Refer to [Min time interval](#min-time-interval) for format examples.
+- **TimescaleDB** - A time-series database built as a PostgreSQL extension. When enabled, Grafana uses `time_bucket` in the `$__timeGroup` macro to display TimescaleDB specific aggregate functions in the query builder. For more information, refer to [TimescaleDB documentation](https://docs.timescale.com/timescaledb/latest/tutorials/grafana/grafana-timescalecloud/#connect-timescaledb-and-grafana).
+
+**Connection limits:**
+
+- **Max open** - The maximum number of open connections to the database. The default `100`.
+- **Auto max idle** - Toggle to set the maximum number of idle connections to the number of maximum open connections. This setting is toggled on by default.
+- **Max idle** - The maximum number of connections in the idle connection pool. The default `100`.
+- **Max lifetime** - The maximum amount of time in seconds a connection may be reused. The default is `14400`, or 4 hours.
+
+**Private data source connect** - _Only for Grafana Cloud users._ Private data source connect, or PDC, allows you to establish a private, secured connection between a Grafana Cloud instance, or stack, and data sources secured within a private network. Click the drop-down to locate the URL for PDC. For more information regarding Grafana PDC refer to [Private data source connect (PDC)](https://grafana.com/docs/grafana-cloud/connect-externally-hosted/private-data-source-connect/).
+
+Click **Manage private data source connect** to be taken to your PDC connection page, where you’ll find your PDC configuration details.
+
+After you have added your PostgreSQL connection settings, click **Save & test** to test and save the data source connection.
+
+### Min time interval
+
+The **Min time interval** setting defines a lower limit for the [`$__interval`](ref:add-template-variables-interval) and [`$__interval_ms`](ref:add-template-variables-interval-ms) variables.
+
+This option can also be configured or overridden in the dashboard panel under the data source settings.
+
+This value must be formatted as a number followed by a valid time identifier:
+
+| Identifier | Description |
+| ---------- | ----------- |
+| `y` | year |
+| `M` | month |
+| `w` | week |
+| `d` | day |
+| `h` | hour |
+| `m` | minute |
+| `s` | second |
+| `ms` | millisecond |
+
+## Provision the data source
+
+You can define and configure the data source in YAML files with [provisioning](/docs/grafana//administration/provisioning/#data-sources).
+For more information about provisioning, and available configuration options, refer to [Provision Grafana](ref:provisioning-data-sources).
+
+### PostgreSQL provisioning example
+
+```yaml
+apiVersion: 1
+
+datasources:
+ - name: Postgres
+ type: postgres
+ url: localhost:5432
+ user: grafana
+ secureJsonData:
+ password: 'Password!'
+ jsonData:
+ database: grafana
+ sslmode: 'disable' # disable/require/verify-ca/verify-full
+ maxOpenConns: 100
+ maxIdleConns: 100
+ maxIdleConnsAuto: true
+ connMaxLifetime: 14400
+ postgresVersion: 903 # 903=9.3, 904=9.4, 905=9.5, 906=9.6, 1000=10
+ timescaledb: false
+```
+
+#### Troubleshoot provisioning issues
+
+If you encounter metric request errors or other issues:
+
+- Ensure that the parameters in your data source YAML file precisely match the example provided, including parameter names and the correct use of quotation marks.
+- Verify that the database name _isn't_ included in the URL.
diff --git a/docs/sources/datasources/postgres/query-editor/_index.md b/docs/sources/datasources/postgres/query-editor/_index.md
new file mode 100644
index 00000000000..5c37f7047e7
--- /dev/null
+++ b/docs/sources/datasources/postgres/query-editor/_index.md
@@ -0,0 +1,410 @@
+---
+description: This document describes the PostgreSQL query editor in Grafana.
+keywords:
+ - grafana
+ - postgresql
+ - guide
+labels:
+ products:
+ - cloud
+ - enterprise
+ - oss
+menuTitle: PostgreSQL query editor
+title: PostgreSQL query editor
+weight: 20
+refs:
+ variables:
+ - pattern: /docs/grafana/
+ destination: /docs/grafana//dashboards/variables/
+ - pattern: /docs/grafana-cloud/
+ destination: /docs/grafana//dashboards/variables/
+ add-template-variables-interval:
+ - pattern: /docs/grafana/
+ destination: /docs/grafana//dashboards/variables/add-template-variables/#__interval
+ - pattern: /docs/grafana-cloud/
+ destination: /docs/grafana//dashboards/variables/add-template-variables/#__interval
+ explore:
+ - pattern: /docs/grafana/
+ destination: /docs/grafana//explore/
+ - pattern: /docs/grafana-cloud/
+ destination: /docs/grafana//explore/
+ query-transform-data:
+ - pattern: /docs/grafana/
+ destination: /docs/grafana//panels-visualizations/query-transform-data/
+ - pattern: /docs/grafana-cloud/
+ destination: /docs/grafana-cloud/visualizations/panels-visualizations/query-transform-data/
+ query-editor:
+ - pattern: /docs/grafana/
+ destination: /docs/grafana//panels-visualizations/query-transform-data/#query-editors
+ - pattern: /docs/grafana-cloud/
+ destination: /docs/grafana-cloud/visualizations/panels-visualizations/query-transform-data/#query-editors
+ alert-rules:
+ - pattern: /docs/grafana/
+ destination: /docs/grafana//alerting/fundamentals/alert-rules/
+ - pattern: /docs/grafana-cloud/
+ destination: /docs/grafana-cloud/alerting-and-irm/alerting/alerting-rules/
+ template-annotations-and-labels:
+ - pattern: /docs/grafana/
+ destination: /docs/grafana//alerting/alerting-rules/templates/
+ - pattern: /docs/grafana-cloud/
+ destination: /docs/grafana-cloud/alerting-and-irm/alerting/alerting-rules/templates/
+ templates:
+ - pattern: /docs/grafana/
+ destination: /docs/grafana//dashboards/variables/#templates
+ - pattern: /docs/grafana-cloud/
+ destination: /docs/grafana-cloud/visualizations/dashboards/variables/#templates
+---
+
+# PostgreSQL query editor
+
+Grafana query editors are unique for each data source.
+
+For general information on Grafana query editors, refer to [Query editors](ref:query-editor).
+
+For general information on querying data sources in Grafana, refer to [Query and transform data](ref:query-transform-data).
+
+The PostgreSQL query editor is located on the [Explore page](ref:explore). You can also access the PostgreSQL query editor from a dashboard panel. Click the ellipsis in the upper right of the panel and select **Edit**.
+
+{{< figure src="/static/img/docs/screenshot-postgres-query-editor.png" class="docs-image--no-shadow" caption="PostgreSQL query builder" >}}
+
+## PostgreSQL query editor components
+
+The PostgreSQL query editor has two modes: **Builder** and **Code**.
+
+Builder mode helps you build a query using a visual interface. Code mode allows for advanced querying and offers support for complex SQL query writing.
+
+### PostgreSQL Builder mode
+
+The following components will help you build a PostgreSQL query:
+
+- **Format** - Select a format response from the drop-down for the PostgreSQL query. The default is **Table**. If you use the **Time series** format option, one of the columns must be `time`. Refer to [Time series queries](#time-series-queries) for more information.
+- **Table** - Select a table from the drop-down. Tables correspond to the chosen database.
+- **Data operations** - _Optional_ Select an aggregation from the drop-down. You can add multiple data operations by clicking the **+ sign**. Click the **garbage can icon** to remove data operations.
+- **Column** - Select a column on which to run the aggregation.
+- **Alias** - _Optional_ Add an alias from the drop-down. You can also add your own alias by typing it in the box and clicking **Enter**. Remove an alias by clicking the **X**.
+- **Filter** - Toggle to add filters.
+- **Filter by column value** - _Optional_ If you toggle **Filter** you can add a column to filter by from the drop-down. To filter on more columns, click the **+ sign** to the right of the condition drop-down. You can choose a variety of operators from the drop-down next to the condition. When multiple filters are added you can add an `AND` operator to display all true conditions or an `OR` operator to display any true conditions. Use the second drop-down to choose a filter. To remove a filter, click the `X` button next to that filter's drop-down. After selecting a date type column, you can choose **Macros** from the operators list and select `timeFilter` which will add the `$\_\_timeFilter` macro to the query with the selected date column.
+- **Group** - Toggle to add **Group by column**.
+- **Group by column** - Select a column to filter by from the drop-down. Click the **+sign** to filter by multiple columns. Click the **X** to remove a filter.
+- **Order** - Toggle to add an `ORDER BY` statement.
+- **Order by** - Select a column to order by from the drop-down. Select ascending (`ASC`) or descending (`DESC`) order.
+- **Limit** - You can add an optional limit on the number of retrieved results. Default is 50.
+- **Preview** - Toggle for a preview of the SQL query generated by the query builder. Preview is toggled on by default.
+
+## PostgreSQL Code mode
+
+To create advanced queries, switch to **Code mode** by clicking **Code** in the upper right of the editor window. Code mode supports the auto-completion of tables, columns, SQL keywords, standard SQL functions, Grafana template variables, and Grafana macros. Columns cannot be completed before a table has been specified.
+
+{{< figure src="/static/img/docs/v92/sql_code_editor.png" class="docs-image--no-shadow" >}}
+
+Select **Table** or **Time Series** as the format. Click the **{}** in the bottom right to format the query. Click the **downward caret** to expand the Code mode editor. **CTRL/CMD + Return** serves as a keyboard shortcut to execute the query.
+
+{{< admonition type="warning" >}}
+Changes made to a query in Code mode will not transfer to Builder mode and will be discarded. You will be prompted to copy your code to the clipboard to save any changes.
+{{< /admonition >}}
+
+## Macros
+
+You can add macros to your queries to simplify the syntax and enable dynamic elements, such as date range filters.
+
+| Macro example | Description |
+| ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `$__time(dateColumn)` | Replaces the value with an expression to convert to a UNIX timestamp and renames the column to `time_sec`. Example: `UNIX_TIMESTAMP(dateColumn) AS time_sec`. |
+| `$__timeEpoch(dateColumn)` | Replaces the value with an expression to convert to a UNIX Epoch timestamp and renames the column to `time_sec`. Example: `UNIX_TIMESTAMP(dateColumn) AS time_sec`. |
+| `$__timeFilter(dateColumn)` | Replaces the value a time range filter using the specified column name. Example: `dateColumn BETWEEN FROM_UNIXTIME(1494410783) AND FROM_UNIXTIME(1494410983)` |
+| `$__timeFrom()` | Replaces the value with the start of the currently active time selection. Example: `FROM_UNIXTIME(1494410783)` |
+| `$__timeTo()` | Replaces the value with the end of the currently active time selection. Example: `FROM_UNIXTIME(1494410983)` |
+| `$__timeGroup(dateColumn,'5m')` | Replaces the value with an expression suitable for use in a `GROUP BY` clause. Example: `cast(cast(UNIX_TIMESTAMP(dateColumn)/(300) AS signed)*300 AS signed)` |
+| `$__timeGroup(dateColumn,'5m', 0)` | Same as the `$__timeGroup(dateColumn,'5m')` macro, but includes a fill parameter to ensure missing points in the series are added by Grafana, using 0 as the default value. **This applies only to time series queries.** |
+| `$__timeGroup(dateColumn,'5m', NULL)` | Same as the `$__timeGroup(dateColumn,'5m', 0)` but `NULL` is used as the value for missing points. _This applies only to time series queries._ |
+| `$__timeGroup(dateColumn,'5m', previous)` | Same as the `$__timeGroup(dateColumn,'5m', previous)` macro, but uses the previous value in the series as the fill value. If no previous value exists, it uses `NULL`. _This applies only to time series queries._ |
+| `$__timeGroupAlias(dateColumn,'5m')` | Replaces the value identical to `$__timeGroup` but with an added column alias. |
+| `$__unixEpochFilter(dateColumn)` | Replaces the value by a time range filter using the specified column name with times represented as a UNIX timestamp. Example: `dateColumn > 1494410783 AND dateColumn < 1494497183` |
+| `$__unixEpochFrom()` | Replaces the value with the start of the currently active time selection as a UNIX timestamp. Example: `1494410783` |
+| `$__unixEpochTo()` | Replaces the value with the end of the currently active time selection as a UNIX timestamp. Example: `1494497183` |
+| `$__unixEpochNanoFilter(dateColumn)` | Replaces the value with a time range filter using the specified column name with time represented as a nanosecond timestamp. Example: `dateColumn > 1494410783152415214 AND dateColumn < 1494497183142514872` |
+| `$__unixEpochNanoFrom()` | Replaces the value with the start of the currently active time selection as a nanosecond timestamp. Example: `1494410783152415214` |
+| `$__unixEpochNanoTo()` | Replaces the value with the end of the currently active time selection as nanosecond timestamp. Example: `1494497183142514872` |
+| `$__unixEpochGroup(dateColumn,'5m', [fillmode])` | Same as `$__timeGroup` but for times stored as Unix timestamp. `fillMode` only works with time series queries. |
+| `$__unixEpochGroupAlias(dateColumn,'5m', [fillmode])` | Same as `$__timeGroup` but also adds a column alias. `fillMode` only works with time series queries. |
+
+## Table SQL queries
+
+If the **Format** option is set to **Table**, you can execute virtually any type of SQL query. The Table panel will automatically display the resulting columns and rows from your query.
+
+
+
+You can change or customize the name of a Table panel column by using the SQL keyword `AS` syntax.
+
+```sql
+SELECT
+ title as "Title",
+ "user".login as "Created By",
+ dashboard.created as "Created On"
+FROM dashboard
+INNER JOIN "user" on "user".id = dashboard.created_by
+WHERE $__timeFilter(dashboard.created)
+```
+
+## Time series queries
+
+Set the **Format** option to **Time series** to create and run time series queries.
+
+{{< admonition type="note" >}}
+To run a time series query you must include a column named `time` that returns either a SQL `datetime` value or a numeric datatype representing the UNIX epoch time in seconds. Additionally, the query results must be sorted by the `time` column for proper visualization in panels.
+{{< /admonition >}}
+
+The examples in this section refer to the data in the following table:
+
+```text
++---------------------+--------------+---------------------+----------+
+| time_date_time | value_double | CreatedAt | hostname |
++---------------------+--------------+---------------------+----------+
+| 2020-01-02 03:05:00 | 3.0 | 2020-01-02 03:05:00 | 10.0.1.1 |
+| 2020-01-02 03:06:00 | 4.0 | 2020-01-02 03:06:00 | 10.0.1.2 |
+| 2020-01-02 03:10:00 | 6.0 | 2020-01-02 03:10:00 | 10.0.1.1 |
+| 2020-01-02 03:11:00 | 7.0 | 2020-01-02 03:11:00 | 10.0.1.2 |
+| 2020-01-02 03:20:00 | 5.0 | 2020-01-02 03:20:00 | 10.0.1.2 |
++---------------------+--------------+---------------------+----------+
+```
+
+Time series query results are returned in [wide data frame format](https://grafana.com/developers/plugin-tools/key-concepts/data-frames#wide-format). In the data frame query result, any column, except for time or string-type columns, transforms into value fields. String columns, on the other hand, become field labels.
+
+{{< admonition type="note" >}}
+For backward compatibility, an exception to this rule applies to queries that return three columns, one of which is a string column named `metric`. Instead of converting the metric column into field labels, it is used as the field name, while the series name is set to its value. See the following example for reference.
+{{< /admonition >}}
+
+**Example with `metric` column:**
+
+```sql
+SELECT
+ $__timeGroupAlias("time_date_time",'5m'),
+ min("value_double"),
+ 'min' as metric
+FROM test_data
+WHERE $__timeFilter("time_date_time")
+GROUP BY time
+ORDER BY time
+```
+
+Data frame result:
+
+```text
++---------------------+-----------------+
+| Name: time | Name: min |
+| Labels: | Labels: |
+| Type: []time.Time | Type: []float64 |
++---------------------+-----------------+
+| 2020-01-02 03:05:00 | 3 |
+| 2020-01-02 03:10:00 | 6 |
++---------------------+-----------------+
+```
+
+To customize default series name formatting, refer to [Standard options definitions](ref:configure-standard-options-display-name).
+
+Following are time series query examples.
+
+**Example using the fill parameter in the $\_\_timeGroupAlias macro to convert null values to be zero instead:**
+
+```sql
+SELECT
+ $__timeGroupAlias("createdAt",'5m',0),
+ sum(value) as value,
+ hostname
+FROM test_data
+WHERE
+ $__timeFilter("createdAt")
+GROUP BY time, hostname
+ORDER BY time
+```
+
+Based on the data frame result in the following example, the time series panel will generate two series named _value 10.0.1.1_ and _value 10.0.1.2_. To display the series names as _10.0.1.1_ and _10.0.1.2_, use the [Standard options definitions](ref:configure-standard-options-display-name) display value `${__field.labels.hostname}`.
+
+Data frame result:
+
+```text
++---------------------+---------------------------+---------------------------+
+| Name: time | Name: value | Name: value |
+| Labels: | Labels: hostname=10.0.1.1 | Labels: hostname=10.0.1.2 |
+| Type: []time.Time | Type: []float64 | Type: []float64 |
++---------------------+---------------------------+---------------------------+
+| 2020-01-02 03:05:00 | 3 | 4 |
+| 2020-01-02 03:10:00 | 6 | 7 |
++---------------------+---------------------------+---------------------------+
+```
+
+**Example with multiple columns:**
+
+```sql
+SELECT
+ $__timeGroupAlias("time_date_time",'5m'),
+ min("value_double") as "min_value",
+ max("value_double") as "max_value"
+FROM test_data
+WHERE $__timeFilter("time_date_time")
+GROUP BY time
+ORDER BY time
+```
+
+Data frame result:
+
+```text
++---------------------+-----------------+-----------------+
+| Name: time | Name: min_value | Name: max_value |
+| Labels: | Labels: | Labels: |
+| Type: []time.Time | Type: []float64 | Type: []float64 |
++---------------------+-----------------+-----------------+
+| 2020-01-02 03:04:00 | 3 | 4 |
+| 2020-01-02 03:05:00 | 6 | 7 |
++---------------------+-----------------+-----------------+
+```
+
+## Templating
+
+Instead of hard coding values like server, application, or sensor names in your metric queries, you can use variables. Variables appear as drop-down select boxes at the top of the dashboard. These drop-downs make it easy to change the data being displayed in your dashboard.
+
+Refer to [Templates](ref:templates) for an introduction to creating template variables as well as the different types.
+
+### Query variable
+
+If you add a `Query` template variable you can write a PostgreSQL query to retrieve items such as measurement names, key names, or key values, which will be displayed in the drop-down menu.
+
+For example, you can use a variable to retrieve all the values from the `hostname` column in a table by creating the following query in the templating variable _Query_ setting.
+
+```sql
+SELECT hostname FROM host
+```
+
+A query can return multiple columns, and Grafana will automatically generate a list based on the query results. For example, the following query returns a list with values from `hostname` and `hostname2`.
+
+```sql
+SELECT host.hostname, other_host.hostname2 FROM host JOIN other_host ON host.city = other_host.city
+```
+
+To use time range dependent macros like `$__timeFilter(column)` in your query, you must set the template variable's refresh mode to _On Time Range Change_.
+
+```sql
+SELECT event_name FROM event_log WHERE $__timeFilter(time_column)
+```
+
+Another option is a query that can create a key/value variable. The query should return two columns that are named `__text` and `__value`. The `__text` column must contain unique values (if not, only the first value is used). This allows the drop-down options to display a text-friendly name as the text while using an ID as the value. For example, a query could use `hostname` as the text and `id` as the value:
+
+```sql
+SELECT hostname AS __text, id AS __value FROM host
+```
+
+You can also create nested variables. For example, if you have a variable named `region`, you can configure the `hosts` variable to display only the hosts within the currently selected region as shown in the following example. If `region` is a multi-value variable, use the `IN` operator instead of `=` to match multiple values.
+
+```sql
+SELECT hostname FROM host WHERE region IN($region)
+```
+
+#### Using `__searchFilter` to filter results in Query Variable
+
+Using `__searchFilter` in the query field allows the query results to be filtered based on the user’s input in the drop-down selection box. If you do not enter anything, the default value for `__searchFilter` is `%`.
+
+Note that you must enclose the `__searchFilter` expression in quotes as Grafana does not add them automatically.
+
+The following example demonstrates how to use `__searchFilter` in the query field to enable real-time searching for `hostname` as the user type in the drop-down selection box.
+
+```sql
+SELECT hostname FROM my_host WHERE hostname LIKE '$__searchFilter'
+```
+
+### Using Variables in Queries
+
+Template variable values are only quoted when the template variable is a `multi-value`.
+
+If the variable is a multi-value variable, use the `IN` comparison operator instead of `=` to match against multiple values.
+
+You can use two different syntaxes:
+
+`$` Example with a template variable named `hostname`:
+
+```sql
+SELECT
+ atimestamp as time,
+ aint as value
+FROM table
+WHERE $__timeFilter(atimestamp) and hostname in($hostname)
+ORDER BY atimestamp ASC
+```
+
+`[[varname]]` Example with a template variable named `hostname`:
+
+```sql
+SELECT
+ atimestamp as time,
+ aint as value
+FROM table
+WHERE $__timeFilter(atimestamp) and hostname in([[hostname]])
+ORDER BY atimestamp ASC
+```
+
+#### Disabling quoting for multi-value variables
+
+Grafana automatically formats multi-value variables as a quoted, comma-separated string. For example, if `server01` and `server02` are selected, they are formatted as `'server01'`, `'server02'`. To remove the quotes, enable the CSV formatting option for the variables:
+
+`${servers:csv}`
+
+Read more about variable formatting options in the [Variables](ref:variable-syntax-advanced-variable-format-options) documentation.
+
+## Annotations
+
+[Annotations](ref:annotate-visualizations) allow you to overlay rich event information on top of graphs. Add annotation queries via the **Dashboard settings > Annotations view**.
+
+**Example query using a `time` column with epoch values:**
+
+```sql
+SELECT
+ epoch_time as time,
+ metric1 as text,
+ concat_ws(', ', metric1::text, metric2::text) as tags
+FROM
+ public.test_data
+WHERE
+ $__unixEpochFilter(epoch_time)
+```
+
+**Example region query using `time` and `timeend` columns with epoch values:**
+
+```sql
+SELECT
+ epoch_time as time,
+ epoch_time_end as timeend,
+ metric1 as text,
+ concat_ws(', ', metric1::text, metric2::text) as tags
+FROM
+ public.test_data
+WHERE
+ $__unixEpochFilter(epoch_time)
+```
+
+**Example query using a `time` column with a native SQL date/time data type:**
+
+```sql
+SELECT
+ native_date_time as time,
+ metric1 as text,
+ concat_ws(', ', metric1::text, metric2::text) as tags
+FROM
+ public.test_data
+WHERE
+ $__timeFilter(native_date_time)
+```
+
+| Name | Description |
+| --------- | --------------------------------------------------------------------------------------------------------------------- |
+| `time` | The name of the date/time field, which can be a column with a native SQL date/time data type or epoch value. |
+| `timeend` | Optional name of the end date/time field, which can be a column with a native SQL date/time data type or epoch value. |
+| `text` | Event description field. |
+| `tags` | Optional field name to use for event tags as a comma-separated string. |
+
+## Alerting
+
+Use time series queries to create alerts. Table formatted queries aren't yet supported in alert rule conditions.
+
+For more information regarding alerting refer to the following:
+
+- [Alert rules](ref:alert-rules)
+- [Template annotations and labels](ref:template-annotations-and-labels)
diff --git a/docs/sources/datasources/prometheus/_index.md b/docs/sources/datasources/prometheus/_index.md
index cd5cbb04ac1..46015e7a0af 100644
--- a/docs/sources/datasources/prometheus/_index.md
+++ b/docs/sources/datasources/prometheus/_index.md
@@ -89,13 +89,13 @@ For instructions on how to add a data source to Grafana, refer to the [administr
Only users with the organization `administrator` role can add data sources and edit existing data sources.
Administrators can also [configure the data source via YAML](#provision-the-data-source) with Grafana's provisioning system.
-Once you've added the Prometheus data source, you can [configure it](ref:configure-prometheus-data-source) so that your Grafana instance's users can create queries in its [query editor]({{< relref "./query-editor" >}}) when they [build dashboards](ref:build-dashboards), use [Explore](ref:explore), and [annotate visualizations](ref:annotate-visualizations).
+Once you've added the Prometheus data source, you can [configure it](ref:configure-prometheus-data-source) so that your Grafana instance's users can create queries in its [query editor](query-editor/) when they [build dashboards](ref:build-dashboards), use [Explore](ref:explore), and [annotate visualizations](ref:annotate-visualizations).
The following guides will help you get started with the Prometheus data source:
- [Configure the Prometheus data source](ref:configure-prometheus-data-source)
-- [Prometheus query editor]({{< relref "./query-editor" >}})
-- [Template variables]({{< relref "./template-variables" >}})
+- [Prometheus query editor](query-editor/)
+- [Template variables](template-variables/)
## Prometheus API
diff --git a/docs/sources/datasources/prometheus/configure-prometheus-data-source.md b/docs/sources/datasources/prometheus/configure-prometheus-data-source.md
index 077b6aeff04..a0888659638 100644
--- a/docs/sources/datasources/prometheus/configure-prometheus-data-source.md
+++ b/docs/sources/datasources/prometheus/configure-prometheus-data-source.md
@@ -48,13 +48,18 @@ Grafana ships with built-in support for Prometheus. If you are new to Prometheus
## Configure the data source
+{{< shared id="add-prom-data-source" >}}
+
To add the Prometheus data source, complete the following steps:
1. Click **Connections** in the left-side menu.
1. Under **Connections**, click **Add new connection**.
1. Enter `Prometheus` in the search bar.
-1. Select **Prometheus**.
+1. Click **Prometheus data source**.
1. Click **Add new data source** in the upper right.
+1. Enter a name for the data source.
+
+{{< /shared >}}
You will be taken to the **Settings** tab where you will set up your Prometheus configuration.
@@ -70,7 +75,8 @@ The first option to configure is the name of your connection:
### Connection section
-- **Prometheus server URL** - The URL of your Prometheus server. If your Prometheus server is local, use `http://localhost:9090`. If it is on a server within a network, this is the URL with port where you are running Prometheus. Example: `http://prometheus.example.orgname:9090`.
+- **Prometheus server URL** - The URL of your Prometheus server. {{< shared id="prom-data-source-url" >}}
+ If your Prometheus server is local, use `http://localhost:9090`. If it's on a server within a network, this is the URL with the port where you are running Prometheus. Example: `http://prometheus.example.orgname:9090`.
{{< admonition type="note" >}}
@@ -80,6 +86,8 @@ You should use the IP address of the Prometheus container, or the hostname if yo
{{< /admonition >}}
+{{< /shared >}}
+
### Authentication section
There are several authentication methods you can choose in the Authentication section.
@@ -124,7 +132,7 @@ Following are additional configuration options.
{{% admonition type="note" %}}
-The **Manage alerts via Alerting UI** toggle is enabled by default. You can change this behavior by setting the [default_manage_alerts_ui_toggle]({{< relref "../../setup-grafana/configure-grafana/#default_manage_alerts_ui_toggle" >}}) option in the Grafana configuration file.
+The **Manage alerts via Alerting UI** toggle is enabled by default. You can change this behavior by setting the [default_manage_alerts_ui_toggle](../../../setup-grafana/configure-grafana/#default_manage_alerts_ui_toggle) option in the Grafana configuration file.
{{% /admonition %}}
@@ -136,7 +144,7 @@ The **Manage alerts via Alerting UI** toggle is enabled by default. You can chan
### Query editor
-- **Default editor** - Sets a default editor. Options are `Builder` or `Code`. For information on query editor types see [Prometheus query editor]({{< relref "./query-editor" >}}).
+- **Default editor** - Sets a default editor. Options are `Builder` or `Code`. For information on query editor types see [Prometheus query editor](../query-editor/).
- **Disable metrics lookup** - Toggle on to disable the metrics chooser and metric/label support in the query field's autocomplete. This helps if you have performance issues with large Prometheus instances.
@@ -171,3 +179,22 @@ Support for exemplars is available only for the Prometheus data source. If this
- **Label name** - The name of the field in the `labels` object used to obtain the traceID property.
- **Remove exemplar link** - Click to remove existing links.
+
+### Troubleshooting
+
+Refer to the following troubleshooting information, as required.
+
+#### Data doesn't appear in Explore metrics
+
+
+
+If metric data doesn't appear in Explore after you've successfully tested a connection to a Prometheus data source or sent
+metrics to Grafana Cloud, ensure that you've selected the correct data source in the **Data source** drop-down menu. If
+you've used remote_write to send metrics to Grafana Cloud, the data source name follows the convention
+`grafanacloud-stackname-prom`.
+
+
+
+The following image shows the **Data source** field in Explore metrics.
+
+
diff --git a/docs/sources/datasources/pyroscope/_index.md b/docs/sources/datasources/pyroscope/_index.md
index 069902bfc0a..60efe8f3f33 100644
--- a/docs/sources/datasources/pyroscope/_index.md
+++ b/docs/sources/datasources/pyroscope/_index.md
@@ -56,7 +56,7 @@ To use profiling data, you should:
- [Configure your application to send profiles](/docs/pyroscope//configure-client/)
- [Configure the Grafana Pyroscope data source](./configure-pyroscope-data-source/).
-- [View and query profiling data using Explore Profiles or the query editor ](./query-profile-data/)
+- [View and query profiling data using Profiles Drilldown or the query editor ](./query-profile-data/)
## Continuous profiling
diff --git a/docs/sources/datasources/pyroscope/configure-pyroscope-data-source.md b/docs/sources/datasources/pyroscope/configure-pyroscope-data-source.md
index 8a344f6a7e6..0acfd01df3c 100644
--- a/docs/sources/datasources/pyroscope/configure-pyroscope-data-source.md
+++ b/docs/sources/datasources/pyroscope/configure-pyroscope-data-source.md
@@ -33,11 +33,11 @@ refs:
destination: /docs/grafana//datasources/tempo/configure-tempo-data-source/
- pattern: /docs/grafana-cloud/
destination: docs/grafana-cloud/connect-externally-hosted/data-sources/tempo/configure-tempo-data-source/
- provisioning-data-sources:
+ explore-profiles:
- pattern: /docs/grafana/
- destination: /docs/grafana//administration/provisioning/#data-sources
- - pattern: /docs/grafana-cloud/provision
- destination: /docs/grafana//administration/provisioning/#data-sources
+ destination: /docs/grafana//explore/simplified-exploration/profiles/
+ - pattern: /docs/grafana-cloud/
+ destination: /docs/grafana-cloud/visualizations/simplified-exploration/profiles/
---
# Configure the Grafana Pyroscope data source
@@ -73,7 +73,7 @@ To configure basic settings for the data source, complete the following steps:
1. On the **Settings** tab, complete the **Name**, **Connection**, and **Authentication** sections.
- Use the **Name** field to specify the name used for the data source in panels, queries, and Explore. Toggle the **Default** switch for the data source to be pre-selected for new panels.
-- Under **Connection**, enter the **URL** of the Pyroscope instance. For example, `https://example.com:4100`.
+- Under **Connection**, enter the **URL** of the Pyroscope instance. For example, `https://example.com:4100`. Refer to [Connection URL](#connection-url) for more information.
- Complete the [**Authentication** section](#authentication).
1. Optional: Use **Additional settings** to configure other options.
@@ -89,6 +89,24 @@ To modify an existing Pyroscope data source:
1. Optional: Use **Additional settings** to configure or modify other options.
1. After completing your updates, select **Save & test**.
+#### Connection URL
+
+The data source connection URL should point to a location of a running Pyroscope backend.
+
+**Grafana Cloud Profiles**
+
+Your Grafana Cloud instance automatically includes a fully provisioned data source.
+
+If you are running a self-managed Grafana instance or need to configure an additional Pyroscope data source pointing to Grafana Cloud Profiles, you can find the Pyroscope URL under the **Manage your stack** section for your organization.
+
+**Self-managed Pyroscope backend**
+
+The connection URL for a self-managed Pyroscope backend depends on how Pyroscope is deployed.
+Refer to the steps under [Query profiles in Grafana](https://grafana.com/docs/pyroscope//deploy-kubernetes/helm/#query-profiles-in-grafana) for more information on how to configure the data source.
+
+If you plan to use the [Profiles Drilldown](ref:explore-profiles) application and you are running a self-managed Pyroscope backend in microservices mode, the data source connection URL should point to a gateway or proxy that routes requests to the corresponding Pyroscope service.
+Refer to the [Helm ingress configuration](https://github.com/grafana/pyroscope/blob/main/operations/pyroscope/helm/pyroscope/templates/ingress.yaml) for specific routing requirements.
+
## Authentication
Use this section to select an authentication method to access the data source.
diff --git a/docs/sources/datasources/pyroscope/query-profile-data.md b/docs/sources/datasources/pyroscope/query-profile-data.md
index d56a629d42d..d0917ccfe12 100644
--- a/docs/sources/datasources/pyroscope/query-profile-data.md
+++ b/docs/sources/datasources/pyroscope/query-profile-data.md
@@ -1,5 +1,5 @@
---
-description: Explore your profiling data using Explore Profiles or the Pyroscope query editor.
+description: Explore your profiling data using Profiles Drilldown or the Pyroscope query editor.
keywords:
- query
- profiling
@@ -33,7 +33,7 @@ refs:
destination: /docs/grafana//explore/simplified-exploration/profiles/
- pattern: /docs/grafana-cloud/
destination: /docs/grafana-cloud/visualizations/simplified-exploration/profiles/
- explore-profile-install:
+ explore-profiles-install:
- pattern: /docs/grafana/
destination: /docs/grafana//explore/simplified-exploration/profiles/access/
- pattern: /docs/grafana-cloud/
@@ -54,22 +54,22 @@ https://grafana.com/docs/grafana-cloud/visualizations/panels-visualizations/visu
# Query profile data
-You can query your profile data using the open source Grafana Explore Profiles app or the built-in Grafana Pyroscope data source query editor.
+You can query your profile data using the open source Grafana Profiles Drilldown app or the built-in Grafana Pyroscope data source query editor.
-- Explore Profiles provides a queryless experience for inspecting your profiling data with opinionated workflows to assist your investigation.
+- Profiles Drilldown provides a queryless experience for inspecting your profiling data with opinionated workflows to assist your investigation.
- Data source query editor provides complete control over your data exploration and is recommended for experienced users.
In addition, you can embed flame graph panels in Grafana dashboards.
Refer to the [Flame graph panel](ref:flame-graph-panel) documentation for details.
-## Explore Profiles
+## Profiles Drilldown
-[Explore Profiles](ref:explore-profiles) is a native Grafana application designed to integrate seamlessly with Pyroscope, the open source continuous profiling platform, providing a smooth, queryless experience for browsing and analyzing profiling data.
+[Grafana Profiles Drilldown](ref:explore-profiles) is a native Grafana application designed to integrate seamlessly with Pyroscope, the open source continuous profiling platform, providing a smooth, queryless experience for browsing and analyzing profiling data.
-You can use Explore Profiles in Grafana Cloud or in your own Grafana instance.
-For more information, refer to [Access or install Explore Profiles](ref:explore-profiles-install).
+You can use Profiles Drilldown in Grafana Cloud or in your own Grafana instance.
+For more information, refer to [Access or install Profiles Drilldown](ref:explore-profiles-install).
-
+
### Use cases
@@ -80,10 +80,10 @@ The main use cases are the following:
- Proactive: Cutting costs, addressing latency issues, or optimizing memory usage for applications
- Reactive: Resolving incidents with line-level accuracy or debugging active latency/memory issues
-Explore Profiles provides an intuitive interface to specifically support proactivee and reactive use cases.
+Profiles Drilldown provides an intuitive interface to specifically support proactivee and reactive use cases.
You get a holistic view of all of your services and how they're functioning, but also the ability to drill down for more targeted root cause analysis.
-Explore Profiles offers a convenient platform to analyze profiles and get insights that are impossible to get from using other traditional signals like logs, metrics, or tracing.
+Profiles Drilldown offers a convenient platform to analyze profiles and get insights that are impossible to get from using other traditional signals like logs, metrics, or tracing.
{{< youtube id="x9aPw_CbIQc" >}}
@@ -93,7 +93,7 @@ Explore Profiles offers a convenient platform to analyze profiles and get insigh
The Pyroscope data source query editor gives you access to a profile type selector, a label selector, and collapsible options.
-Like Explore Profiles, the query editor also provides a flame graph to visualize data.
+Like Profiles Drilldown, the query editor also provides a flame graph to visualize data.

diff --git a/docs/sources/datasources/tempo/_index.md b/docs/sources/datasources/tempo/_index.md
index 8b2123b5cd4..836db6cac14 100644
--- a/docs/sources/datasources/tempo/_index.md
+++ b/docs/sources/datasources/tempo/_index.md
@@ -71,7 +71,14 @@ refs:
# Tempo data source
-Grafana ships with built-in support for [Tempo](https://grafana.com/docs/tempo/latest/), a high-volume, minimal-dependency trace storage, open source tracing solution from Grafana Labs. This topic explains configuration and queries specific to the Tempo data source.
+Grafana ships with built-in support for [Tempo](https://grafana.com/docs/tempo//), a high-volume, minimal-dependency trace storage, open source tracing solution from Grafana Labs.
+
+To learn more about traces, refer to [Introduction to tracing](https://grafana.com/docs/tempo//introduction/).
+
+To use traces, you need you have an application or service that is instrumented to emit traces.
+Refer to the [Instrument for tracing](https://grafana.com/docs/tempo//getting-started/instrumentation/) for more information.
+
+## Add a data source
For instructions on how to add a data source to Grafana, refer to the [administration documentation](ref:data-source-management).
Only users with the organization administrator role can add data sources.
@@ -81,6 +88,8 @@ This video explains how to add data sources, including Loki, Tempo, and Mimir, t
{{< youtube id="cqHO0oYW6Ic" start="298" >}}
-Once you've added the data source, you can [configure it]({{< relref "./configure-tempo-data-source/" >}}) so that your Grafana instance's users can create queries in its [query editor]({{< relref "./query-editor/" >}}) when they [build dashboards](ref:build-dashboards) and use [Explore](ref:explore).
+## Learn more
+
+After you've added the data source, you can [configure it](./configure-tempo-data-source/) so that your Grafana instance's users can create queries in its [query editor](./query-editor/) when they [build dashboards](ref:build-dashboards) and use [Explore](ref:explore).
{{< section withDescriptions="true">}}
diff --git a/docs/sources/datasources/tempo/configure-tempo-data-source.md b/docs/sources/datasources/tempo/configure-tempo-data-source.md
index 157238122f1..39d3cdf751a 100644
--- a/docs/sources/datasources/tempo/configure-tempo-data-source.md
+++ b/docs/sources/datasources/tempo/configure-tempo-data-source.md
@@ -131,7 +131,7 @@ To use streaming, you need to:
- Run Tempo version 2.2 or later, or Grafana Enterprise Traces (GET) version 2.2 or later, or use Grafana Cloud Traces.
- Tempo must have `stream_over_http_enabled: true` for streaming to work.
- For more information, refer to [Tempo GRPC API](https://grafana.com/docs/tempo//api_docs/#tempo-grpc-api).
+ For more information, refer to [Tempo gRPC API](https://grafana.com/docs/tempo//api_docs/#tempo-grpc-api).
- For self-managed Tempo or GET instances: If your Tempo or GET instance is behind a load balancer or proxy that doesn't supporting gRPC or HTTP2, streaming may not work and should be deactivated.
@@ -333,6 +333,10 @@ You can choose one of three options:
| **Duration** | _(Default)_ Displays the span duration on the span bar row. |
| **Tag** | Displays the span tag on the span bar row. You must also specify which tag key to use to get the tag value, such as `component`. |
+### Tag limit
+
+The **Tag limit** setting modifies the max number of tags and tag values to retrieve from Tempo. Default: 5000
+
### Private data source connect
[//]: # 'Shared content for authentication section procedure in data sources'
diff --git a/docs/sources/datasources/tempo/query-editor/_index.md b/docs/sources/datasources/tempo/query-editor/_index.md
index b561a54bdcd..022364549e0 100644
--- a/docs/sources/datasources/tempo/query-editor/_index.md
+++ b/docs/sources/datasources/tempo/query-editor/_index.md
@@ -61,7 +61,7 @@ The queries use [TraceQL](/docs/tempo/latest/traceql), the query language design
For general documentation on querying data sources in Grafana, refer to [Query and transform data](ref:query-transform-data).
{{< admonition type="tip" >}}
-Don't know TraceQL? Try [Explore Traces](ref:explore-traces-app), an intuitive, queryless app that lets you explore your tracing data using RED metrics.
+Don't know TraceQL? Try [Grafana Traces Drilldown](ref:explore-traces-app), an intuitive, queryless app that lets you explore your tracing data using RED metrics.
{{< /admonition >}}
## Before you begin
@@ -97,7 +97,7 @@ The three query types are:
The **Search** query builder provides drop-down lists and text fields to help you write a query.
The query builder is ideal for people who aren't familiar with or want to learn TraceQL.
-Refer to the [Search using the TraceQL query builder documentation]({{< relref "./traceql-search" >}}) to learn more about creating queries using convenient drop-down menus.
+Refer to the [Search using the TraceQL query builder documentation](traceql-search/) to learn more about creating queries using convenient drop-down menus.

@@ -105,7 +105,7 @@ Refer to the [Search using the TraceQL query builder documentation]({{< relref "
The **TraceQL** query editor lets you search by trace ID and write TraceQL queries using autocomplete.
-Refer to the [TraceQL query editor documentation]({{< relref "./traceql-editor" >}}) to learn more about constructing queries using a code-editor-like experience.
+Refer to the [TraceQL query editor documentation](./traceql-editor) to learn more about constructing queries using a code-editor-like experience.

@@ -113,8 +113,8 @@ You can also search for a trace ID by entering it into the query field.
### Service graph view
-Grafana’s **Service Graph** view uses metrics to display span request rates, error rates, and durations, as well as service graphs.
-Once the requirements are set up, this preconfigured view is immediately available.
+The **Service Graph** view uses metrics to display span request rates, error rates, and durations, as well as service graphs.
+After the requirements are set up, this preconfigured view is immediately available.
Using the service graph view, you can:
diff --git a/docs/sources/datasources/tempo/query-editor/traceql-editor.md b/docs/sources/datasources/tempo/query-editor/traceql-editor.md
index 7752a290229..cc5b38beaaa 100644
--- a/docs/sources/datasources/tempo/query-editor/traceql-editor.md
+++ b/docs/sources/datasources/tempo/query-editor/traceql-editor.md
@@ -12,7 +12,7 @@ labels:
- oss
menuTitle: Write TraceQL queries
title: Write TraceQL queries with the editor
-weight: 300
+weight: 400
refs:
explore:
- pattern: /docs/grafana/
@@ -41,4 +41,4 @@ refs:
[//]: # 'Shared content for the TraceQL query editor'
[//]: # 'This content is located in /docs/sources/shared/datasources/tempo-editor-traceql.md'
-{{< docs/shared source="grafana" lookup="datasources/tempo-editor-traceql.md" version="" >}}
+{{< docs/shared source="grafana" lookup="datasources/tempo-editor-traceql.md" version="" >}}
diff --git a/docs/sources/datasources/tempo/query-editor/traceql-search.md b/docs/sources/datasources/tempo/query-editor/traceql-search.md
index b885f1239d8..84ac0b396c4 100644
--- a/docs/sources/datasources/tempo/query-editor/traceql-search.md
+++ b/docs/sources/datasources/tempo/query-editor/traceql-search.md
@@ -56,4 +56,4 @@ To enable the TraceQL query builder in self-hosted Grafana through version 10.1,
[//]: # 'Shared content for the Search - TraceQL query builder'
-{{< docs/shared source="grafana" lookup="datasources/tempo-search-traceql.md" leveloffset="+1" version="" >}}
+{{< docs/shared source="grafana" lookup="datasources/tempo-search-traceql.md" leveloffset="+1" version="" >}}
diff --git a/docs/sources/datasources/tempo/query-editor/traceql-structure.md b/docs/sources/datasources/tempo/query-editor/traceql-structure.md
new file mode 100644
index 00000000000..b67d57cedf3
--- /dev/null
+++ b/docs/sources/datasources/tempo/query-editor/traceql-structure.md
@@ -0,0 +1,21 @@
+---
+description: Learn how to create TraceQL queries are structured.
+keywords:
+ - queries
+ - TraceQL
+labels:
+ products:
+ - cloud
+ - enterprise
+ - oss
+menuTitle: TraceQL query structure
+title: TraceQL query structure
+weight: 200
+---
+
+# TraceQL query structure
+
+[//]: # 'Shared content for best practices for traces'
+[//]: # 'This content is located in /tempo/docs/sources/shared/trace-structure.md'
+
+{{< docs/shared source="tempo" lookup="traceql-query-structure.md" version="" >}}
diff --git a/docs/sources/datasources/tempo/service-graph.md b/docs/sources/datasources/tempo/service-graph.md
index 0e6c1f8b657..59b1445f4f0 100644
--- a/docs/sources/datasources/tempo/service-graph.md
+++ b/docs/sources/datasources/tempo/service-graph.md
@@ -72,8 +72,8 @@ You use the Service Graph to detect performance issues; track increases in error
## Display the Service Graph
-1. [Configure Grafana Alloy](https://grafana.com/docs/tempo/latest/configuration/grafana-alloy/) or [Tempo or GET](https://grafana.com/docs/tempo/latest/metrics-generator/service_graphs/#tempo) to generate Service Graph data.
-1. Link a Prometheus data source in the Tempo data source's [Service Graph]({{< relref "./configure-tempo-data-source#configure-service-graph" >}}) settings.
+1. [Configure Grafana Alloy](https://grafana.com/docs/tempo//configuration/grafana-alloy/) or [Tempo or GET](https://grafana.com/docs/tempo//metrics-generator/service_graphs/#tempo) to generate Service Graph data.
+1. Link a Prometheus data source in the Tempo data source's [Service Graph](../configure-tempo-data-source#configure-service-graph) settings.
1. Navigate to [Explore](ref:explore).
1. Select the Tempo data source.
1. Select the **Service Graph** query type.
@@ -113,10 +113,10 @@ To open the Service Graph view:
1. Run the query.
1. _(Optional)_ Filter your results.
-{{% admonition type="note" %}}
+{{< admonition type="note" >}}
Grafana uses the `traces_spanmetrics_calls_total` metric to display the name, rate, and error rate columns, and `traces_spanmetrics_latency_bucket` to display the duration column.
These metrics must exist in your Prometheus data source.
-{{% /admonition %}}
+{{< /admonition >}}
To open a query in Prometheus with the span name of that row automatically set in the query, click a row in the **rate**, **error rate**, or **duration** columns.
diff --git a/docs/sources/datasources/tempo/traces-in-grafana/_index.md b/docs/sources/datasources/tempo/traces-in-grafana/_index.md
new file mode 100644
index 00000000000..c3f622bb57d
--- /dev/null
+++ b/docs/sources/datasources/tempo/traces-in-grafana/_index.md
@@ -0,0 +1,23 @@
+---
+description: Learn about how you can use tracing data in Grafana Cloud to query data,
+ generate metrics, and link your tracing data with logs, metrics, and profiles.
+keywords:
+ - Grafana
+ - traces
+ - tracing
+title: Use traces in Grafana
+weight: 275
+---
+
+# Use traces in Grafana
+
+Using traces, you can search for traces, generate metrics from spans, and link your tracing data with logs, metrics, and profiles.
+
+This page provides a summary of how you can use tracing data in Grafana.
+
+For general documentation on querying data sources in Grafana, refer to [Query and transform data](https://grafana.com/docs/grafana-cloud/visualizations/panels-visualizations/query-transform-data/).
+
+[//]: # 'Shared content for best practices for traces'
+[//]: # 'This content is located in /tempo/docs/sources/shared/tempo-in-grafana.md'
+
+{{< docs/shared source="tempo" lookup="tempo-in-grafana.md" version="" >}}
diff --git a/docs/sources/datasources/tempo/json-trace-file.md b/docs/sources/datasources/tempo/traces-in-grafana/json-trace-file.md
similarity index 82%
rename from docs/sources/datasources/tempo/json-trace-file.md
rename to docs/sources/datasources/tempo/traces-in-grafana/json-trace-file.md
index 0387eab883a..77b45011a2f 100644
--- a/docs/sources/datasources/tempo/json-trace-file.md
+++ b/docs/sources/datasources/tempo/traces-in-grafana/json-trace-file.md
@@ -12,7 +12,9 @@ labels:
- oss
menuTitle: Upload JSON trace file
title: Upload a JSON trace file
-weight: 400
+weight: 900
+aliases:
+ - ../json-trace-file/ # /docs/grafana/latest/datasources/tempo/json-trace-file
---
# Upload a JSON trace file
@@ -20,7 +22,15 @@ weight: 400
You can upload a JSON file that contains a single trace and visualize it.
If the file has multiple traces, Grafana visualizes the first trace.
-**To download a trace or Service Graph through the inspector:**
+To upload a trace file:
+
+1. Select **Explore** in Grafana.
+1. Select **Import trace** in the right corner.
+1. Upload your JSON trace file.
+
+## Download a trace or service graph
+
+To download a trace or Service Graph through the [Inspector panel](https://grafana.com/docs/grafana//explore/explore-inspector/):
1. Open the inspector.
1. Navigate to the **Data** tab.
diff --git a/docs/sources/datasources/tempo/link-trace-id.md b/docs/sources/datasources/tempo/traces-in-grafana/link-trace-id.md
similarity index 87%
rename from docs/sources/datasources/tempo/link-trace-id.md
rename to docs/sources/datasources/tempo/traces-in-grafana/link-trace-id.md
index d53496e3784..6570377bbc7 100644
--- a/docs/sources/datasources/tempo/link-trace-id.md
+++ b/docs/sources/datasources/tempo/traces-in-grafana/link-trace-id.md
@@ -12,7 +12,10 @@ labels:
- oss
menuTitle: Link to a trace ID
title: Link to a trace ID
-weight: 700
+weight: 800
+aliases:
+ - ../link-trace-id/ # /docs/grafana/latest/datasources/tempo/link-trace-id/
+
refs:
configure-grafana-feature-toggles:
- pattern: /docs/grafana/
@@ -69,10 +72,10 @@ You can link to Tempo traces from logs or metrics.
You can link to Tempo traces from logs in Loki, Elasticsearch, Splunk, and other logs data sources by configuring an internal link.
-To configure this feature, see the [Derived fields]({{< relref "../loki#configure-derived-fields" >}}) section of the Loki data source docs or the [Data links]({{< relref "../elasticsearch#data-links" >}}) section of the Elasticsearch or Splunk data source docs.
+To configure this feature, refer to the [Derived fields](../../../loki#configure-derived-fields) section of the Loki data source docs or the [Data links](../../../elasticsearch#data-links) section of the Elasticsearch or Splunk data source docs.
## Link to a trace ID from metrics
You can link to Tempo traces from metrics in Prometheus data sources by configuring an exemplar.
-To configure this feature, see the [introduction to exemplars](ref:exemplars) documentation.
+To configure this feature, refer to the [Exemplars](ref:exemplars) documentation.
diff --git a/docs/sources/datasources/zipkin/_index.md b/docs/sources/datasources/zipkin/_index.md
index 99047f46e58..e289b621819 100644
--- a/docs/sources/datasources/zipkin/_index.md
+++ b/docs/sources/datasources/zipkin/_index.md
@@ -339,10 +339,10 @@ To only show the spans you have matched, you can press the `Show matches only` t
You can link to Zipkin traces from logs in Loki, Elasticsearch, Splunk, and other logs data sources by configuring an internal link.
-To configure this feature, see the [Derived fields]({{< relref "../loki#configure-derived-fields" >}}) section of the Loki data source docs or the [Data links]({{< relref "../elasticsearch#data-links" >}}) section of the Elasticsearch or Splunk data source docs.
+To configure this feature, see the [Derived fields](../loki/#configure-derived-fields) section of the Loki data source docs or the [Data links](../elasticsearch/#data-links) section of the Elasticsearch or Splunk data source docs.
## Link to a trace ID from metrics
You can link to Zipkin traces from metrics in Prometheus data sources by configuring an exemplar.
-To configure this feature, see the [introduction to exemplars]({{< relref "docs/grafana/latest/fundamentals/exemplars" >}}) documentation.
+To configure this feature, see the [introduction to exemplars](../../fundamentals/exemplars/) documentation.
diff --git a/docs/sources/developers/angular_deprecation/_index.md b/docs/sources/developers/angular_deprecation/_index.md
index 7b596b88308..cdd8c172c5e 100644
--- a/docs/sources/developers/angular_deprecation/_index.md
+++ b/docs/sources/developers/angular_deprecation/_index.md
@@ -25,9 +25,9 @@ Warning messages are displayed if a dashboard depends on an a panel visualizatio
To avoid disruption:
-- Ensure that you are running the latest version of plugins by following this guide on [updating]({{< relref "../../administration/plugin-management/#update-a-plugin" >}}). Many panels and data sources have migrated from AngularJS.
-- If you are using legacy Core Grafana visualizations such as Graph or Table-old, migrate to their replacements using the provided [automatic migrations]({{< relref "./angular-plugins/#automatic-migration-of-plugins" >}}).
-- Review the [list of current Angular plugins]({{< relref "./angular-plugins/" >}}) to discover which Core and external plugins are impacted, and whether an update or alternative is required.
+- Ensure that you are running the latest version of plugins by following this guide on [updating](../../administration/plugin-management/#update-a-plugin). Many panels and data sources have migrated from AngularJS.
+- If you are using legacy Core Grafana visualizations such as Graph or Table-old, migrate to their replacements using the provided [automatic migrations](angular-plugins/#automatic-migration-of-plugins).
+- Review the [list of current Angular plugins](angular-plugins/) to discover which Core and external plugins are impacted, and whether an update or alternative is required.
## Why are we deprecating Angular support?
@@ -35,7 +35,7 @@ AngularJS is an old frontend framework whose active development stopped many yea
## When will Angular plugins stop working?
-In Grafana 11, which will be released in preview in April 2024 and generally available in May, we will change the default behavior of the [angular_support_enabled](https://github.com/grafana/grafana/blob/d61bcdf4ca5e69489e0067c56fbe7f0bfdf84ee4/conf/defaults.ini#L362) configuration parameter to turn off support for AngularJS based plugins. In case you still rely on [AngularJS-based plugins]({{< relref "./angular-plugins/" >}}) developed internally or by the community, you will need to enable this option to continue using them.
+In Grafana 11, which will be released in preview in April 2024 and generally available in May, we will change the default behavior of the [angular_support_enabled](https://github.com/grafana/grafana/blob/d61bcdf4ca5e69489e0067c56fbe7f0bfdf84ee4/conf/defaults.ini#L362) configuration parameter to turn off support for AngularJS based plugins. In case you still rely on [AngularJS-based plugins](angular-plugins/) developed internally or by the community, you will need to enable this option to continue using them.
New Grafana Cloud users will be unable to request for support to be added to their instance.
@@ -63,4 +63,4 @@ We encourage you to locate the repository of the corresponding plugin and create
- [Migrate Angular to React](https://grafana.com/developers/plugin-tools/migration-guides/angular-react/)
- [Build a panel plugin](https://grafana.com/tutorials/build-a-panel-plugin/)
- [Build a data source plugin](https://grafana.com/tutorials/build-a-data-source-plugin/)
-- [List of current Angular plugins]({{< relref "./angular-plugins/" >}})
+- [List of current Angular plugins](angular-plugins/)
diff --git a/docs/sources/developers/angular_deprecation/angular-plugins.md b/docs/sources/developers/angular_deprecation/angular-plugins.md
index d565cb5a2e1..bbb61da3c44 100644
--- a/docs/sources/developers/angular_deprecation/angular-plugins.md
+++ b/docs/sources/developers/angular_deprecation/angular-plugins.md
@@ -16,7 +16,7 @@ description: An annotated list of Grafana plugins using AngularJS.
# Plugins using AngularJS
-The use of AngularJS in Grafana has been [deprecated]({{< relref "../angular_deprecation" >}}) in favor of React. Support for AngularJS will be turned off by default in Grafana 11.
+The use of AngularJS in Grafana has been [deprecated](../) in favor of React. Support for AngularJS will be turned off by default in Grafana 11.
This page explains how Grafana users might be impacted by the removal of Angular support based on plugins dependent on this legacy framework. You will also see if there is a migration option available for a given plugin.
@@ -30,8 +30,8 @@ Refer to the [table below](#angularjs-based-plugins) and take the appropriate ac
- Consider the advice on whether to update, migrate to a listed alternative, or explore the Grafana plugins [catalog](/grafana/plugins) to find the most suitable option for your use case.
- Use our [detect-angular-dashboards](https://github.com/grafana/detect-angular-dashboards) open source tooling to list dashboards which have a dependency on Angular plugins.
-- Check your Grafana instances for usage of these plugins. Refer to the documentation on [browsing installed plugins]({{< relref "../../administration/plugin-management/#browse-plugins" >}}).
-- Customers of Grafana Enterprise and users of Grafana Cloud can also leverage [usage insights]({{< relref "../../dashboards/assess-dashboard-usage/" >}}) to prioritize any migration efforts.
+- Check your Grafana instances for usage of these plugins. Refer to the documentation on [browsing installed plugins](../../../administration/plugin-management/#browse-plugins).
+- Customers of Grafana Enterprise and users of Grafana Cloud can also leverage [usage insights](../../../dashboards/assess-dashboard-usage/) to prioritize any migration efforts.
- Review the plugin source repositories to add your support to any migration issues or consider forking the repo.
{{% admonition type="note" %}}
@@ -64,144 +64,144 @@ A dashboard must still be saved with the new plugin ID to persist the change.
# AngularJS-based plugins
-This table lists plugins which we have detected as having a dependency on AngularJS. For alternatives, consider included [Visualizations]({{< relref "../../panels-visualizations/visualizations" >}}) and [Data sources]({{< relref "../../datasources" >}}), as well as external plugins from the [catalog](/grafana/plugins).
+This table lists plugins which we have detected as having a dependency on AngularJS. For alternatives, consider included [Visualizations](../../../panels-visualizations/visualizations/) and [Data sources](../../../datasources/), as well as external plugins from the [catalog](/grafana/plugins).
-| Plugin ID | Name | Action |
-| ----------------------------------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| grafana-worldmap-panel | Worldmap Panel | Migrate - [Geomap]({{< relref "../../panels-visualizations/visualizations/geomap" >}}) (core) replaced Worldmap - Note this should migrate when Angular is disabled. |
-| natel-discrete-panel | Discrete | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
-| vonage-status-panel | Status Panel | Migrate - Consider [Stat]({{< relref "../../panels-visualizations/visualizations/stat" >}}) (core) or [Polystat](https://grafana.com/grafana/plugins/grafana-polystat-panel/) as potential alternatives. |
-| grafana-simple-json-datasource | SimpleJson | Migrate - Consider [Infinity](https://grafana.com/grafana/plugins/yesoreyeram-infinity-datasource/) as a potential alternative. |
-| natel-plotly-panel | Plotly | Migrate - Consider alternative [nline-plotlyjs-panel](https://grafana.com/grafana/plugins/nline-plotlyjs-panel/) plugin. |
-| agenty-flowcharting-panel | FlowCharting | Migrate - Consider [Canvas]({{< relref "../../panels-visualizations/visualizations/canvas" >}}) (core) or [Diagram](https://grafana.com/grafana/plugins/jdbranham-diagram-panel/) as potential alternatives. |
-| camptocamp-prometheus-alertmanager-datasource | Prometheus AlertManager | Update - Note the minimum version for React is 2.0.0. |
-| briangann-gauge-panel | D3 Gauge | Update - Note the minimum version for React is 2.0.0. We recommend the latest. |
-| yesoreyeram-boomtable-panel | Boom Table | Migrate - Consider [Table]({{< relref "../../panels-visualizations/visualizations/table" >}}) (core) and [transformations]({{< relref "../../panels-visualizations/query-transform-data/transform-data/" >}}) as appropriate. |
-| briangann-datatable-panel | Datatable Panel | Wait - New version with React migration is planned. |
-| flant-statusmap-panel | Statusmap | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
-| michaeldmoore-multistat-panel | Multistat | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
-| pr0ps-trackmap-panel | TrackMap | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
-| snuids-trafficlights-panel | Traffic Lights | Migrate - Consider [Traffic Light](https://grafana.com/grafana/plugins/heywesty-trafficlight-panel/) as a potential alternative. |
-| vertamedia-clickhouse-datasource | Altinity plugin for ClickHouse | Update - Note the minimum version for React is 3.0.0. |
-| petrslavotinek-carpetplot-panel | Carpet plot | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
-| ryantxu-ajax-panel | AJAX | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
-| michaeldmoore-annunciator-panel | Annunciator | Migrate - Consider [Stat]({{< relref "../../panels-visualizations/visualizations/stat" >}}) (core). |
-| marcuscalidus-svg-panel | SVG | Migrate - Consider alternatives such as [Canvas]({{< relref "../../panels-visualizations/visualizations/canvas" >}}) (core), [Colored SVG](https://grafana.com/grafana/plugins/snuids-svg-panel/), or others. |
-| neocat-cal-heatmap-panel | Cal-HeatMap | Migrate - Consider [Heatmap]({{< relref "../../panels-visualizations/visualizations/heatmap" >}}) (core) visualization. |
-| blackmirror1-singlestat-math-panel | Singlestat Math | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
-| scadavis-synoptic-panel | SCADAvis Synoptic Panel | Update - Note the minimum version for React is 2.0. |
-| farski-blendstat-panel | Blendstat | Migrate - Consider [Stat]({{< relref "../../panels-visualizations/visualizations/stat" >}}) (core) and [transformations]({{< relref "../../panels-visualizations/query-transform-data/transform-data/" >}}) as appropriate. |
-| savantly-heatmap-panel | Heatmap | Migrate - Consider [Heatmap]({{< relref "../../panels-visualizations/visualizations/heatmap" >}}) (core) visualization. |
-| mtanda-histogram-panel | Histogram | Migrate - Consider included [Histogram]({{< relref "../../panels-visualizations/visualizations/histogram" >}}) visualization. |
-| snuids-radar-panel | Radar Graph | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
-| fatcloud-windrose-panel | WindRose | Migrate - Consider alternative [Operator Windrose](https://grafana.com/grafana/plugins/operato-windrose-panel/) plugin. |
-| bessler-pictureit-panel | PictureIt | Migrate - Consider alternative [ePict](https://grafana.com/grafana/plugins/larona-epict-panel/) plugin. |
-| digrich-bubblechart-panel | Bubble Chart | Update - Note the minimum version for React is 2.0.1. We recommend the latest. |
-| corpglory-progresslist-panel | Progress List | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
-| aidanmountford-html-panel | HTML | Migrate - Consider alternatives such as [Text]({{< relref "../../panels-visualizations/visualizations/text" >}}) (core), [HTML](https://grafana.com/grafana/plugins/gapit-htmlgraphics-panel), or others. |
-| fifemon-graphql-datasource | GraphQL Data Source | Wait - Removal of AngularJS is planned. Consider [Infinity](https://grafana.com/grafana/plugins/yesoreyeram-infinity-datasource/) plugin as alternative. |
-| goshposh-metaqueries-datasource | MetaQueries | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| mxswat-separator-panel | Separator | Migrate - Consider alternative [Text]({{< relref "../../panels-visualizations/visualizations/text" >}}) panel (core) which can be empty and used as a separator. |
-| natel-influx-admin-panel | Influx Admin | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| doitintl-bigquery-datasource | Google BigQuery | Migrate - Consider [Grafana Big Query](https://grafana.com/grafana/plugins/grafana-bigquery-datasource/) plugin. |
-| satellogic-3d-globe-panel | 3D Globe Panel | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
-| foursquare-clouderamanager-datasource | Cloudera Manager | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| grafana-splunk-datasource | Splunk | Update - Note the minimum version for React is 4.1.0. We recommend the latest. |
-| grafana-singlestat-panel | Singlestat | Migrate - Consider [Stat]({{< relref "../../panels-visualizations/visualizations/stat" >}}) panel (core). |
-| blackmirror1-statusbygroup-panel | Status By Group Panel | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
-| novalabs-annotations-panel | Annotation Panel | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
-| jasonlashua-prtg-datasource | PRTG | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| ryantxu-annolist-panel | Annotation List | Migrate - Consider [annotations list]({{< relref "../../panels-visualizations/visualizations/annotations" >}}) (core). |
-| cloudflare-app | Cloudflare Grafana App | Migrate - Consider using the [Cloudflare Dashboard](https://dash.cloudflare.com/?to=/:account/:zone/analytics/dns) or [DNS Analytics API](https://developers.cloudflare.com/api/operations/dns-analytics-table). |
-| smartmakers-trafficlight-panel | TrafficLight | Migrate - Consider [Traffic Light](https://grafana.com/grafana/plugins/heywesty-trafficlight-panel/) as a potential alternative. |
-| zuburqan-parity-report-panel | Parity Report | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
-| citilogics-geoloop-panel | GeoLoop | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
-| xginn8-pagerduty-datasource | Pagerduty | Wait - We are developing an Enterprise plugin for Pagerduty targeted for availability in Q1 2024. Note that all roadmap items are subject to change. |
-| gretamosa-topology-panel | Topology Panel | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
-| fzakaria-simple-annotations-datasource | Simple Annotations | Migrate - Check for annotations support within your data sources to remove dependency on this plugin. |
-| oci-metrics-datasource | Oracle Cloud Infrastructure Metrics | Update - Note the minimum version for React is 5.0.0. |
-| abhisant-druid-datasource | Druid | Migrate - Migrate to replacement [Druid](https://grafana.com/grafana/plugins/grafadruid-druid-datasource/) plugin. |
-| devopsprodigy-kubegraf-app | DevOpsProdigy KubeGraf | Migrate - Consider [Grafana Kubernetes Monitoring](https://grafana.com/solutions/kubernetes/) (Grafana Cloud only). |
-| mtanda-heatmap-epoch-panel | HeatmapEpoch | Migrate - Consider [Heatmap]({{< relref "../../panels-visualizations/visualizations/heatmap" >}}) (core) visualization. |
-| alexandra-trackmap-panel | Track Map | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
-| gnocchixyz-gnocchi-datasource | Gnocchi | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| tencentcloud-monitor-app | Tencent Cloud Monitor | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| andig-darksky-datasource | DarkSky | Remove - Note that support for the DarkSky API was ended by Apple in March 2023. |
-| mtanda-google-calendar-datasource | GoogleCalendar | Wait - Migration to React is planned. |
-| ntop-ntopng-datasource | ntopng | Migrate - Consider [InfluxDB]({{< relref "../../datasources/influxdb/" >}}) (core), with additional guidance available [here](https://www.ntop.org/guides/ntopng/basic_concepts/timeseries.html#influxdb-driver). |
-| ayoungprogrammer-finance-datasource | Finance | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| grafana-kairosdb-datasource | KairosDB | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| fastweb-openfalcon-datasource | Open-Falcon | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| praj-ams-datasource | Ambari Metrics | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| monasca-datasource | Monasca | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| grafana-strava-datasource | Strava | Update - Note the minimum version for React is 1.6.0. We recommend the latest. |
-| gridprotectionalliance-osisoftpi-datasource | OSIsoft-PI | Update - Note the minimum version for React is 4.0.0. We recommend the latest. |
-| monitoringartist-monitoringart-datasource | Monitoring Art | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
-| hawkular-datasource | Hawkular | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| ovh-warp10-datasource | Warp 10 | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| natel-usgs-datasource | USGS Water Services | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| radensolutions-netxms-datasource | NetXMS | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| ibm-apm-datasource | IBM APM | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| cognitedata-datasource | Cognite Data Fusion | Update - Note the minimum version for React is 4.0.0. We recommend the latest. |
-| linksmart-sensorthings-datasource | LinkSmart SensorThings | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| pue-solr-datasource | Solr | Migrate - Consider this [guidance](https://solr.apache.org/guide/solr/latest/deployment-guide/monitoring-with-prometheus-and-grafana.html) on using solr-exporter for prometheus. |
-| paytm-kapacitor-datasource | KapacitorSimpleJson | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| oci-logs-datasource | Oracle Cloud Infrastructure Logs | Update - Note the minimum version for React is 4.0.0. |
-| gridprotectionalliance-openhistorian-datasource | openHistorian | Wait - Note that new version with React migration is planned. |
-| devicehive-devicehive-datasource | DeviceHive | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| rackerlabs-blueflood-datasource | Blueflood | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| udoprog-heroic-datasource | Heroic | Migrate - Note that Heroic DB has been discontinued. |
-| akumuli-datasource | Akumuli | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| bmchelix-ade-datasource | BMC Helix | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| sidewinder-datasource | Sidewinder | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| linksmart-hds-datasource | LinkSmart HDS Datasource | Migrate - browse included data sources and plugins catalog for potential alternatives. |
-| skydive-datasource | Skydive | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| quasardb-datasource | QuasarDB | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| spotify-heroic-datasource | Heroic | Migrate - Note that Heroic DB has been discontinued. |
-| grafana-es-open-distro-datasource | Open Distro for Elasticsearch | Migrate - Note that [OpenSearch](https://grafana.com/grafana/plugins/grafana-opensearch-datasource/) replaced Open Distro for Elasticseach. |
-| humio-datasource | Humio | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| yeya24-chaosmesh-datasource | Chaos Mesh | Migrate - Note that plugin was replaced by [chaosmeshorg-datasource](https://grafana.com/grafana/plugins/chaosmeshorg-datasource/). |
-| kentik-connect-app | Kentik Connect Pro | Update - Note the minimum version for React is 1.7.0. |
-| chaosmeshorg-datasource | Chaos Mesh | Update - Note the minimum version for React is 3.0.0. |
-| aquaqanalytics-kdbadaptor-datasource | kdb+ | Migrate - Note that [kdb+ backend](https://grafana.com/grafana/plugins/aquaqanalytics-kdbbackend-datasource) replaced kdb.+. |
-| alexanderzobnin-zabbix-app | Zabbix | Update - Note the minimum version for React is 4.3.0. We recommend the latest. Recently brought under Grafana signature. |
-| bosun-app | Bosun | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| belugacdn-app | BelugaCDN | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| grafana-azure-data-explorer-datasource | Azure Data Explorer Datasource | Update - The minimum supported version is 3.5.1. We recommend the latest. |
-| ddurieux-glpi-app | glpi | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| fetzerch-sunandmoon-datasource | Sun and Moon | Update - Note the minimum version for React is 0.3.0. |
-| grafana-clock-panel | Clock | Update - Note the minimum version for React is 1.1.0. We recommend the latest. |
-| grafana-github-datasource | GitHub | Update - Note the minimum version for React is 1.3.3. We recommend the latest. |
-| grafana-datadog-datasource | Datadog | Update - Note the minimum version for React is 3.0.0. We recommend the latest. |
-| grafana-gitlab-datasource | Gitlab | Update - Note the minimum version for React is 1.1.0. We recommend the latest. |
-| grafana-iot-twinmaker-app | AWS IoT TwinMaker App | Update - Note the minimum version for React is 1.6.3. We recommend the latest. |
-| grafana-newrelic-datasource | New Relic | Update - Note the minimum version for React is 3.0.0. We recommend the latest. |
-| grafana-opensearch-datasource | Opensearch | Update - Note the minimum version for React is 2.0.0. We recommend the latest. |
-| grafana-oracle-datasource | Oracle | Update - Note the minimum version for React is 2.0.6. We recommend the latest. |
-| grafana-piechart-panel | Pie Chart | Migrate - Note that [Pie Chart]({{< relref "../../panels-visualizations/visualizations/pie-chart" >}}) (core) replaced Pie Chart. |
-| grafana-polystat-panel | Polystat | Update - Note the minimum version for React is 2.0.0. We recommend the latest. |
-| grafana-servicenow-datasource | ServiceNow | Update - Note the minimum version for React is 2.0.2. We recommend the latest. |
-| grafana-synthetic-monitoring-app | Synthetic Monitoring | Update - Note the minimum version for React is 0.7.3. We recommend the latest. |
-| grafana-wavefront-datasource | Wavefront | Update - Note the minimum version for React is 2.0.0. We recommend the latest. |
-| hadesarchitect-cassandra-datasource | Apache Cassandra | Update - Note the minimum version for React is 2.1.1. We recommend the latest. |
-| instana-datasource | Instana | Update - Note the minimum version for React is 3.0.0. We recommend the latest. |
-| jdbranham-diagram-panel | Diagram | Update - Note the minimum version for React is 1.7.1. We recommend the latest. |
-| larona-epict-panel | ePict | Update - Note the minimum version for React is 2.0.0. We recommend the latest. |
-| moogsoft-aiops-app | Moogsoft AIOps | Update - Note the minimum version for React is 9.0.0. |
-| opennms-helm-app | OpenNMS Helm | Migrate - Note that [OpenNMS Plugin for Grafana](https://grafana.com/grafana/plugins/opennms-opennms-app/) replaced OpenNMS Helm. |
-| percona-percona-app | Percona | Migrate - Consider use of [Percona dashboards](https://github.com/percona/grafana-dashboards/). |
-| novatec-sdg-panel | Service Dependency Graph | Update - Note the minimum version for React is 4.0.3. |
-| pierosavi-imageit-panel | ImageIt | Migrate - Consider [ePict](https://grafana.com/grafana/plugins/larona-epict-panel/) or browse plugins catalog for potential alternatives. |
-| redis-app | Redis Application | Update - Note the minimum version for React is 1.2.0. We recommend the latest. |
-| sbueringer-consul-datasource | Consul | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| simpod-json-datasource | JSON | Update - Note the minimum version for React is 0.3.0. We recommend the latest. |
-| singlestat | Singlestat | Migrate - Note that [Stat]({{< relref "../../panels-visualizations/visualizations/stat" >}}) (core) replaced Singlestat. |
-| sni-pnp-datasource | PNP | Update - Note the minimum version for React is 2.0.0. We recommend the latest. |
-| sni-thruk-datasource | Thruk | Update - Note the minimum version for React is 2.0.0. We recommend the latest. |
-| stagemonitor-elasticsearch-app | stagemonitor Elasticsearch | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| tdengine-datasource | TDengine Datasource | Update - Note the minimum version for React is 3.3.0. We recommend the latest. |
-| vertica-grafana-datasource | Vertica | Update - Note the minimum version for React is 2.0.0. We recommend the latest. |
-| voxter-app | Voxter VoIP Platform Metrics | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
-| graph | Graph (old) | Migrate - Note that this is replaced by [Time Series]({{< relref "../../panels-visualizations/visualizations/time-series" >}}) (core) - This plugin should migrate when Angular is disabled. Also consider Bar Chart or Histogram if appropriate. |
-| table-old | Table (old) | Migrate - Note that this is replaced by [Table]({{< relref "../../panels-visualizations/visualizations/table" >}}) (core) - This plugin should migrate when AngularJS is disabled. |
-| shorelinesoftware-shoreline-datasource | Shoreline Data Source | Update - Note the minimum version for React is 1.2.1. We recommend the latest. |
+| Plugin ID | Name | Action |
+| ----------------------------------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| grafana-worldmap-panel | Worldmap Panel | Migrate - [Geomap](../../../panels-visualizations/visualizations/geomap/) (core) replaced Worldmap - Note this should migrate when Angular is disabled. |
+| natel-discrete-panel | Discrete | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
+| vonage-status-panel | Status Panel | Migrate - Consider [Stat](../../../panels-visualizations/visualizations/stat/) (core) or [Polystat](https://grafana.com/grafana/plugins/grafana-polystat-panel/) as potential alternatives. |
+| grafana-simple-json-datasource | SimpleJson | Migrate - Consider [Infinity](https://grafana.com/grafana/plugins/yesoreyeram-infinity-datasource/) as a potential alternative. |
+| natel-plotly-panel | Plotly | Migrate - Consider alternative [nline-plotlyjs-panel](https://grafana.com/grafana/plugins/nline-plotlyjs-panel/) plugin. |
+| agenty-flowcharting-panel | FlowCharting | Migrate - Consider [Canvas](../../../panels-visualizations/visualizations/canvas/) (core) or [Diagram](https://grafana.com/grafana/plugins/jdbranham-diagram-panel/) as potential alternatives. |
+| camptocamp-prometheus-alertmanager-datasource | Prometheus AlertManager | Update - Note the minimum version for React is 2.0.0. |
+| briangann-gauge-panel | D3 Gauge | Update - Note the minimum version for React is 2.0.0. We recommend the latest. |
+| yesoreyeram-boomtable-panel | Boom Table | Migrate - Consider [Table](../../../panels-visualizations/visualizations/table/) (core) and [transformations](../../../panels-visualizations/query-transform-data/transform-data/) as appropriate. |
+| briangann-datatable-panel | Datatable Panel | Wait - New version with React migration is planned. |
+| flant-statusmap-panel | Statusmap | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
+| michaeldmoore-multistat-panel | Multistat | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
+| pr0ps-trackmap-panel | TrackMap | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
+| snuids-trafficlights-panel | Traffic Lights | Migrate - Consider [Traffic Light](https://grafana.com/grafana/plugins/heywesty-trafficlight-panel/) as a potential alternative. |
+| vertamedia-clickhouse-datasource | Altinity plugin for ClickHouse | Update - Note the minimum version for React is 3.0.0. |
+| petrslavotinek-carpetplot-panel | Carpet plot | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
+| ryantxu-ajax-panel | AJAX | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
+| michaeldmoore-annunciator-panel | Annunciator | Migrate - Consider [Stat](../../../panels-visualizations/visualizations/stat/) (core). |
+| marcuscalidus-svg-panel | SVG | Migrate - Consider alternatives such as [Canvas](../../../panels-visualizations/visualizations/canvas/) (core), [Colored SVG](https://grafana.com/grafana/plugins/snuids-svg-panel/), or others. |
+| neocat-cal-heatmap-panel | Cal-HeatMap | Migrate - Consider [Heatmap](../../../panels-visualizations/visualizations/heatmap/) (core) visualization. |
+| blackmirror1-singlestat-math-panel | Singlestat Math | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
+| scadavis-synoptic-panel | SCADAvis Synoptic Panel | Update - Note the minimum version for React is 2.0. |
+| farski-blendstat-panel | Blendstat | Migrate - Consider [Stat](../../../panels-visualizations/visualizations/stat/) (core) and [transformations](../../../panels-visualizations/query-transform-data/transform-data/) as appropriate. |
+| savantly-heatmap-panel | Heatmap | Migrate - Consider [Heatmap](../../../panels-visualizations/visualizations/heatmap/) (core) visualization. |
+| mtanda-histogram-panel | Histogram | Migrate - Consider included [Histogram](../../../panels-visualizations/visualizations/histogram/) visualization. |
+| snuids-radar-panel | Radar Graph | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
+| fatcloud-windrose-panel | WindRose | Migrate - Consider alternative [Operator Windrose](https://grafana.com/grafana/plugins/operato-windrose-panel/) plugin. |
+| bessler-pictureit-panel | PictureIt | Migrate - Consider alternative [ePict](https://grafana.com/grafana/plugins/larona-epict-panel/) plugin. |
+| digrich-bubblechart-panel | Bubble Chart | Update - Note the minimum version for React is 2.0.1. We recommend the latest. |
+| corpglory-progresslist-panel | Progress List | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
+| aidanmountford-html-panel | HTML | Migrate - Consider alternatives such as [Text](../../../panels-visualizations/visualizations/text/) (core), [HTML](https://grafana.com/grafana/plugins/gapit-htmlgraphics-panel), or others. |
+| fifemon-graphql-datasource | GraphQL Data Source | Wait - Removal of AngularJS is planned. Consider [Infinity](https://grafana.com/grafana/plugins/yesoreyeram-infinity-datasource/) plugin as alternative. |
+| goshposh-metaqueries-datasource | MetaQueries | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| mxswat-separator-panel | Separator | Migrate - Consider alternative [Text](../../../panels-visualizations/visualizations/text/) panel (core) which can be empty and used as a separator. |
+| natel-influx-admin-panel | Influx Admin | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| doitintl-bigquery-datasource | Google BigQuery | Migrate - Consider [Grafana Big Query](https://grafana.com/grafana/plugins/grafana-bigquery-datasource/) plugin. |
+| satellogic-3d-globe-panel | 3D Globe Panel | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
+| foursquare-clouderamanager-datasource | Cloudera Manager | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| grafana-splunk-datasource | Splunk | Update - Note the minimum version for React is 4.1.0. We recommend the latest. |
+| grafana-singlestat-panel | Singlestat | Migrate - Consider [Stat](../../../panels-visualizations/visualizations/stat/) panel (core). |
+| blackmirror1-statusbygroup-panel | Status By Group Panel | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
+| novalabs-annotations-panel | Annotation Panel | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
+| jasonlashua-prtg-datasource | PRTG | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| ryantxu-annolist-panel | Annotation List | Migrate - Consider [annotations list](../../../panels-visualizations/visualizations/annotations/) (core). |
+| cloudflare-app | Cloudflare Grafana App | Migrate - Consider using the [Cloudflare Dashboard](https://dash.cloudflare.com/?to=/:account/:zone/analytics/dns) or [DNS Analytics API](https://developers.cloudflare.com/api/operations/dns-analytics-table). |
+| smartmakers-trafficlight-panel | TrafficLight | Migrate - Consider [Traffic Light](https://grafana.com/grafana/plugins/heywesty-trafficlight-panel/) as a potential alternative. |
+| zuburqan-parity-report-panel | Parity Report | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
+| citilogics-geoloop-panel | GeoLoop | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
+| xginn8-pagerduty-datasource | Pagerduty | Wait - We are developing an Enterprise plugin for Pagerduty targeted for availability in Q1 2024. Note that all roadmap items are subject to change. |
+| gretamosa-topology-panel | Topology Panel | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
+| fzakaria-simple-annotations-datasource | Simple Annotations | Migrate - Check for annotations support within your data sources to remove dependency on this plugin. |
+| oci-metrics-datasource | Oracle Cloud Infrastructure Metrics | Update - Note the minimum version for React is 5.0.0. |
+| abhisant-druid-datasource | Druid | Migrate - Migrate to replacement [Druid](https://grafana.com/grafana/plugins/grafadruid-druid-datasource/) plugin. |
+| devopsprodigy-kubegraf-app | DevOpsProdigy KubeGraf | Migrate - Consider [Grafana Kubernetes Monitoring](https://grafana.com/solutions/kubernetes/) (Grafana Cloud only). |
+| mtanda-heatmap-epoch-panel | HeatmapEpoch | Migrate - Consider [Heatmap](../../../panels-visualizations/visualizations/heatmap/) (core) visualization. |
+| alexandra-trackmap-panel | Track Map | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
+| gnocchixyz-gnocchi-datasource | Gnocchi | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| tencentcloud-monitor-app | Tencent Cloud Monitor | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| andig-darksky-datasource | DarkSky | Remove - Note that support for the DarkSky API was ended by Apple in March 2023. |
+| mtanda-google-calendar-datasource | GoogleCalendar | Wait - Migration to React is planned. |
+| ntop-ntopng-datasource | ntopng | Migrate - Consider [InfluxDB](../../../datasources/influxdb/) (core), with additional guidance available [here](https://www.ntop.org/guides/ntopng/basic_concepts/timeseries.html#influxdb-driver). |
+| ayoungprogrammer-finance-datasource | Finance | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| grafana-kairosdb-datasource | KairosDB | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| fastweb-openfalcon-datasource | Open-Falcon | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| praj-ams-datasource | Ambari Metrics | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| monasca-datasource | Monasca | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| grafana-strava-datasource | Strava | Update - Note the minimum version for React is 1.6.0. We recommend the latest. |
+| gridprotectionalliance-osisoftpi-datasource | OSIsoft-PI | Update - Note the minimum version for React is 4.0.0. We recommend the latest. |
+| monitoringartist-monitoringart-datasource | Monitoring Art | Migrate - Browse included visualizations and plugins catalog for potential alternatives. |
+| hawkular-datasource | Hawkular | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| ovh-warp10-datasource | Warp 10 | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| natel-usgs-datasource | USGS Water Services | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| radensolutions-netxms-datasource | NetXMS | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| ibm-apm-datasource | IBM APM | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| cognitedata-datasource | Cognite Data Fusion | Update - Note the minimum version for React is 4.0.0. We recommend the latest. |
+| linksmart-sensorthings-datasource | LinkSmart SensorThings | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| pue-solr-datasource | Solr | Migrate - Consider this [guidance](https://solr.apache.org/guide/solr/latest/deployment-guide/monitoring-with-prometheus-and-grafana.html) on using solr-exporter for prometheus. |
+| paytm-kapacitor-datasource | KapacitorSimpleJson | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| oci-logs-datasource | Oracle Cloud Infrastructure Logs | Update - Note the minimum version for React is 4.0.0. |
+| gridprotectionalliance-openhistorian-datasource | openHistorian | Wait - Note that new version with React migration is planned. |
+| devicehive-devicehive-datasource | DeviceHive | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| rackerlabs-blueflood-datasource | Blueflood | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| udoprog-heroic-datasource | Heroic | Migrate - Note that Heroic DB has been discontinued. |
+| akumuli-datasource | Akumuli | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| bmchelix-ade-datasource | BMC Helix | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| sidewinder-datasource | Sidewinder | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| linksmart-hds-datasource | LinkSmart HDS Datasource | Migrate - browse included data sources and plugins catalog for potential alternatives. |
+| skydive-datasource | Skydive | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| quasardb-datasource | QuasarDB | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| spotify-heroic-datasource | Heroic | Migrate - Note that Heroic DB has been discontinued. |
+| grafana-es-open-distro-datasource | Open Distro for Elasticsearch | Migrate - Note that [OpenSearch](https://grafana.com/grafana/plugins/grafana-opensearch-datasource/) replaced Open Distro for Elasticseach. |
+| humio-datasource | Humio | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| yeya24-chaosmesh-datasource | Chaos Mesh | Migrate - Note that plugin was replaced by [chaosmeshorg-datasource](https://grafana.com/grafana/plugins/chaosmeshorg-datasource/). |
+| kentik-connect-app | Kentik Connect Pro | Update - Note the minimum version for React is 1.7.0. |
+| chaosmeshorg-datasource | Chaos Mesh | Update - Note the minimum version for React is 3.0.0. |
+| aquaqanalytics-kdbadaptor-datasource | kdb+ | Migrate - Note that [kdb+ backend](https://grafana.com/grafana/plugins/aquaqanalytics-kdbbackend-datasource) replaced kdb.+. |
+| alexanderzobnin-zabbix-app | Zabbix | Update - Note the minimum version for React is 4.3.0. We recommend the latest. Recently brought under Grafana signature. |
+| bosun-app | Bosun | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| belugacdn-app | BelugaCDN | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| grafana-azure-data-explorer-datasource | Azure Data Explorer Datasource | Update - The minimum supported version is 3.5.1. We recommend the latest. |
+| ddurieux-glpi-app | glpi | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| fetzerch-sunandmoon-datasource | Sun and Moon | Update - Note the minimum version for React is 0.3.0. |
+| grafana-clock-panel | Clock | Update - Note the minimum version for React is 1.1.0. We recommend the latest. |
+| grafana-github-datasource | GitHub | Update - Note the minimum version for React is 1.3.3. We recommend the latest. |
+| grafana-datadog-datasource | Datadog | Update - Note the minimum version for React is 3.0.0. We recommend the latest. |
+| grafana-gitlab-datasource | Gitlab | Update - Note the minimum version for React is 1.1.0. We recommend the latest. |
+| grafana-iot-twinmaker-app | AWS IoT TwinMaker App | Update - Note the minimum version for React is 1.6.3. We recommend the latest. |
+| grafana-newrelic-datasource | New Relic | Update - Note the minimum version for React is 3.0.0. We recommend the latest. |
+| grafana-opensearch-datasource | Opensearch | Update - Note the minimum version for React is 2.0.0. We recommend the latest. |
+| grafana-oracle-datasource | Oracle | Update - Note the minimum version for React is 2.0.6. We recommend the latest. |
+| grafana-piechart-panel | Pie Chart | Migrate - Note that [Pie Chart](../../../panels-visualizations/visualizations/pie-chart/) (core) replaced Pie Chart. |
+| grafana-polystat-panel | Polystat | Update - Note the minimum version for React is 2.0.0. We recommend the latest. |
+| grafana-servicenow-datasource | ServiceNow | Update - Note the minimum version for React is 2.0.2. We recommend the latest. |
+| grafana-synthetic-monitoring-app | Synthetic Monitoring | Update - Note the minimum version for React is 0.7.3. We recommend the latest. |
+| grafana-wavefront-datasource | Wavefront | Update - Note the minimum version for React is 2.0.0. We recommend the latest. |
+| hadesarchitect-cassandra-datasource | Apache Cassandra | Update - Note the minimum version for React is 2.1.1. We recommend the latest. |
+| instana-datasource | Instana | Update - Note the minimum version for React is 3.0.0. We recommend the latest. |
+| jdbranham-diagram-panel | Diagram | Update - Note the minimum version for React is 1.7.1. We recommend the latest. |
+| larona-epict-panel | ePict | Update - Note the minimum version for React is 2.0.0. We recommend the latest. |
+| moogsoft-aiops-app | Moogsoft AIOps | Update - Note the minimum version for React is 9.0.0. |
+| opennms-helm-app | OpenNMS Helm | Migrate - Note that [OpenNMS Plugin for Grafana](https://grafana.com/grafana/plugins/opennms-opennms-app/) replaced OpenNMS Helm. |
+| percona-percona-app | Percona | Migrate - Consider use of [Percona dashboards](https://github.com/percona/grafana-dashboards/). |
+| novatec-sdg-panel | Service Dependency Graph | Update - Note the minimum version for React is 4.0.3. |
+| pierosavi-imageit-panel | ImageIt | Migrate - Consider [ePict](https://grafana.com/grafana/plugins/larona-epict-panel/) or browse plugins catalog for potential alternatives. |
+| redis-app | Redis Application | Update - Note the minimum version for React is 1.2.0. We recommend the latest. |
+| sbueringer-consul-datasource | Consul | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| simpod-json-datasource | JSON | Update - Note the minimum version for React is 0.3.0. We recommend the latest. |
+| singlestat | Singlestat | Migrate - Note that [Stat](../../../panels-visualizations/visualizations/stat/) (core) replaced Singlestat. |
+| sni-pnp-datasource | PNP | Update - Note the minimum version for React is 2.0.0. We recommend the latest. |
+| sni-thruk-datasource | Thruk | Update - Note the minimum version for React is 2.0.0. We recommend the latest. |
+| stagemonitor-elasticsearch-app | stagemonitor Elasticsearch | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| tdengine-datasource | TDengine Datasource | Update - Note the minimum version for React is 3.3.0. We recommend the latest. |
+| vertica-grafana-datasource | Vertica | Update - Note the minimum version for React is 2.0.0. We recommend the latest. |
+| voxter-app | Voxter VoIP Platform Metrics | Migrate - Browse included data sources and plugins catalog for potential alternatives. |
+| graph | Graph (old) | Migrate - Note that this is replaced by [Time Series](../../../panels-visualizations/visualizations/time-series/) (core) - This plugin should migrate when Angular is disabled. Also consider Bar Chart or Histogram if appropriate. |
+| table-old | Table (old) | Migrate - Note that this is replaced by [Table](../../../panels-visualizations/visualizations/table/) (core) - This plugin should migrate when AngularJS is disabled. |
+| shorelinesoftware-shoreline-datasource | Shoreline Data Source | Update - Note the minimum version for React is 1.2.1. We recommend the latest. |
diff --git a/docs/sources/developers/http_api/_index.md b/docs/sources/developers/http_api/_index.md
index 13f1ca5aac9..8889f1670c1 100644
--- a/docs/sources/developers/http_api/_index.md
+++ b/docs/sources/developers/http_api/_index.md
@@ -49,44 +49,44 @@ Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
## HTTP APIs
-- [Admin API]({{< relref "admin/" >}})
+- [Admin API](admin/)
- [Alerting API (unstable)](https://editor.swagger.io/?url=https://raw.githubusercontent.com/grafana/grafana/main/pkg/services/ngalert/api/tooling/post.json)
-- [Alerting provisioning API]({{< relref "alerting_provisioning/" >}})
-- [Annotations API]({{< relref "annotations/" >}})
-- [Correlations API]({{< relref "correlations/" >}})
-- [Dashboard API]({{< relref "dashboard/" >}})
-- [Dashboard permissions API]({{< relref "dashboard_permissions/" >}})
-- [Dashboard versions API]({{< relref "dashboard_versions/" >}})
-- [Data source API]({{< relref "data_source/" >}})
-- [Folder API]({{< relref "folder/" >}})
-- [Folder permissions API]({{< relref "folder_permissions/" >}})
-- [Folder/Dashboard search API]({{< relref "folder_dashboard_search/" >}})
-- [Library element API]({{< relref "library_element/" >}})
-- [Organization API]({{< relref "org/" >}})
-- [Other API]({{< relref "other/" >}})
-- [Playlists API]({{< relref "playlist/" >}})
-- [Preferences API]({{< relref "preferences/" >}})
-- [Shared dashboards API]({{< relref "dashboard_public/" >}})
-- [Query history API]({{< relref "query_history/" >}})
-- [Service account API]({{< relref "serviceaccount/" >}})
-- [Short URL API]({{< relref "short_url/" >}})
-- [Snapshot API]({{< relref "snapshot/" >}})
-- [SSO settings API]({{< relref "sso-settings/" >}})
-- [Team API]({{< relref "team/" >}})
-- [User API]({{< relref "user/" >}})
+- [Alerting provisioning API](alerting_provisioning/)
+- [Annotations API](annotations/)
+- [Correlations API](correlations/)
+- [Dashboard API](dashboard/)
+- [Dashboard permissions API](dashboard_permissions/)
+- [Dashboard versions API](dashboard_versions/)
+- [Data source API](data_source/)
+- [Folder API](folder/)
+- [Folder permissions API](folder_permissions/)
+- [Folder/Dashboard search API](folder_dashboard_search/)
+- [Library element API](library_element/)
+- [Organization API](org/)
+- [Other API](other/)
+- [Playlists API](playlist/)
+- [Preferences API](preferences/)
+- [Shared dashboards API](dashboard_public/)
+- [Query history API](query_history/)
+- [Service account API](serviceaccount/)
+- [Short URL API](short_url/)
+- [Snapshot API](snapshot/)
+- [SSO settings API](sso-settings/)
+- [Team API](team/)
+- [User API](user/)
## Deprecated HTTP APIs
-- [Authentication API]({{< relref "auth/" >}})
+- [Authentication API](auth/)
## Grafana Enterprise HTTP APIs
Grafana Enterprise includes all of the Grafana OSS APIs as well as the following APIs:
-- [Data source permissions API]({{< relref "datasource_permissions/" >}})
-- [Group attribute sync API]({{< relref "group_attribute_sync/" >}})
-- [License API]({{< relref "licensing/" >}})
-- [Query and resource caching API]({{< relref "query_and_resource_caching/" >}})
-- [Reporting API]({{< relref "reporting/" >}})
-- [Role-based access control API]({{< relref "access_control/" >}})
-- [Team sync API]({{< relref "team_sync/" >}})
+- [Data source permissions API](datasource_permissions/)
+- [Group attribute sync API](group_attribute_sync/)
+- [License API](licensing/)
+- [Query and resource caching API](query_and_resource_caching/)
+- [Reporting API](reporting/)
+- [Role-based access control API](access_control/)
+- [Team sync API](team_sync/)
diff --git a/docs/sources/developers/http_api/access_control.md b/docs/sources/developers/http_api/access_control.md
index ecd0ac62d52..e4d0dc2d5a3 100644
--- a/docs/sources/developers/http_api/access_control.md
+++ b/docs/sources/developers/http_api/access_control.md
@@ -21,11 +21,11 @@ title: RBAC HTTP API
# RBAC API
-> Role-based access control API is only available in Grafana Cloud or Grafana Enterprise. Read more about [Grafana Enterprise]({{< relref "/docs/grafana/latest/introduction/grafana-enterprise" >}}).
+> Role-based access control API is only available in Grafana Cloud or Grafana Enterprise. Read more about [Grafana Enterprise](/docs/grafana/latest/introduction/grafana-enterprise/).
The API can be used to create, update, delete, get, and list roles.
-To check which basic or fixed roles have the required permissions, refer to [RBAC role definitions]({{< ref "/docs/grafana/latest/administration/roles-and-permissions/access-control/rbac-fixed-basic-role-definitions" >}}).
+To check which basic or fixed roles have the required permissions, refer to [RBAC role definitions](/docs/grafana/latest/administration/roles-and-permissions/access-control/rbac-fixed-basic-role-definitions).
## Get status
@@ -226,7 +226,7 @@ Content-Type: application/json; charset=UTF-8
`POST /api/access-control/roles`
-Creates a new custom role and maps given permissions to that role. Note that roles with the same prefix as [Fixed roles]({{< relref "/docs/grafana/latest/administration/roles-and-permissions/access-control#fixed-roles" >}}) can't be created.
+Creates a new custom role and maps given permissions to that role. Note that roles with the same prefix as [Fixed roles](/docs/grafana/latest/administration/roles-and-permissions/access-control/#fixed-roles) can't be created.
#### Required permissions
@@ -264,24 +264,24 @@ Content-Type: application/json
#### JSON body schema
-| Field Name | Date Type | Required | Description |
-| ----------- | ---------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| uid | string | No | UID of the role. If not present, the UID will be automatically created for you and returned in response. Refer to the [Custom roles]({{< relref "/docs/grafana/latest/administration/roles-and-permissions/access-control#custom-roles" >}}) for more information. |
-| global | boolean | No | A flag indicating if the role is global or not. If set to `false`, the default org ID of the authenticated user will be used from the request. |
-| version | number | No | Version of the role. If not present, version 0 will be assigned to the role and returned in the response. Refer to the [Custom roles]({{< relref "/docs/grafana/latest/administration/roles-and-permissions/access-control/#custom-roles" >}}) for more information. |
-| name | string | Yes | Name of the role. Refer to [Custom roles]({{< relref "/docs/grafana/latest/administration/roles-and-permissions/access-control#custom-roles" >}}) for more information. |
-| description | string | No | Description of the role. |
-| displayName | string | No | Display name of the role, visible in the UI. |
-| group | string | No | The group name the role belongs to. |
-| hidden | boolean | No | Specify whether the role is hidden or not. If set to `true`, then the role does not show in the role picker. It will not be listed by API endpoints unless explicitly specified. |
-| permissions | Permission | No | If not present, the role will be created without any permissions. |
+| Field Name | Date Type | Required | Description |
+| ----------- | ---------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| uid | string | No | UID of the role. If not present, the UID will be automatically created for you and returned in response. Refer to the [Custom roles](/docs/grafana/latest/administration/roles-and-permissions/access-control/#custom-roles) for more information. |
+| global | boolean | No | A flag indicating if the role is global or not. If set to `false`, the default org ID of the authenticated user will be used from the request. |
+| version | number | No | Version of the role. If not present, version 0 will be assigned to the role and returned in the response. Refer to the [Custom roles](/docs/grafana/latest/administration/roles-and-permissions/access-control/#custom-roles) for more information. |
+| name | string | Yes | Name of the role. Refer to [Custom roles](/docs/grafana/latest/administration/roles-and-permissions/access-control/#custom-roles) for more information. |
+| description | string | No | Description of the role. |
+| displayName | string | No | Display name of the role, visible in the UI. |
+| group | string | No | The group name the role belongs to. |
+| hidden | boolean | No | Specify whether the role is hidden or not. If set to `true`, then the role does not show in the role picker. It will not be listed by API endpoints unless explicitly specified. |
+| permissions | Permission | No | If not present, the role will be created without any permissions. |
**Permission**
-| Field Name | Data Type | Required | Description |
-| ---------- | --------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| action | string | Yes | Refer to [Custom role actions and scopes]({{< relref "/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes" >}}) for full list of available actions. |
-| scope | string | No | If not present, no scope will be mapped to the permission. Refer to [Custom role actions and scopes]({{< relref "/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes" >}}) for full list of available scopes. |
+| Field Name | Data Type | Required | Description |
+| ---------- | --------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| action | string | Yes | Refer to [Custom role actions and scopes](/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes/) for full list of available actions. |
+| scope | string | No | If not present, no scope will be mapped to the permission. Refer to [Custom role actions and scopes](/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes/) for full list of available scopes. |
#### Example response
@@ -449,10 +449,10 @@ Content-Type: application/json
**Permission**
-| Field Name | Data Type | Required | Description |
-| ---------- | --------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| action | string | Yes | Refer to [Custom role actions and scopes]({{< relref "/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes" >}}) for full list of available actions. |
-| scope | string | No | If not present, no scope will be mapped to the permission. Refer to [Custom role actions and scopes]({{< relref "/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes" >}}) for full list of available scopes. |
+| Field Name | Data Type | Required | Description |
+| ---------- | --------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| action | string | Yes | Refer to [Custom role actions and scopes](/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes/) for full list of available actions. |
+| scope | string | No | If not present, no scope will be mapped to the permission. Refer to [Custom role actions and scopes](/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes/) for full list of available scopes. |
#### Example response
@@ -494,7 +494,7 @@ Permission validation only occurs when permission validation is enabled (`rbac.p
> It has been enabled by default since Grafana 10.2.
-For more information, refer to [Create role validation errors]({{< ref "#create-role-validation-errors" >}}).
+For more information, refer to [Create role validation errors](#create-role-validation-errors).
#### Status codes
@@ -530,10 +530,10 @@ Accept: application/json
#### Query parameters
-| Param | Type | Required | Description |
-| ------ | ------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| force | boolean | No | When set to `true`, the role will be deleted with all its assignments. |
-| global | boolean | No | A flag indicating if the role is global or not. If set to false, the default org ID of the authenticated user will be used from the request. Refer to the [About RBAC]({{< relref "/docs/grafana/latest/administration/roles-and-permissions/access-control" >}}) for more information. |
+| Param | Type | Required | Description |
+| ------ | ------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| force | boolean | No | When set to `true`, the role will be deleted with all its assignments. |
+| global | boolean | No | A flag indicating if the role is global or not. If set to false, the default org ID of the authenticated user will be used from the request. Refer to the [About RBAC](/docs/grafana/latest/administration/roles-and-permissions/access-control/) for more information. |
#### Example response
@@ -711,7 +711,7 @@ Content-Type: application/json; charset=UTF-8
Assign a role to a specific user.
For bulk updates consider
-[Set user role assignments]({{< ref "#set-user-role-assignments" >}}).
+[Set user role assignments](#set-user-role-assignments).
#### Required permissions
@@ -769,7 +769,7 @@ Content-Type: application/json; charset=UTF-8
Revoke a role from a user.
For bulk updates consider
-[Set user role assignments]({{< ref "#set-user-role-assignments" >}}).
+[Set user role assignments](#set-user-role-assignments).
#### Required permissions
@@ -821,8 +821,8 @@ This will remove any assigned roles that aren't in the request and add
roles that are in the set but are not already assigned to the user.
If you want to add or remove a single role, consider using
-[Add a user role assignment]({{< ref "#add-a-user-role-assignment" >}}) or
-[Remove a user role assignment]({{< ref "#remove-a-user-role-assignment" >}})
+[Add a user role assignment](#add-a-user-role-assignment) or
+[Remove a user role assignment](#remove-a-user-role-assignment)
instead.
#### Required permissions
@@ -985,7 +985,7 @@ Content-Type: application/json; charset=UTF-8
Assign a role to a specific service account.
For bulk updates consider
-[Set service account role assignments]({{< ref "#set-service-account-role-assignments" >}}).
+[Set service account role assignments](#set-service-account-role-assignments).
#### Required permissions
@@ -1043,7 +1043,7 @@ Content-Type: application/json; charset=UTF-8
Revoke a role from a service account.
For bulk updates consider
-[Set service account role assignments]({{< ref "#set-service-account-role-assignments" >}}).
+[Set service account role assignments](#set-service-account-role-assignments).
#### Required permissions
@@ -1095,8 +1095,8 @@ This will remove any assigned roles that aren't in the request and add
roles that are in the set but are not already assigned to the service account.
If you want to add or remove a single role, consider using
-[Add a service account role assignment]({{< ref "#add-a-service-account-role-assignment" >}}) or
-[Remove a service account role assignment]({{< ref "#remove-a-service-account-role-assignment" >}})
+[Add a service account role assignment](#add-a-service-account-role-assignment) or
+[Remove a service account role assignment](#remove-a-service-account-role-assignment)
instead.
#### Required permissions
@@ -1213,7 +1213,7 @@ Content-Type: application/json; charset=UTF-8
Assign a role to a specific team.
-For bulk updates consider [Set team role assignments]({{< ref "#set-team-role-assignments" >}}).
+For bulk updates consider [Set team role assignments](#set-team-role-assignments).
#### Required permissions
@@ -1268,7 +1268,7 @@ Content-Type: application/json; charset=UTF-8
Revoke a role from a team.
-For bulk updates consider [Set team role assignments]({{< ref "#set-team-role-assignments" >}}).
+For bulk updates consider [Set team role assignments](#set-team-role-assignments).
#### Required permissions
@@ -1314,8 +1314,8 @@ This will remove any assigned roles that aren't in the request and add
roles that are in the set but are not already assigned to the user.
If you want to add or remove a single role, consider using
-[Add a team role assignment]({{< ref "#add-a-team-role-assignment" >}}) or
-[Remove a team role assignment]({{< ref "#remove-a-team-role-assignment" >}})
+[Add a team role assignment](#add-a-team-role-assignment) or
+[Remove a team role assignment](#remove-a-team-role-assignment)
instead.
#### Required permissions
diff --git a/docs/sources/developers/http_api/admin.md b/docs/sources/developers/http_api/admin.md
index eb96ebecf95..62a64c19cec 100644
--- a/docs/sources/developers/http_api/admin.md
+++ b/docs/sources/developers/http_api/admin.md
@@ -28,17 +28,17 @@ To use these API endpoints you have to use Basic authentication and the Grafana
The `admin` user that Grafana is provisioned with by default has permissions to use these API endpoints.
{{< /admonition >}}
-> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions]({{< relref "../../administration/roles-and-permissions/access-control/custom-role-actions-scopes/" >}}) for more information.
+> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions](../../../administration/roles-and-permissions/access-control/custom-role-actions-scopes/) for more information.
## Fetch settings
`GET /api/admin/settings`
-Only works with Basic Authentication (username and password). See [introduction](http://docs.grafana.org/http_api/admin/#admin-api) for an explanation.
+Only works with Basic Authentication (username and password). See [introduction](/docs/grafana//http_api/admin/#admin-api) for an explanation.
**Required permissions**
-See note in the [introduction]({{< ref "#admin-api" >}}) for an explanation.
+See note in the [introduction](#admin-api) for an explanation.
| Action | Scope |
| ------------- | ----------------------------------------------------------------------------------- |
@@ -213,7 +213,7 @@ This endpoint only supports changes to `auth.saml` configuration.
**Required permissions**
-See note in the [introduction]({{< ref "#admin-api" >}}) for an explanation.
+See note in the [introduction](#admin-api) for an explanation.
| Action | Scope |
| -------------- | ----------------------------------------------------------------------------------- |
@@ -263,11 +263,11 @@ Status codes:
`GET /api/admin/stats`
-Only works with Basic Authentication (username and password). See [introduction](http://docs.grafana.org/http_api/admin/#admin-api) for an explanation.
+Only works with Basic Authentication (username and password). See [introduction](/docs/grafana//http_api/admin/#admin-api) for an explanation.
**Required permissions**
-See note in the [introduction]({{< ref "#admin-api" >}}) for an explanation.
+See note in the [introduction](#admin-api) for an explanation.
| Action | Scope |
| ----------------- | ----- |
@@ -307,7 +307,7 @@ Content-Type: application/json
Preview usage report to be sent to vendor.
-Only works with Basic Authentication (username and password). See [introduction](http://docs.grafana.org/http_api/admin/#admin-api) for an explanation.
+Only works with Basic Authentication (username and password). See [introduction](/docs/grafana//http_api/admin/#admin-api) for an explanation.
**Example Request**:
@@ -345,11 +345,11 @@ Content-Type: application/json
`POST /api/admin/users`
-Create new user. Only works with Basic Authentication (username and password). See [introduction](http://docs.grafana.org/http_api/admin/#admin-api) for an explanation.
+Create new user. Only works with Basic Authentication (username and password). See [introduction](/docs/grafana//http_api/admin/#admin-api) for an explanation.
**Required permissions**
-See note in the [introduction]({{< ref "#admin-api" >}}) for an explanation.
+See note in the [introduction](#admin-api) for an explanation.
| Action | Scope |
| ------------ | ----- |
@@ -371,7 +371,7 @@ Content-Type: application/json
}
```
-Note that `OrgId` is an optional parameter that can be used to assign a new user to a different organization when [auto_assign_org]({{< relref "../../setup-grafana/configure-grafana/#auto-assign-org" >}}) is set to `true`.
+Note that `OrgId` is an optional parameter that can be used to assign a new user to a different organization when [auto_assign_org](../../../setup-grafana/configure-grafana/#auto-assign-org) is set to `true`.
**Example Response**:
@@ -386,12 +386,12 @@ Content-Type: application/json
`PUT /api/admin/users/:id/password`
-Only works with Basic Authentication (username and password). See [introduction](http://docs.grafana.org/http_api/admin/#admin-api) for an explanation.
+Only works with Basic Authentication (username and password). See [introduction](/docs/grafana//http_api/admin/#admin-api) for an explanation.
Change password for a specific user.
**Required permissions**
-See note in the [introduction]({{< ref "#admin-api" >}}) for an explanation.
+See note in the [introduction](#admin-api) for an explanation.
| Action | Scope |
| -------------------- | --------------- |
@@ -420,11 +420,11 @@ Content-Type: application/json
`PUT /api/admin/users/:id/permissions`
-Only works with Basic Authentication (username and password). See [introduction](http://docs.grafana.org/http_api/admin/#admin-api) for an explanation.
+Only works with Basic Authentication (username and password). See [introduction](/docs/grafana//http_api/admin/#admin-api) for an explanation.
**Required permissions**
-See note in the [introduction]({{< ref "#admin-api" >}}) for an explanation.
+See note in the [introduction](#admin-api) for an explanation.
| Action | Scope |
| ----------------------- | --------------- |
@@ -453,11 +453,11 @@ Content-Type: application/json
`DELETE /api/admin/users/:id`
-Only works with Basic Authentication (username and password). See [introduction](http://docs.grafana.org/http_api/admin/#admin-api) for an explanation.
+Only works with Basic Authentication (username and password). See [introduction](/docs/grafana//http_api/admin/#admin-api) for an explanation.
**Required permissions**
-See note in the [introduction]({{< ref "#admin-api" >}}) for an explanation.
+See note in the [introduction](#admin-api) for an explanation.
| Action | Scope |
| ------------ | --------------- |
@@ -486,11 +486,11 @@ Content-Type: application/json
Return a list of all auth tokens (devices) that the user currently have logged in from.
-Only works with Basic Authentication (username and password). See [introduction](http://docs.grafana.org/http_api/admin/#admin-api) for an explanation.
+Only works with Basic Authentication (username and password). See [introduction](/docs/grafana//http_api/admin/#admin-api) for an explanation.
**Required permissions**
-See note in the [introduction]({{< ref "#admin-api" >}}) for an explanation.
+See note in the [introduction](#admin-api) for an explanation.
| Action | Scope |
| -------------------- | --------------- |
@@ -545,11 +545,11 @@ Content-Type: application/json
Revokes the given auth token (device) for the user. User of issued auth token (device) will no longer be logged in
and will be required to authenticate again upon next activity.
-Only works with Basic Authentication (username and password). See [introduction](http://docs.grafana.org/http_api/admin/#admin-api) for an explanation.
+Only works with Basic Authentication (username and password). See [introduction](/docs/grafana//http_api/admin/#admin-api) for an explanation.
**Required permissions**
-See note in the [introduction]({{< ref "#admin-api" >}}) for an explanation.
+See note in the [introduction](#admin-api) for an explanation.
| Action | Scope |
| --------------------- | --------------- |
@@ -585,11 +585,11 @@ Content-Type: application/json
Logout user revokes all auth tokens (devices) for the user. User of issued auth tokens (devices) will no longer be logged in
and will be required to authenticate again upon next activity.
-Only works with Basic Authentication (username and password). See [introduction](http://docs.grafana.org/http_api/admin/#admin-api) for an explanation.
+Only works with Basic Authentication (username and password). See [introduction](/docs/grafana//http_api/admin/#admin-api) for an explanation.
**Required permissions**
-See note in the [introduction]({{< ref "#admin-api" >}}) for an explanation.
+See note in the [introduction](#admin-api) for an explanation.
| Action | Scope |
| ------------ | --------------- |
@@ -630,11 +630,11 @@ Reloads the provisioning config files for specified type and provision entities
until the new provisioned entities are already stored in the database. In case of dashboards, it will stop
polling for changes in dashboard files and then restart it with new configurations after returning.
-Only works with Basic Authentication (username and password). See [introduction](http://docs.grafana.org/http_api/admin/#admin-api) for an explanation.
+Only works with Basic Authentication (username and password). See [introduction](/docs/grafana//http_api/admin/#admin-api) for an explanation.
**Required permissions**
-See note in the [introduction]({{< ref "#admin-api" >}}) for an explanation.
+See note in the [introduction](#admin-api) for an explanation.
| Action | Scope | Provision entity |
| ------------------- | -------------------------- | ---------------- |
@@ -669,7 +669,7 @@ Content-Type: application/json
Reloads the LDAP configuration.
-Only works with Basic Authentication (username and password). See [introduction](http://docs.grafana.org/http_api/admin/#admin-api) for an explanation.
+Only works with Basic Authentication (username and password). See [introduction](/docs/grafana//http_api/admin/#admin-api) for an explanation.
**Example Request**:
@@ -694,7 +694,7 @@ Content-Type: application/json
`POST /api/admin/encryption/rotate-data-keys`
-[Rotates]({{< relref "../../setup-grafana/configure-security/configure-database-encryption/#rotate-data-keys" >}}) data encryption keys.
+[Rotates](../../../setup-grafana/configure-security/configure-database-encryption/#rotate-data-keys) data encryption keys.
**Example Request**:
@@ -715,7 +715,7 @@ Content-Type: application/json
`POST /api/admin/encryption/reencrypt-data-keys`
-[Re-encrypts]({{< relref "../../setup-grafana/configure-security/configure-database-encryption/#re-encrypt-data-keys" >}}) data encryption keys.
+[Re-encrypts](../../../setup-grafana/configure-security/configure-database-encryption/#re-encrypt-data-keys) data encryption keys.
**Example Request**:
@@ -736,7 +736,7 @@ Content-Type: application/json
`POST /api/admin/encryption/reencrypt-secrets`
-[Re-encrypts]({{< relref "../../setup-grafana/configure-security/configure-database-encryption/#re-encrypt-secrets" >}}) secrets.
+[Re-encrypts](../../../setup-grafana/configure-security/configure-database-encryption/#re-encrypt-secrets) secrets.
**Example Request**:
@@ -757,7 +757,7 @@ Content-Type: application/json
`POST /api/admin/encryption/rollback-secrets`
-[Rolls back]({{< relref "../../setup-grafana/configure-security/configure-database-encryption/#roll-back-secrets" >}}) secrets.
+[Rolls back](../../../setup-grafana/configure-security/configure-database-encryption/#roll-back-secrets) secrets.
**Example Request**:
diff --git a/docs/sources/developers/http_api/annotations.md b/docs/sources/developers/http_api/annotations.md
index 974b0c6c6d5..0fb5c4a5d1a 100644
--- a/docs/sources/developers/http_api/annotations.md
+++ b/docs/sources/developers/http_api/annotations.md
@@ -22,7 +22,7 @@ title: Annotations HTTP API
Annotations are saved in the Grafana database (sqlite, mysql or postgres). Annotations can be organization annotations that can be shown on any dashboard by configuring an annotation data source - they are filtered by tags. Or they can be tied to a panel on a dashboard and are then only shown on that panel.
-> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions]({{< relref "/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes" >}}) for more information.
+> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions](/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes/) for more information.
## Find Annotations
@@ -30,7 +30,7 @@ Annotations are saved in the Grafana database (sqlite, mysql or postgres). Annot
**Required permissions**
-See note in the [introduction]({{< ref "#annotations-api" >}}) for an explanation.
+See note in the [introduction](#annotations-api) for an explanation.
| Action | Scope |
@@ -123,7 +123,7 @@ The format for `time` and `timeEnd` should be epoch numbers in millisecond resol
**Required permissions**
-See note in the [introduction]({{< ref "#annotations-api" >}}) for an explanation.
+See note in the [introduction](#annotations-api) for an explanation.
| Action | Scope |
@@ -178,7 +178,7 @@ format (string with multiple tags being separated by a space).
**Required permissions**
-See note in the [introduction]({{< ref "#annotations-api" >}}) for an explanation.
+See note in the [introduction](#annotations-api) for an explanation.
| Action | Scope |
| -------------------- | ------------------------------- |
@@ -219,7 +219,7 @@ Updates all properties of an annotation that matches the specified id. To only u
**Required permissions**
-See note in the [introduction]({{< ref "#annotations-api" >}}) for an explanation.
+See note in the [introduction](#annotations-api) for an explanation.
| Action | Scope |
@@ -265,7 +265,7 @@ This operation currently supports updating of the `text`, `tags`, `time` and `ti
**Required permissions**
-See note in the [introduction]({{< ref "#annotations-api" >}}) for an explanation.
+See note in the [introduction](#annotations-api) for an explanation.
| Action | Scope |
@@ -307,7 +307,7 @@ Deletes the annotation that matches the specified id.
**Required permissions**
-See note in the [introduction]({{< ref "#annotations-api" >}}) for an explanation.
+See note in the [introduction](#annotations-api) for an explanation.
| Action | Scope |
@@ -344,7 +344,7 @@ Find all the event tags created in the annotations.
**Required permissions**
-See note in the [introduction]({{< ref "#annotations-api" >}}) for an explanation.
+See note in the [introduction](#annotations-api) for an explanation.
| Action | Scope |
| ------------------ | ----- |
diff --git a/docs/sources/developers/http_api/auth.md b/docs/sources/developers/http_api/auth.md
index be88ae5ccd0..898def0691b 100644
--- a/docs/sources/developers/http_api/auth.md
+++ b/docs/sources/developers/http_api/auth.md
@@ -22,10 +22,10 @@ title: 'Authentication HTTP API '
The Authentication HTTP API is used to manage API keys.
{{% admonition type="note" %}}
-Grafana recommends using service accounts instead of API keys. For more information, refer to [Grafana service account API reference]({{< relref "./serviceaccount/" >}}).
+Grafana recommends using service accounts instead of API keys. For more information, refer to [Grafana service account API reference](../serviceaccount/).
{{% /admonition %}}
-> If you are running Grafana Enterprise, for some endpoints you would need to have relevant permissions. Refer to [Role-based access control permissions]({{< relref "../../administration/roles-and-permissions/access-control/custom-role-actions-scopes/" >}}) for more information.
+> If you are running Grafana Enterprise, for some endpoints you would need to have relevant permissions. Refer to [Role-based access control permissions](../../../administration/roles-and-permissions/access-control/custom-role-actions-scopes/) for more information.
## List API keys
@@ -38,7 +38,7 @@ This endpoint is deprecated.
**Required permissions**
-See note in the [introduction]({{< ref "#authentication-api" >}}) for an explanation.
+See note in the [introduction](#authentication-api) for an explanation.
| Action | Scope |
| -------------- | ----------- |
@@ -85,7 +85,7 @@ This endpoint has been made obsolete in Grafana 11.3.0.
{{% /admonition %}}
-Endpoint is obsolete and has been moved to [Grafana service account API]({{< relref "./serviceaccount/" >}}). For more information, refer to [Migrate to Grafana service account API](/docs/grafana//administration/service-accounts/migrate-api-keys/).
+Endpoint is obsolete and has been moved to [Grafana service account API](../serviceaccount/). For more information, refer to [Migrate to Grafana service account API](/docs/grafana//administration/service-accounts/migrate-api-keys/).
`POST /api/auth/keys`
@@ -110,7 +110,7 @@ Content-Type: application/json
**Required permissions**
-See note in the [introduction]({{< ref "#authentication-api" >}}) for an explanation.
+See note in the [introduction](#authentication-api) for an explanation.
| Action | Scope |
| ---------------- | ---------- |
diff --git a/docs/sources/developers/http_api/dashboard.md b/docs/sources/developers/http_api/dashboard.md
index d37b0e080c9..75d1f8a50d3 100644
--- a/docs/sources/developers/http_api/dashboard.md
+++ b/docs/sources/developers/http_api/dashboard.md
@@ -18,7 +18,7 @@ title: Dashboard HTTP API
# Dashboard API
-> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions]({{< relref "/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes" >}}) for more information.
+> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions](/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes/) for more information.
## Identifier (id) vs unique identifier (uid)
@@ -26,7 +26,7 @@ The identifier (id) of a dashboard is an auto-incrementing numeric value and is
The unique identifier (uid) of a dashboard can be used for uniquely identify a dashboard between multiple Grafana installs.
It's automatically generated if not provided when creating a dashboard. The uid allows having consistent URLs for accessing
-dashboards and when syncing dashboards between multiple Grafana installs, see [dashboard provisioning]({{< relref "/docs/grafana/latest/administration/provisioning#dashboards" >}})
+dashboards and when syncing dashboards between multiple Grafana installs, see [dashboard provisioning](/docs/grafana/latest/administration/provisioning/#dashboards)
for more information. This means that changing the title of a dashboard will not break any bookmarked links to that dashboard.
The uid can have a maximum length of 40 characters.
@@ -41,7 +41,7 @@ Creates a new dashboard or updates an existing dashboard. When updating existing
**Required permissions**
-See note in the [introduction]({{< ref "#dashboard-api" >}}) for an explanation.
+See note in the [introduction](#dashboard-api) for an explanation.
| Action | Scope |
@@ -80,7 +80,7 @@ JSON Body schema:
- **dashboard** – The complete dashboard model.
- **dashboard.id** – id = null to create a new dashboard.
- **dashboard.uid** – Optional unique identifier when creating a dashboard. uid = null will generate a new uid.
-- **dashboard.refresh** - Set the dashboard refresh interval. If this is lower than [the minimum refresh interval]({{< relref "/docs/grafana/latest/setup-grafana/configure-grafana#min_refresh_interval" >}}), then Grafana will ignore it and will enforce the minimum refresh interval.
+- **dashboard.refresh** - Set the dashboard refresh interval. If this is lower than [the minimum refresh interval](/docs/grafana/latest/setup-grafana/configure-grafana/#min_refresh_interval), then Grafana will ignore it and will enforce the minimum refresh interval.
- **folderId** – The id of the folder to save the dashboard in.
- **folderUid** – The UID of the folder to save the dashboard in. Overrides the `folderId`.
- **overwrite** – Set to true if you want to overwrite an existing dashboard with a given dashboard UID.
@@ -139,7 +139,6 @@ The **412** status code is used for explaining that you cannot create the dashbo
There can be different reasons for this:
- The dashboard has been changed by someone else, `status=version-mismatch`
-- A dashboard with the same name in the folder already exists, `status=name-exists`
- A dashboard with the same uid already exists, `status=name-exists`
- The dashboard belongs to plugin ``, `status=plugin-dashboard`
@@ -156,8 +155,6 @@ Content-Length: 97
}
```
-In case of title already exists the `status` property will be `name-exists`.
-
## Get dashboard by uid
`GET /api/dashboards/uid/:uid`
@@ -166,7 +163,7 @@ Will return the dashboard given the dashboard unique identifier (uid). Informati
**Required permissions**
-See note in the [introduction]({{< ref "#dashboard-api" >}}) for an explanation.
+See note in the [introduction](#dashboard-api) for an explanation.
| Action | Scope |
@@ -225,7 +222,7 @@ Will delete the dashboard given the specified unique identifier (uid).
**Required permissions**
-See note in the [introduction]({{< ref "#dashboard-api" >}}) for an explanation.
+See note in the [introduction](#dashboard-api) for an explanation.
| Action | Scope |
@@ -275,7 +272,7 @@ Will delete permanently the dashboard given the specified unique identifier (uid
**Required permissions**
-See note in the [introduction]({{< ref "#dashboard-api" >}}) for an explanation.
+See note in the [introduction](#dashboard-api) for an explanation.
| Action | Scope |
@@ -325,7 +322,7 @@ Will restore a deleted dashboard given the specified unique identifier (uid).
**Required permissions**
-See note in the [introduction]({{< ref "#dashboard-api" >}}) for an explanation.
+See note in the [introduction](#dashboard-api) for an explanation.
| Action | Scope |
@@ -358,7 +355,7 @@ Content-Type: application/json
Status Codes:
-- **200** – Deleted
+- **200** – Restored
- **401** – Unauthorized
- **403** – Access denied
- **404** – Not found
@@ -453,4 +450,4 @@ Content-Type: application/json
## Dashboard Search
-See [Folder/Dashboard Search API]({{< relref "folder_dashboard_search/" >}}).
+See [Folder/Dashboard Search API](../folder_dashboard_search/).
diff --git a/docs/sources/developers/http_api/dashboard_permissions.md b/docs/sources/developers/http_api/dashboard_permissions.md
index 07242307875..3a12656faf5 100644
--- a/docs/sources/developers/http_api/dashboard_permissions.md
+++ b/docs/sources/developers/http_api/dashboard_permissions.md
@@ -32,7 +32,7 @@ The permission levels for the permission field:
- 2 = Edit
- 4 = Admin
-> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions]({{< relref "/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes" >}}) for more information.
+> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions](/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes/) for more information.
## Get permissions for a dashboard
@@ -42,7 +42,7 @@ Gets all existing permissions for the dashboard with the given `uid`.
**Required permissions**
-See note in the [introduction]({{< ref "#dashboard-permission-api" >}}) for an explanation.
+See note in the [introduction](#dashboard-permission-api) for an explanation.
| Action | Scope |
@@ -124,7 +124,7 @@ Updates permissions for a dashboard. This operation will remove existing permiss
**Required permissions**
-See note in the [introduction]({{< ref "#dashboard-permission-api" >}}) for an explanation.
+See note in the [introduction](#dashboard-permission-api) for an explanation.
| Action | Scope |
diff --git a/docs/sources/developers/http_api/data_source.md b/docs/sources/developers/http_api/data_source.md
index e9d8a8b35ab..ddda447bcfc 100644
--- a/docs/sources/developers/http_api/data_source.md
+++ b/docs/sources/developers/http_api/data_source.md
@@ -19,7 +19,7 @@ title: Data source HTTP API
# Data source API
-> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions]({{< relref "/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes" >}}) for more information.
+> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions](/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes/) for more information.
## Get all data sources
@@ -31,7 +31,7 @@ This API currently doesn't handle pagination. The default maximum number of data
**Required permissions**
-See note in the [introduction]({{< ref "#data-source-api" >}}) for an explanation.
+See note in the [introduction](#data-source-api) for an explanation.
| Action | Scope |
| ---------------- | -------------- |
@@ -90,7 +90,7 @@ This API is deprecated since Grafana v9.0.0 and will be removed in a future rele
**Required permissions**
-See note in the [introduction]({{< ref "#data-source-api" >}}) for an explanation.
+See note in the [introduction](#data-source-api) for an explanation.
| Action | Scope |
| ---------------- | ---------------------------------------------------------------------------- |
@@ -146,7 +146,7 @@ Content-Type: application/json
**Required permissions**
-See note in the [introduction]({{< ref "#data-source-api" >}}) for an explanation.
+See note in the [introduction](#data-source-api) for an explanation.
| Action | Scope |
| ---------------- | -------------------------------------------------------------------------------------- |
@@ -202,7 +202,7 @@ Content-Type: application/json
**Required permissions**
-See note in the [introduction]({{< ref "#data-source-api" >}}) for an explanation.
+See note in the [introduction](#data-source-api) for an explanation.
| Action | Scope |
| ---------------- | ---------------------------------------------------------------------------------------------- |
@@ -258,7 +258,7 @@ Content-Type: application/json
**Required permissions**
-See note in the [introduction]({{< ref "#data-source-api" >}}) for an explanation.
+See note in the [introduction](#data-source-api) for an explanation.
| Action | Scope |
| ------------------- | ---------------------------------------------------------------------------------------------- |
@@ -292,7 +292,7 @@ Content-Type: application/json
**Required permissions**
-See note in the [introduction]({{< ref "#data-source-api" >}}) for an explanation.
+See note in the [introduction](#data-source-api) for an explanation.
| Action | Scope |
| ------------------ | ----- |
@@ -446,7 +446,7 @@ This API is deprecated since Grafana v9.0.0 and will be removed in a future rele
**Required permissions**
-See note in the [introduction]({{< ref "#data-source-api" >}}) for an explanation.
+See note in the [introduction](#data-source-api) for an explanation.
| Action | Scope |
| ----------------- | ---------------------------------------------------------------------------- |
@@ -529,7 +529,7 @@ Similar to [creating a data source](#create-a-data-source), `password` and `basi
**Required permissions**
-See note in the [introduction]({{< ref "#data-source-api" >}}) for an explanation.
+See note in the [introduction](#data-source-api) for an explanation.
| Action | Scope |
| ----------------- | -------------------------------------------------------------------------------------- |
@@ -617,7 +617,7 @@ This API is deprecated since Grafana v9.0.0 and will be removed in a future rele
**Required permissions**
-See note in the [introduction]({{< ref "#data-source-api" >}}) for an explanation.
+See note in the [introduction](#data-source-api) for an explanation.
| Action | Scope |
| ------------------ | ---------------------------------------------------------------------------- |
@@ -649,7 +649,7 @@ Content-Type: application/json
**Required permissions**
-See note in the [introduction]({{< ref "#data-source-api" >}}) for an explanation.
+See note in the [introduction](#data-source-api) for an explanation.
| Action | Scope |
| ------------------ | -------------------------------------------------------------------------------------- |
@@ -684,7 +684,7 @@ Content-Type: application/json
**Required permissions**
-See note in the [introduction]({{< ref "#data-source-api" >}}) for an explanation.
+See note in the [introduction](#data-source-api) for an explanation.
| Action | Scope |
| ------------------ | ---------------------------------------------------------------------------------------------- |
diff --git a/docs/sources/developers/http_api/datasource_permissions.md b/docs/sources/developers/http_api/datasource_permissions.md
index 9c0a0fc3ee8..b65464d0dba 100644
--- a/docs/sources/developers/http_api/datasource_permissions.md
+++ b/docs/sources/developers/http_api/datasource_permissions.md
@@ -23,9 +23,9 @@ title: Datasource Permissions HTTP API
# Data Source Permissions API
-> The Data Source Permissions is only available in Grafana Enterprise. Read more about [Grafana Enterprise]({{< relref "/docs/grafana/latest/introduction/grafana-enterprise" >}}).
+> The Data Source Permissions is only available in Grafana Enterprise. Read more about [Grafana Enterprise](/docs/grafana/latest/introduction/grafana-enterprise/).
-> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions]({{< relref "/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes" >}}) for more information.
+> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions](/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes/) for more information.
This API can be used to list, add and remove permissions for a data source.
@@ -39,7 +39,7 @@ Gets all existing permissions for the data source with the given `uid`.
**Required permissions**
-See note in the [introduction]({{< ref "#data-source-permissions-api" >}}) for an explanation.
+See note in the [introduction](#data-source-permissions-api) for an explanation.
| Action | Scope |
| ---------------------------- | ------------------------------------------------------------------------------------------ |
@@ -134,7 +134,7 @@ To remove a permission, set the `permission` field to an empty string.
**Required permissions**
-See note in the [introduction]({{< ref "#data-source-permissions-api" >}}) for an explanation.
+See note in the [introduction](#data-source-permissions-api) for an explanation.
| Action | Scope |
| ----------------------------- | ------------------------------------------------------------------------------------------ |
@@ -206,7 +206,7 @@ To remove a permission, set the `permission` field to an empty string.
**Required permissions**
-See note in the [introduction]({{< ref "#data-source-permissions-api" >}}) for an explanation.
+See note in the [introduction](#data-source-permissions-api) for an explanation.
| Action | Scope |
| ----------------------------- | ------------------------------------------------------------------------------------------ |
@@ -280,7 +280,7 @@ To remove a permission, set the `permission` field to an empty string.
**Required permissions**
-See note in the [introduction]({{< ref "#data-source-permissions-api" >}}) for an explanation.
+See note in the [introduction](#data-source-permissions-api) for an explanation.
| Action | Scope |
| ----------------------------- | ------------------------------------------------------------------------------------------ |
diff --git a/docs/sources/developers/http_api/examples/create-api-tokens-for-org.md b/docs/sources/developers/http_api/examples/create-api-tokens-for-org.md
index d5b2ded16a4..caa6bc90243 100644
--- a/docs/sources/developers/http_api/examples/create-api-tokens-for-org.md
+++ b/docs/sources/developers/http_api/examples/create-api-tokens-for-org.md
@@ -32,7 +32,7 @@ There are two authentication methods to access the API:
The task is to create a new organization and then add a Token that can be used by other users. In the examples below which use basic auth, the user is `admin` and the password is `admin`.
-1. [Create the org](http://docs.grafana.org/http_api/org/#create-organization). Here is an example using curl:
+1. [Create the org](/docs/grafana//http_api/org/#create-organization). Here is an example using curl:
```bash
curl -X POST -H "Content-Type: application/json" -d '{"name":"apiorg"}' http://admin:admin@localhost:3000/api/orgs
@@ -40,25 +40,25 @@ The task is to create a new organization and then add a Token that can be used b
This should return a response: `{"message":"Organization created","orgId":6}`. Use the orgId for the next steps.
-1. Optional step. If the org was created previously and/or step 3 fails then first [add your Admin user to the org](http://docs.grafana.org/http_api/org/#add-user-in-organization):
+1. Optional step. If the org was created previously and/or step 3 fails then first [add your Admin user to the org](/docs/grafana//http_api/org/#add-user-in-organization):
```bash
curl -X POST -H "Content-Type: application/json" -d '{"loginOrEmail":"admin", "role": "Admin"}' http://admin:admin@localhost:3000/api/orgs//users
```
-1. [Switch the org context for the Admin user to the new org](http://docs.grafana.org/http_api/user/#switch-user-context-for-signed-in-user):
+1. [Switch the org context for the Admin user to the new org](/docs/grafana//http_api/user/#switch-user-context-for-signed-in-user):
```bash
curl -X POST http://admin:admin@localhost:3000/api/user/using/
```
-1. [Create a Service Account]({{< relref "./serviceaccount/#create-service-account" >}}):
+1. [Create a Service Account](../../serviceaccount/#create-service-account):
```bash
curl -X POST -H "Content-Type: application/json" -d '{"name":"test", "role": "Admin"}' http://admin:admin@localhost:3000/api/serviceaccounts
```
-1. [Create a Service Account token]({{< relref "./serviceaccount/#create-service-account-tokens" >}}) for the service account created in the previous step:
+1. [Create a Service Account token](../../serviceaccount/#create-service-account-tokens) for the service account created in the previous step:
```bash
curl -X POST -H "Content-Type: application/json" -d '{"name":"test-token"}' http://admin:admin@localhost:3000/api/serviceaccounts//tokens
@@ -83,7 +83,7 @@ The task is to create a new organization and then add a Token that can be used b
Using the Token that was created in the previous step, you can create a dashboard or carry out other actions without having to switch organizations.
-1. [Add a dashboard](http://docs.grafana.org/http_api/dashboard/#create-update-dashboard) using the key (or bearer token as it is also called):
+1. [Add a dashboard](/docs/grafana//http_api/dashboard/#create-update-dashboard) using the key (or bearer token as it is also called):
```bash
curl -X POST --insecure -H "Authorization: Bearer eyJrIjoiR0ZXZmt1UFc0OEpIOGN5RWdUalBJTllUTk83VlhtVGwiLCJuIjoiYXBpa2V5Y3VybCIsImlkIjo2fQ==" -H "Content-Type: application/json" -d '{
diff --git a/docs/sources/developers/http_api/examples/curl-examples.md b/docs/sources/developers/http_api/examples/curl-examples.md
index a7f3c1ca2e8..b00e59feb4a 100644
--- a/docs/sources/developers/http_api/examples/curl-examples.md
+++ b/docs/sources/developers/http_api/examples/curl-examples.md
@@ -27,16 +27,16 @@ The most basic example for a dashboard for which there is no authentication. You
curl http://localhost:3000/api/search
```
-Here's a cURL command that works for getting the home dashboard when you are running Grafana locally with [basic authentication]({{< relref "/docs/grafana/latest/setup-grafana/configure-security/configure-authentication#basic-auth" >}}) enabled using the default admin credentials:
+Here's a cURL command that works for getting the home dashboard when you are running Grafana locally with [basic authentication](/docs/grafana/latest/setup-grafana/configure-security/configure-authentication/#basic-auth) enabled using the default admin credentials:
```
curl http://admin:admin@localhost:3000/api/search
```
-To pass a username and password with [HTTP basic authorization]({{< relref "/docs/grafana/latest/administration/roles-and-permissions/access-control/manage-rbac-roles" >}}), encode them as base64.
+To pass a username and password with [HTTP basic authorization](/docs/grafana/latest/administration/roles-and-permissions/access-control/manage-rbac-roles/), encode them as base64.
You can't use authorization tokens in the request.
-For example, to [list permissions associated with roles]({{< relref "/docs/grafana/latest/administration/roles-and-permissions/access-control/manage-rbac-roles" >}}) given a username of `user` and password of `password`, use:
+For example, to [list permissions associated with roles](/docs/grafana/latest/administration/roles-and-permissions/access-control/manage-rbac-roles/) given a username of `user` and password of `password`, use:
```
curl --location '/api/access-control/builtin-roles' --user 'user:password'
diff --git a/docs/sources/developers/http_api/folder.md b/docs/sources/developers/http_api/folder.md
index dce1ff7eea7..73a9c54ba39 100644
--- a/docs/sources/developers/http_api/folder.md
+++ b/docs/sources/developers/http_api/folder.md
@@ -18,7 +18,7 @@ title: Folder HTTP API
# Folder API
-> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions]({{< relref "/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes" >}}) for more information.
+> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions](/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes/) for more information.
## Identifier (id) vs unique identifier (uid)
@@ -40,7 +40,7 @@ that the authenticated user has permission to view.
**Required permissions**
-See note in the [introduction]({{< ref "#folder-api" >}}) for an explanation.
+See note in the [introduction](#folder-api) for an explanation.
| Action | Scope |
| -------------- | ----------- |
@@ -83,7 +83,7 @@ Will return the folder given the folder uid.
**Required permissions**
-See note in the [introduction]({{< ref "#folder-api" >}}) for an explanation.
+See note in the [introduction](#folder-api) for an explanation.
| Action | Scope |
| -------------- | ----------- |
@@ -141,7 +141,7 @@ Creates a new folder.
**Required permissions**
-See note in the [introduction]({{< ref "#folder-api" >}}) for an explanation.
+See note in the [introduction](#folder-api) for an explanation.
`folders:create` allows creating folders and subfolders. If granted with scope `folders:uid:general`, allows creating root level folders. Otherwise, allows creating subfolders under the specified folders.
@@ -167,7 +167,7 @@ Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
JSON Body schema:
-- **uid** – Optional [unique identifier]({{< ref "#identifier-id-vs-unique-identifier-uid" >}}).
+- **uid** – Optional [unique identifier](#identifier-id-vs-unique-identifier-uid).
- **title** – The title of the folder.
- **parentUid** - Optional field, the unique identifier of the parent folder under which the folder should be created. Requires nested folders to be enabled.
@@ -215,7 +215,7 @@ Updates an existing folder identified by uid.
**Required permissions**
-See note in the [introduction]({{< ref "#folder-api" >}}) for an explanation.
+See note in the [introduction](#folder-api) for an explanation.
| Action | Scope |
| --------------- | ----------- |
@@ -302,11 +302,11 @@ Content-Length: 97
Deletes an existing folder identified by UID along with all dashboards (and their alerts) stored in the folder. This operation cannot be reverted.
-If [Grafana Alerting]({{< relref "/docs/grafana/latest/alerting" >}}) is enabled, you can set an optional query parameter `forceDeleteRules=false` so that requests will fail with 400 (Bad Request) error if the folder contains any Grafana alerts. However, if this parameter is set to `true` then it will delete any Grafana alerts under this folder.
+If [Grafana Alerting](/docs/grafana/latest/alerting/) is enabled, you can set an optional query parameter `forceDeleteRules=false` so that requests will fail with 400 (Bad Request) error if the folder contains any Grafana alerts. However, if this parameter is set to `true` then it will delete any Grafana alerts under this folder.
**Required permissions**
-See note in the [introduction]({{< ref "#folder-api" >}}) for an explanation.
+See note in the [introduction](#folder-api) for an explanation.
| Action | Scope |
| ---------------- | ----------- |
@@ -352,7 +352,7 @@ This is relevant only if nested folders are enabled.
**Required permissions**
-See note in the [introduction]({{< ref "#folder-api" >}}) for an explanation.
+See note in the [introduction](#folder-api) for an explanation.
If moving the folder under another folder:
@@ -367,7 +367,7 @@ If moving the folder under root:
JSON body schema:
-- **parentUid** – Optional [unique identifier]({{< relref "#identifier-id-vs-unique-identifier-uid" >}}) of the new parent folder. If this is empty, then the folder is moved under the root.
+- **parentUid** – Optional [unique identifier](#identifier-id-vs-unique-identifier-uid) of the new parent folder. If this is empty, then the folder is moved under the root.
**Example Request**:
diff --git a/docs/sources/developers/http_api/folder_dashboard_search.md b/docs/sources/developers/http_api/folder_dashboard_search.md
index 5f945a60a03..af741927365 100644
--- a/docs/sources/developers/http_api/folder_dashboard_search.md
+++ b/docs/sources/developers/http_api/folder_dashboard_search.md
@@ -24,7 +24,7 @@ title: Folder/Dashboard Search HTTP API
`GET /api/search/`
-> Note: When using [Role-based access control]({{< relref "/docs/grafana/latest/administration/roles-and-permissions/access-control" >}}), search results will contain only dashboards and folders which you have access to.
+> Note: When using [Role-based access control](/docs/grafana/latest/administration/roles-and-permissions/access-control/), search results will contain only dashboards and folders which you have access to.
Query parameters:
diff --git a/docs/sources/developers/http_api/folder_permissions.md b/docs/sources/developers/http_api/folder_permissions.md
index 4e7b3ed31ff..74eeffff35a 100644
--- a/docs/sources/developers/http_api/folder_permissions.md
+++ b/docs/sources/developers/http_api/folder_permissions.md
@@ -32,7 +32,7 @@ The permission levels for the permission field:
- 2 = Edit
- 4 = Admin
-> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions]({{< relref "/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes" >}}) for more information.
+> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions](/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes/) for more information.
## Get permissions for a folder
@@ -42,7 +42,7 @@ Gets all existing permissions for the folder with the given `uid`.
**Required permissions**
-See note in the [introduction]({{< ref "#folder-permission-api" >}}) for an explanation.
+See note in the [introduction](#folder-permission-api) for an explanation.
| Action | Scope |
| -------------------------- | ----------- |
@@ -121,7 +121,7 @@ Updates permissions for a folder. This operation will remove existing permission
**Required permissions**
-See note in the [introduction]({{< ref "#folder-permission-api" >}}) for an explanation.
+See note in the [introduction](#folder-permission-api) for an explanation.
| Action | Scope |
| --------------------------- | ----------- |
diff --git a/docs/sources/developers/http_api/group_attribute_sync.md b/docs/sources/developers/http_api/group_attribute_sync.md
index 82f4f67c0f8..f6d5e752297 100644
--- a/docs/sources/developers/http_api/group_attribute_sync.md
+++ b/docs/sources/developers/http_api/group_attribute_sync.md
@@ -22,8 +22,7 @@ The Group Attribute Sync API allows you to configure [group attribute sync featu
> **Note:** Available in [Grafana Enterprise](https://grafana.com/docs/grafana//introduction/grafana-enterprise) and [Grafana Cloud](https://grafana.com/docs/grafana-cloud/)
{{% admonition type="note" %}}
-This feature is behind the `groupAttributeSync` feature toggle.
-You can enable feature toggles through configuration file or environment variables. See configuration [docs](/docs/grafana//setup-grafana/configure-grafana/#feature_toggles) for details.
+This feature is currently in [private preview](https://grafana.com/docs/release-life-cycle/#private-preview) and behind the `groupAttributeSync` feature toggle. Please contact support to have this feature enabled.
{{% /admonition %}}
## List group mappings
diff --git a/docs/sources/developers/http_api/library_element.md b/docs/sources/developers/http_api/library_element.md
index c6efb1df45a..19a5577c202 100644
--- a/docs/sources/developers/http_api/library_element.md
+++ b/docs/sources/developers/http_api/library_element.md
@@ -286,7 +286,7 @@ JSON Body schema:
- `name`: Optional, the name of the library element.
- `model`: The JSON model for the library element.
- `kind`: Kind of element to create, Use `1` for library panels or `2` for library variables.
-- `uid`: Optional, the [unique identifier](/http_api/library_element/#identifier-id-vs-unique-identifier-uid).
+- `uid`: Optional, the [unique identifier](#identifier-id-vs-unique-identifier-uid).
**Example Request**:
@@ -366,7 +366,7 @@ JSON Body schema:
- `model`: The JSON model for the library element.
- `kind`: Kind of element to create. Use `1` for library panels or `2` for library variables.
- `version`: Version of the library element you are updating.
-- `uid`: Optional, the [unique identifier](/http_api/library_element/#identifier-id-vs-unique-identifier-uid).
+- `uid`: Optional, the [unique identifier](#identifier-id-vs-unique-identifier-uid).
**Example Request**:
diff --git a/docs/sources/developers/http_api/licensing.md b/docs/sources/developers/http_api/licensing.md
index 937f25a8468..0d09183750c 100644
--- a/docs/sources/developers/http_api/licensing.md
+++ b/docs/sources/developers/http_api/licensing.md
@@ -19,7 +19,7 @@ title: Licensing HTTP API
# Enterprise License API
-Licensing is only available in Grafana Enterprise. Read more about [Grafana Enterprise]({{< relref "/docs/grafana/latest/introduction/grafana-enterprise" >}}).
+Licensing is only available in Grafana Enterprise. Read more about [Grafana Enterprise](/docs/grafana/latest/introduction/grafana-enterprise/).
{{< admonition type="caution" >}}
You can't authenticate to the Licensing HTTP API with service account tokens.
@@ -31,7 +31,7 @@ To use these API endpoints you have to use Basic authentication and the Grafana
The `admin` user that Grafana is provisioned with by default has permissions to use these API endpoints.
{{< /admonition >}}
-> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions]({{< relref "/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes" >}}) for more information.
+> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions](/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes/) for more information.
## Check license availability
@@ -43,7 +43,7 @@ Checks if a valid license is available.
**Required permissions**
-See note in the [introduction]({{< ref "#enterprise-license-api" >}}) for an explanation.
+See note in the [introduction](#enterprise-license-api) for an explanation.
| Action | Scope |
| -------------- | ----- |
@@ -85,7 +85,7 @@ Applies a license to a Grafana instance.
**Required permissions**
-See note in the [introduction]({{< ref "#enterprise-license-api" >}}) for an explanation.
+See note in the [introduction](#enterprise-license-api) for an explanation.
| Action | Scope |
| --------------- | ----- |
@@ -147,7 +147,7 @@ Manually ask license issuer for a new token.
**Required permissions**
-See note in the [introduction]({{< ref "#enterprise-license-api" >}}) for an explanation.
+See note in the [introduction](#enterprise-license-api) for an explanation.
| Action | Scope |
| --------------- | ----- |
@@ -208,7 +208,7 @@ Removes the license stored in the Grafana database.
**Required permissions**
-See note in the [introduction]({{< ref "#enterprise-license-api" >}}) for an explanation.
+See note in the [introduction](#enterprise-license-api) for an explanation.
| Action | Scope |
| ---------------- | ----- |
diff --git a/docs/sources/developers/http_api/org.md b/docs/sources/developers/http_api/org.md
index d79a60f95ef..d5fb8ab9cb5 100644
--- a/docs/sources/developers/http_api/org.md
+++ b/docs/sources/developers/http_api/org.md
@@ -23,7 +23,7 @@ The Organization HTTP API is divided in two resources, `/api/org` (current organ
and `/api/orgs` (admin organizations). One big difference between these are that
the admin of all organizations API only works with basic authentication, see [Admin Organizations API](#admin-organizations-api) for more information.
-> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions]({{< relref "/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes" >}}) for more information.
+> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions](/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes/) for more information.
## Current Organization API
@@ -33,7 +33,7 @@ the admin of all organizations API only works with basic authentication, see [Ad
**Required permissions**
-See note in the [introduction]({{< ref "#organization-api" >}}) for an explanation.
+See note in the [introduction](#organization-api) for an explanation.
| Action | Scope |
| --------- | ----- |
@@ -69,7 +69,7 @@ Accessible to users with org admin role.
**Required permissions**
-See note in the [introduction]({{< ref "#organization-api" >}}) for an explanation.
+See note in the [introduction](#organization-api) for an explanation.
| Action | Scope |
| -------------- | -------- |
@@ -115,7 +115,7 @@ when editing folder/dashboard permissions.
**Required permissions**
-See note in the [introduction]({{< ref "#organization-api" >}}) for an explanation.
+See note in the [introduction](#organization-api) for an explanation.
| Action | Scope |
| -------------- | -------- |
@@ -151,7 +151,7 @@ Content-Type: application/json
**Required permissions**
-See note in the [introduction]({{< ref "#organization-api" >}}) for an explanation.
+See note in the [introduction](#organization-api) for an explanation.
| Action | Scope |
| --------------- | -------- |
@@ -185,7 +185,7 @@ Content-Type: application/json
**Required permissions**
-See note in the [introduction]({{< ref "#organization-api" >}}) for an explanation.
+See note in the [introduction](#organization-api) for an explanation.
| Action | Scope |
| ---------------- | -------- |
@@ -215,7 +215,7 @@ Content-Type: application/json
**Required permissions**
-See note in the [introduction]({{< ref "#organization-api" >}}) for an explanation.
+See note in the [introduction](#organization-api) for an explanation.
| Action | Scope |
| ---------- | ----- |
@@ -251,7 +251,7 @@ Adds a global user to the current organization.
**Required permissions**
-See note in the [introduction]({{< ref "#organization-api" >}}) for an explanation.
+See note in the [introduction](#organization-api) for an explanation.
| Action | Scope |
| ------------- | -------- |
@@ -300,7 +300,7 @@ Only works with Basic Authentication (username and password), see [introduction]
**Required permissions**
-See note in the [introduction]({{< ref "#organization-api" >}}) for an explanation.
+See note in the [introduction](#organization-api) for an explanation.
| Action | Scope |
| --------- | ----- |
@@ -342,7 +342,7 @@ Only works with Basic Authentication (username and password), see [introduction]
**Required permissions**
-See note in the [introduction]({{< ref "#organization-api" >}}) for an explanation.
+See note in the [introduction](#organization-api) for an explanation.
| Action | Scope | Note |
| --------- | ----- | ------------------------------ |
@@ -384,7 +384,7 @@ Only works with Basic Authentication (username and password), see [introduction]
**Required permissions**
-See note in the [introduction]({{< ref "#organization-api" >}}) for an explanation.
+See note in the [introduction](#organization-api) for an explanation.
| Action | Scope | Note |
| ----------- | ----- | ------------------------------ |
@@ -427,7 +427,7 @@ Only works with Basic Authentication (username and password), see [introduction]
**Required permissions**
-See note in the [introduction]({{< ref "#organization-api" >}}) for an explanation.
+See note in the [introduction](#organization-api) for an explanation.
| Action | Scope | Note |
| --------- | ----- | ------------------------------ |
@@ -469,7 +469,7 @@ Only works with Basic Authentication (username and password), see [introduction]
**Required permissions**
-See note in the [introduction]({{< ref "#organization-api" >}}) for an explanation.
+See note in the [introduction](#organization-api) for an explanation.
| Action | Scope |
| ---------- | ----- |
@@ -504,7 +504,7 @@ Only works with Basic Authentication (username and password), see [introduction]
**Required permissions**
-See note in the [introduction]({{< ref "#organization-api" >}}) for an explanation.
+See note in the [introduction](#organization-api) for an explanation.
| Action | Scope |
| ----------- | ----- |
@@ -534,7 +534,7 @@ Only works with Basic Authentication (username and password), see [introduction]
**Required permissions**
-See note in the [introduction]({{< ref "#organization-api" >}}) for an explanation.
+See note in the [introduction](#organization-api) for an explanation.
| Action | Scope |
| -------------- | -------- |
@@ -575,7 +575,7 @@ Only works with Basic Authentication (username and password), see [introduction]
**Required permissions**
-See note in the [introduction]({{< ref "#organization-api" >}}) for an explanation.
+See note in the [introduction](#organization-api) for an explanation.
| Action | Scope |
| ------------- | -------- |
@@ -611,7 +611,7 @@ Only works with Basic Authentication (username and password), see [introduction]
**Required permissions**
-See note in the [introduction]({{< ref "#organization-api" >}}) for an explanation.
+See note in the [introduction](#organization-api) for an explanation.
| Action | Scope |
| --------------- | -------- |
@@ -646,7 +646,7 @@ Only works with Basic Authentication (username and password), see [introduction]
**Required permissions**
-See note in the [introduction]({{< ref "#organization-api" >}}) for an explanation.
+See note in the [introduction](#organization-api) for an explanation.
| Action | Scope |
| ---------------- | -------- |
diff --git a/docs/sources/developers/http_api/query_and_resource_caching.md b/docs/sources/developers/http_api/query_and_resource_caching.md
index 826292decb6..0b24456e2e2 100644
--- a/docs/sources/developers/http_api/query_and_resource_caching.md
+++ b/docs/sources/developers/http_api/query_and_resource_caching.md
@@ -24,7 +24,7 @@ title: Query and Resource Caching HTTP API
# Query and resource caching API
{{% admonition type="note" %}}
-If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions]({{< relref "/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes" >}}) for more information.
+If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions](/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes/) for more information.
{{% /admonition %}}
## Enable caching for a data source
@@ -33,7 +33,7 @@ If you are running Grafana Enterprise, for some endpoints you'll need to have sp
**Required permissions**
-See note in the [introduction]({{< ref "#query-and-resource-caching-api" >}}) for an explanation.
+See note in the [introduction](#query-and-resource-caching-api) for an explanation.
| Action | Scope |
| ------------------------- | -------------- |
@@ -83,7 +83,7 @@ Content-Type: application/json
**Required permissions**
-See note in the [introduction]({{< ref "#query-and-resource-caching-api" >}}) for an explanation.
+See note in the [introduction](#query-and-resource-caching-api) for an explanation.
| Action | Scope |
| ------------------------- | -------------- |
@@ -135,7 +135,7 @@ Will clean cached data for _all_ data sources with caching enabled. The `dataSou
**Required permissions**
-See note in the [introduction]({{< ref "#query-and-resource-caching-api" >}}) for an explanation.
+See note in the [introduction](#query-and-resource-caching-api) for an explanation.
| Action | Scope |
| ------------------------- | -------------- |
@@ -185,7 +185,7 @@ Content-Type: application/json
**Required permissions**
-See note in the [introduction]({{< ref "#query-and-resource-caching-api" >}}) for an explanation.
+See note in the [introduction](#query-and-resource-caching-api) for an explanation.
| Action | Scope |
| ------------------------- | -------------- |
@@ -256,7 +256,7 @@ Content-Type: application/json
**Required permissions**
-See note in the [introduction]({{< ref "#query-and-resource-caching-api" >}}) for an explanation.
+See note in the [introduction](#query-and-resource-caching-api) for an explanation.
| Action | Scope |
| ------------------------ | -------------- |
diff --git a/docs/sources/developers/http_api/reporting.md b/docs/sources/developers/http_api/reporting.md
index 871775fe15a..8666f253e63 100644
--- a/docs/sources/developers/http_api/reporting.md
+++ b/docs/sources/developers/http_api/reporting.md
@@ -17,13 +17,13 @@ title: Reporting API
# Reporting API
-This API allows you to interact programmatically with the [Reporting]({{< relref "/docs/grafana/latest/dashboards/create-reports" >}}) feature.
+This API allows you to interact programmatically with the [Reporting](/docs/grafana/latest/dashboards/create-reports/) feature.
> The Reporting API is not stabilized yet, it is still in active development and may change without prior notice.
-> Reporting is only available in Grafana Enterprise. Read more about [Grafana Enterprise]({{< relref "/docs/grafana/latest/introduction/grafana-enterprise" >}}).
+> Reporting is only available in Grafana Enterprise. Read more about [Grafana Enterprise](/docs/grafana/latest/introduction/grafana-enterprise/).
-> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions]({{< relref "/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes" >}}) for more information.
+> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions](/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes/) for more information.
## List all reports
@@ -31,7 +31,7 @@ This API allows you to interact programmatically with the [Reporting]({{< relref
#### Required permissions
-See note in the [introduction]({{< relref "#reporting-api" >}}) for an explanation.
+See note in the [introduction](#reporting-api) for an explanation.
| Action | Scope |
| ------------ | --------------------------- |
@@ -103,7 +103,7 @@ Content-Length: 1840
### Status Codes
- **200** – OK
-- **401** - Authentication failed, refer to [Authentication API]({{< relref "/docs/grafana/latest/developers/http_api/auth" >}}).
+- **401** - Authentication failed, refer to [Authentication API](/docs/grafana/latest/developers/http_api/auth/).
- **500** – Unexpected error or server misconfiguration. Refer to server logs for more details.
## Get a report
@@ -112,7 +112,7 @@ Content-Length: 1840
#### Required permissions
-See note in the [introduction]({{< relref "#reporting-api" >}}) for an explanation.
+See note in the [introduction](#reporting-api) for an explanation.
| Action | Scope |
| ------------ | ---------------------------------------------------------- |
@@ -187,7 +187,7 @@ Content-Length: 940
- **200** – OK
- **400** – Bad request (invalid report ID).
-- **401** - Authentication failed, refer to [Authentication API]({{< relref "/docs/grafana/latest/developers/http_api/auth" >}}).
+- **401** - Authentication failed, refer to [Authentication API](/docs/grafana/latest/developers/http_api/auth/).
- **403** – Forbidden (access denied to a report or a dashboard used in the report).
- **404** – Not found (such report does not exist).
- **500** – Unexpected error or server misconfiguration. Refer to server logs for more details.
@@ -198,7 +198,7 @@ Content-Length: 940
#### Required permissions
-See note in the [introduction]({{< ref "#reporting-api" >}}) for an explanation.
+See note in the [introduction](#reporting-api) for an explanation.
| Action | Scope |
| -------------- | ----- |
@@ -308,7 +308,7 @@ Content-Length: 35
#### Required permissions
-See note in the [introduction]({{< ref "#reporting-api" >}}) for an explanation.
+See note in the [introduction](#reporting-api) for an explanation.
| Action | Scope |
| ------------- | --------------------------------------------------------- |
@@ -316,7 +316,7 @@ See note in the [introduction]({{< ref "#reporting-api" >}}) for an explanation.
### Example request
-See [JSON body schema]({{< ref "#config-json-body-schema" >}}) for fields description.
+See [JSON body schema](#config-json-body-schema) for fields description.
```http
GET /api/reports HTTP/1.1
@@ -381,7 +381,7 @@ Content-Length: 28
- **200** – OK
- **400** – Bad request (invalid json, missing or invalid fields values, etc.).
-- **401** - Authentication failed, refer to [Authentication API]({{< relref "/docs/grafana/latest/developers/http_api/auth" >}}).
+- **401** - Authentication failed, refer to [Authentication API](/docs/grafana/latest/developers/http_api/auth/).
- **403** – Forbidden (access denied to a report or a dashboard used in the report).
- **404** – Not found (such report does not exist).
- **500** – Unexpected error or server misconfiguration. Refer to server logs for more details.
@@ -392,7 +392,7 @@ Content-Length: 28
#### Required permissions
-See note in the [introduction]({{< ref "#reporting-api" >}}) for an explanation.
+See note in the [introduction](#reporting-api) for an explanation.
| Action | Scope |
| -------------- | --------------------------------------------------------- |
@@ -423,7 +423,7 @@ Content-Length: 39
- **200** – OK
- **400** – Bad request (invalid report ID).
-- **401** - Authentication failed, refer to [Authentication API]({{< relref "/docs/grafana/latest/developers/http_api/auth" >}}).
+- **401** - Authentication failed, refer to [Authentication API](/docs/grafana/latest/developers/http_api/auth/).
- **404** - Not found (report with this ID does not exist).
- **500** - Unexpected error or server misconfiguration. Refer to server logs for more details
@@ -435,7 +435,7 @@ Generate and send a report. This API waits for the report to be generated before
#### Required permissions
-See note in the [introduction]({{< ref "#reporting-api" >}}) for an explanation.
+See note in the [introduction](#reporting-api) for an explanation.
| Action | Scope |
| ------------ | ----- |
@@ -477,7 +477,7 @@ Content-Length: 29
- **200** – Report was sent.
- **400** – Bad request (invalid json, missing content-type, missing or invalid fields, etc.).
-- **401** - Authentication failed, refer to [Authentication API]({{< relref "/docs/grafana/latest/developers/http_api/auth" >}}).
+- **401** - Authentication failed, refer to [Authentication API](/docs/grafana/latest/developers/http_api/auth/).
- **403** - Forbidden (access denied to a report or a dashboard used in the report).
- **404** - Report not found.
- **500** - Unexpected error or server misconfiguration. Refer to server logs for more details.
@@ -490,7 +490,7 @@ Returns reports branding settings that are global and used across all the report
#### Required permissions
-See note in the [introduction]({{< ref "#reporting-api" >}}) for an explanation.
+See note in the [introduction](#reporting-api) for an explanation.
| Action | Scope |
| --------------------- | ----- |
@@ -529,7 +529,7 @@ Content-Length: 181
### Status Codes
- **200** – OK
-- **401** - Authentication failed, refer to [Authentication API]({{< relref "/docs/grafana/latest/developers/http_api/auth" >}}).
+- **401** - Authentication failed, refer to [Authentication API](/docs/grafana/latest/developers/http_api/auth/).
- **500** - Unexpected error or server misconfiguration. Refer to server logs for more detail
## Save reports branding settings
@@ -540,7 +540,7 @@ Creates settings if they don't exist, otherwise updates them. These settings are
#### Required permissions
-See note in the [introduction]({{< ref "#reporting-api" >}}) for an explanation.
+See note in the [introduction](#reporting-api) for an explanation.
| Action | Scope |
| ---------------------- | ----- |
@@ -591,7 +591,7 @@ Content-Length: 35
- **200** – OK
- **400** – Bad request (invalid json, missing or invalid fields values, etc.).
-- **401** - Authentication failed, refer to [Authentication API]({{< relref "/docs/grafana/latest/developers/http_api/auth" >}}).
+- **401** - Authentication failed, refer to [Authentication API](/docs/grafana/latest/developers/http_api/auth/).
- **500** - Unexpected error or server misconfiguration. Refer to server logs for more detail
## Send a test email
@@ -602,7 +602,7 @@ Sends a test email with a report without persisting it in the database.
#### Required permissions
-See note in the [introduction]({{< ref "#reporting-api" >}}) for an explanation.
+See note in the [introduction](#reporting-api) for an explanation.
| Action | Scope |
| ------------ | ----- |
@@ -610,7 +610,7 @@ See note in the [introduction]({{< ref "#reporting-api" >}}) for an explanation.
### Example request
-See [JSON body schema]({{< ref "#config-json-body-schema" >}}) for fields description.
+See [JSON body schema](#config-json-body-schema) for fields description.
```http
POST /api/reports/test-email HTTP/1.1
@@ -674,6 +674,6 @@ Content-Length: 29
- **200** – OK
- **400** – Bad request (invalid json, missing or invalid fields values, etc.).
-- **401** - Authentication failed, refer to [Authentication API]({{< relref "/docs/grafana/latest/developers/http_api/auth" >}}).
+- **401** - Authentication failed, refer to [Authentication API](/docs/grafana/latest/developers/http_api/auth/).
- **403** - Forbidden (access denied to a report or a dashboard used in the report).
- **500** - Unexpected error or server misconfiguration. Refer to server logs for more details
diff --git a/docs/sources/developers/http_api/serviceaccount.md b/docs/sources/developers/http_api/serviceaccount.md
index 680c3472647..559ecc05b3a 100644
--- a/docs/sources/developers/http_api/serviceaccount.md
+++ b/docs/sources/developers/http_api/serviceaccount.md
@@ -18,7 +18,7 @@ title: Service account HTTP API
# Service account API
-> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions]({{< relref "/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes" >}}) for more information.
+> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions](/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes/) for more information.
> For Grafana Cloud instances, please use a Bearer token to authenticate. The examples within this section reference Basic authentication which is for On-Prem Grafana instances.
## Search service accounts with Paging
@@ -27,7 +27,7 @@ title: Service account HTTP API
**Required permissions**
-See note in the [introduction]({{< ref "#service-account-api" >}}) for an explanation.
+See note in the [introduction](#service-account-api) for an explanation.
| Action | Scope |
| -------------------- | ----- |
@@ -94,7 +94,7 @@ Content-Type: application/json
**Required permissions**
-See note in the [introduction]({{< ref "#service-account-api" >}}) for an explanation.
+See note in the [introduction](#service-account-api) for an explanation.
| Action | Scope |
| ---------------------- | ----- |
@@ -141,7 +141,7 @@ Content-Type: application/json
**Required permissions**
-See note in the [introduction]({{< ref "#service-account-api" >}}) for an explanation.
+See note in the [introduction](#service-account-api) for an explanation.
| Action | Scope |
| -------------------- | --------------------- |
@@ -182,7 +182,7 @@ Content-Type: application/json
**Required permissions**
-See note in the [introduction]({{< ref "#service-account-api" >}}) for an explanation.
+See note in the [introduction](#service-account-api) for an explanation.
| Action | Scope |
| --------------------- | --------------------- |
@@ -228,7 +228,7 @@ Content-Type: application/json
**Required permissions**
-See note in the [introduction]({{< ref "#service-account-api" >}}) for an explanation.
+See note in the [introduction](#service-account-api) for an explanation.
| Action | Scope |
| ---------------------- | --------------------- |
@@ -262,7 +262,7 @@ Content-Type: application/json
**Required permissions**
-See note in the [introduction]({{< ref "#service-account-api" >}}) for an explanation.
+See note in the [introduction](#service-account-api) for an explanation.
| Action | Scope |
| --------------------- | ------------------ |
@@ -294,7 +294,7 @@ Content-Type: application/json
**Required permissions**
-See note in the [introduction]({{< ref "#service-account-api" >}}) for an explanation.
+See note in the [introduction](#service-account-api) for an explanation.
| Action | Scope |
| --------------------- | ------------------ |
@@ -326,7 +326,7 @@ Content-Type: application/json
**Required permissions**
-See note in the [introduction]({{< ref "#service-account-api" >}}) for an explanation.
+See note in the [introduction](#service-account-api) for an explanation.
| Action | Scope |
| -------------------- | ------------------ |
@@ -358,7 +358,7 @@ Content-Type: application/json
**Required permissions**
-See note in the [introduction]({{< ref "#service-account-api" >}}) for an explanation.
+See note in the [introduction](#service-account-api) for an explanation.
| Action | Scope |
| --------------------- | ------------------ |
@@ -390,7 +390,7 @@ Content-Type: application/json
**Required permissions**
-See note in the [introduction]({{< ref "#service-account-api" >}}) for an explanation.
+See note in the [introduction](#service-account-api) for an explanation.
| Action | Scope |
| -------------------- | --------------------- |
@@ -430,7 +430,7 @@ Content-Type: application/json
**Required permissions**
-See note in the [introduction]({{< ref "#service-account-api" >}}) for an explanation.
+See note in the [introduction](#service-account-api) for an explanation.
| Action | Scope |
| --------------------- | --------------------- |
@@ -471,7 +471,7 @@ Content-Type: application/json
**Required permissions**
-See note in the [introduction]({{< ref "#service-account-api" >}}) for an explanation.
+See note in the [introduction](#service-account-api) for an explanation.
| Action | Scope |
| --------------------- | --------------------- |
@@ -505,7 +505,7 @@ This operation will delete the service account and create a legacy API Key for t
**Required permissions**
-See note in the [introduction]({{< ref "#service-account-api" >}}) for an explanation.
+See note in the [introduction](#service-account-api) for an explanation.
| Action | Scope |
| ---------------------- | --------------------- |
diff --git a/docs/sources/developers/http_api/short_url.md b/docs/sources/developers/http_api/short_url.md
index 03390a5f655..84c754a42a5 100644
--- a/docs/sources/developers/http_api/short_url.md
+++ b/docs/sources/developers/http_api/short_url.md
@@ -41,7 +41,7 @@ Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
JSON body schema:
-- **path** – The path to shorten, relative to the Grafana [root_url]({{< relref "/docs/grafana/latest/setup-grafana/configure-grafana#root_url" >}}).
+- **path** – The path to shorten, relative to the Grafana [root_url](/docs/grafana/latest/setup-grafana/configure-grafana/#root_url).
**Example response:**
diff --git a/docs/sources/developers/http_api/sso-settings.md b/docs/sources/developers/http_api/sso-settings.md
index cb426373485..dfb10ebf71e 100644
--- a/docs/sources/developers/http_api/sso-settings.md
+++ b/docs/sources/developers/http_api/sso-settings.md
@@ -20,7 +20,7 @@ title: SSO Settings API
# SSO Settings API
-> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions]({{< relref "/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes" >}}) for more information.
+> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions](/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes/) for more information.
{{% admonition type="note" %}}
Available since Grafana 11. SAML support is in public preview behind the `ssoSettingsSAML` feature flag.
@@ -29,7 +29,7 @@ Available since Grafana 11. SAML support is in public preview behind the `ssoSet
The API can be used to create, update, delete, get, and list SSO Settings for OAuth2 and SAML.
The settings managed by this API are stored in the database and override
-[settings from other sources]({{< relref "../../setup-grafana/configure-security/configure-authentication" >}})
+[settings from other sources](../../../setup-grafana/configure-security/configure-authentication/)
(arguments, environment variables, settings file, etc).
Therefore, every time settings for a specific provider are removed or reset to the default settings at runtime,
the settings are inherited from the other sources in the reverse order of precedence
@@ -45,7 +45,7 @@ The providers or SSO keys that are not managed by this API are retrieved from th
**Required permissions**
-See note in the [introduction]({{< ref "#sso-settings" >}}) for an explanation.
+See note in the [introduction](#sso-settings) for an explanation.
| Action | Scope |
| --------------- | ---------------------------- |
@@ -112,7 +112,7 @@ The SSO keys that are not managed by this API are retrieved from the other sourc
**Required permissions**
-See note in the [introduction]({{< ref "#sso-settings" >}}) for an explanation.
+See note in the [introduction](#sso-settings) for an explanation.
| Action | Scope |
| --------------- | ---------------------------- |
@@ -175,7 +175,7 @@ to wait a few minutes for the configuration to propagate to all Grafana instance
**Required permissions**
-See note in the [introduction]({{< ref "#sso-settings" >}}) for an explanation.
+See note in the [introduction](#sso-settings) for an explanation.
| Action | Scope |
| ---------------- | ---------------------------- |
@@ -222,7 +222,7 @@ Deletes an existing SSO Settings entry for a provider.
**Required permissions**
-See note in the [introduction]({{< ref "#sso-settings" >}}) for an explanation.
+See note in the [introduction](#sso-settings) for an explanation.
| Action | Scope |
| ---------------- | ---------------------------- |
diff --git a/docs/sources/developers/http_api/team.md b/docs/sources/developers/http_api/team.md
index f7eec3d6260..db73f9d11f1 100644
--- a/docs/sources/developers/http_api/team.md
+++ b/docs/sources/developers/http_api/team.md
@@ -26,10 +26,8 @@ Access to these API endpoints is restricted as follows:
- All authenticated users are able to view details of teams they are a member of.
- Organization Admins are able to manage all teams and team members.
-- If you enable `editors_can_admin` configuration flag, then Organization Editors can create teams and manage teams where they are Admin.
- - If you enable `editors_can_admin` configuration flag, Editors can find out whether a team that they are not members of exists by trying to create a team with the same name.
-> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions]({{< relref "/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes" >}}) for more information.
+> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions](/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes/) for more information.
## Team Search With Paging
@@ -41,7 +39,7 @@ or
**Required permissions**
-See note in the [introduction]({{< ref "#team-api" >}}) for an explanation.
+See note in the [introduction](#team-api) for an explanation.
| Action | Scope |
| ---------- | -------- |
@@ -107,7 +105,7 @@ The `name` parameter returns a single team if the parameter matches the `name` f
**Required permissions**
-See note in the [introduction]({{< ref "#team-api" >}}) for an explanation.
+See note in the [introduction](#team-api) for an explanation.
| Action | Scope |
| ---------- | -------- |
@@ -153,7 +151,7 @@ The Team `name` needs to be unique. `name` is required and `email` is optional.
**Required permissions**
-See note in the [introduction]({{< ref "#team-api" >}}) for an explanation.
+See note in the [introduction](#team-api) for an explanation.
| Action | Scope |
| ------------ | ----- |
@@ -179,7 +177,7 @@ Authorization: Bearer glsa_kcVxDhZtu5ISOZIEt
HTTP/1.1 200
Content-Type: application/json
-{"message":"Team created","teamId":2}
+{"message":"Team created","teamId":2,"uid":"ceaulqadfoav4e"}
```
Status Codes:
@@ -197,7 +195,7 @@ There are two fields that can be updated for a team: `name` and `email`.
**Required permissions**
-See note in the [introduction]({{< ref "#team-api" >}}) for an explanation.
+See note in the [introduction](#team-api) for an explanation.
| Action | Scope |
| ----------- | -------- |
@@ -240,7 +238,7 @@ Status Codes:
**Required permissions**
-See note in the [introduction]({{< ref "#team-api" >}}) for an explanation.
+See note in the [introduction](#team-api) for an explanation.
| Action | Scope |
| ------------ | -------- |
@@ -277,7 +275,7 @@ Status Codes:
**Required permissions**
-See note in the [introduction]({{< ref "#team-api" >}}) for an explanation.
+See note in the [introduction](#team-api) for an explanation.
| Action | Scope |
| ---------------------- | -------- |
@@ -330,7 +328,7 @@ Status Codes:
**Required permissions**
-See note in the [introduction]({{< ref "#team-api" >}}) for an explanation.
+See note in the [introduction](#team-api) for an explanation.
| Action | Scope |
| ----------------------- | -------- |
@@ -372,7 +370,7 @@ Status Codes:
**Required permissions**
-See note in the [introduction]({{< ref "#team-api" >}}) for an explanation.
+See note in the [introduction](#team-api) for an explanation.
| Action | Scope |
| ----------------------- | -------- |
@@ -412,7 +410,7 @@ Will override all current members and administrators for the specified team.
**Required permissions**
-See note in the [introduction]({{< ref "#team-api" >}}) for an explanation.
+See note in the [introduction](#team-api) for an explanation.
| Action | Scope |
| ----------------------- | -------- |
@@ -455,7 +453,7 @@ Status Codes:
**Required permissions**
-See note in the [introduction]({{< ref "#team-api" >}}) for an explanation.
+See note in the [introduction](#team-api) for an explanation.
| Action | Scope |
| ---------- | -------- |
@@ -489,7 +487,7 @@ Content-Type: application/json
**Required permissions**
-See note in the [introduction]({{< ref "#team-api" >}}) for an explanation.
+See note in the [introduction](#team-api) for an explanation.
| Action | Scope |
| ----------- | -------- |
diff --git a/docs/sources/developers/http_api/team_sync.md b/docs/sources/developers/http_api/team_sync.md
index 84a5b15679f..c4c0e607a2d 100644
--- a/docs/sources/developers/http_api/team_sync.md
+++ b/docs/sources/developers/http_api/team_sync.md
@@ -23,9 +23,9 @@ title: Team Sync HTTP API
# Team Sync API
-> Team Sync is only available in Grafana Enterprise. Read more about [Grafana Enterprise]({{< relref "/docs/grafana/latest/introduction/grafana-enterprise" >}}).
+> Team Sync is only available in Grafana Enterprise. Read more about [Grafana Enterprise](/docs/grafana/latest/introduction/grafana-enterprise/).
-> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions]({{< relref "/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes" >}}) for more information.
+> If you are running Grafana Enterprise, for some endpoints you'll need to have specific permissions. Refer to [Role-based access control permissions](/docs/grafana/latest/administration/roles-and-permissions/access-control/custom-role-actions-scopes/) for more information.
## Get External Groups
@@ -33,7 +33,7 @@ title: Team Sync HTTP API
**Required permissions**
-See note in the [introduction]({{< ref "#external-group-synchronization-api" >}}) for an explanation.
+See note in the [introduction](#external-group-synchronization-api) for an explanation.
| Action | Scope |
| ---------------------- | -------- |
@@ -75,7 +75,7 @@ Status Codes:
**Required permissions**
-See note in the [introduction]({{< ref "#external-group-synchronization-api" >}}) for an explanation.
+See note in the [introduction](#external-group-synchronization-api) for an explanation.
| Action | Scope |
| ----------------------- | -------- |
@@ -117,7 +117,7 @@ Status Codes:
**Required permissions**
-See note in the [introduction]({{< ref "#external-group-synchronization-api" >}}) for an explanation.
+See note in the [introduction](#external-group-synchronization-api) for an explanation.
| Action | Scope |
| ----------------------- | -------- |
diff --git a/docs/sources/explore/correlations-editor-in-explore.md b/docs/sources/explore/correlations-editor-in-explore.md
index 50053226158..dd0a0ce1936 100644
--- a/docs/sources/explore/correlations-editor-in-explore.md
+++ b/docs/sources/explore/correlations-editor-in-explore.md
@@ -3,6 +3,7 @@ labels:
products:
- enterprise
- oss
+ - cloud
title: Correlations Editor in Explore
weight: 20
---
@@ -13,22 +14,22 @@ weight: 20
The Explore editor is available in 10.1 and later versions. In the editor, transformations is available in Grafana 10.3 and later versions.
{{% /admonition %}}
-Correlations allow users to build a link between any two data sources. For more information about correlations in general, please see the [correlations]({{< relref "../administration/correlations" >}}) topic in the administration page.
+Correlations allow users to build a link between any two data sources. For more information about correlations in general, please see the [correlations](/docs/grafana//administration/correlations/) topic in the administration page.
## Create a correlation
1. In Grafana, navigate to the Explore page.
-1. Select a data source that you would like to be [the source data source]({{< relref "../administration/correlations/correlation-configuration#source-data-source-and-result-field" >}}) for a new correlation.
-1. Run a query producing data in [a supported visualization]({{< relref "../administration/correlations#correlations" >}}).
-1. Click **+ Add** in the top toolbar and select **Add correlation** (you can also select **Correlations Editor** from the [Command Palette]({{< relref "../search#command-palette" >}})).
+1. Select a data source that you would like to be [the source data source](/docs/grafana//administration/correlations/correlation-configuration/#source-data-source-and-result-field) for a new correlation.
+1. Run a query producing data in [a supported visualization](/docs/grafana//administration/correlations/#correlations).
+1. Click **+ Add** in the top toolbar and select **Add correlation** (you can also select **Correlations Editor** from the [Command Palette](/docs/grafana//search/#command-palette)).
1. Explore is now in Correlations Editor mode indicated by a blue border and top bar. You can exit Correlations Editor by clicking **Exit** in the top bar.
1. You can now create the following new correlations for the visualization with links that are attached to the data that you can use to build a new query:
- Logs: links are displayed next to field values inside log details for each log row
- Table: every table cell is a link
1. Click on a link to add a new correlation.
- Links are associated with a field that is used as a [result field of a correlation]({{< relref "../administration/correlations/correlation-configuration" >}}).
-1. In the split view that opens, use the right pane to set up [the target query source of the correlation]({{< relref "../administration/correlations/correlation-configuration#target-query" >}}).
-1. Build a target query using [variables syntax]({{< relref "../dashboards/variables/variable-syntax" >}}) with variables from the list provided at the top of the pane. The list contains sample values from the selected data row.
+ Links are associated with a field that is used as a [result field of a correlation](/docs/grafana//administration/correlations/correlation-configuration/).
+1. In the split view that opens, use the right pane to set up [the target query source of the correlation](/docs/grafana//administration/correlations/correlation-configuration/#target-query).
+1. Build a target query using [variables syntax](/docs/grafana//dashboards/variables/variable-syntax/) with variables from the list provided at the top of the pane. The list contains sample values from the selected data row.
1. Provide a label and description (optional).
A label will be used as the name of the link inside the visualization and can contain variables.
1. Provide transformations (optional; see below for details).
@@ -37,7 +38,7 @@ Correlations allow users to build a link between any two data sources. For more
## Transformations
-Transformations allow you to extract values that exist in a field with other data. For example, using a transformation, you can extract one portion of a log line to use in a correlation. For more details on transformations in correlations, see [Correlations]({{< relref "../administration/correlations/correlation-configuration/#correlation-transformations" >}}).
+Transformations allow you to extract values that exist in a field with other data. For example, using a transformation, you can extract one portion of a log line to use in a correlation. For more details on transformations in correlations, see [Correlations](/docs/grafana//explore/correlations-editor-in-explore/#transformations).
After clicking one of the generated links in the editor mode, you can add transformations by clicking **Add transformation** in the Transformations dropdown menu.
@@ -47,7 +48,7 @@ You can use a transformation in your correlation with the following steps:
Select the portion of the field that you want to use for the transformation. For example, a log line.
Once selected, the value of this field will be used to assist you in building the transformation.
1. Select the type of the transformation.
- See [correlations]({{< relref "../administration/correlations/correlation-configuration/#correlation-transformations" >}}) for the options and relevant settings.
+ See [correlations](/docs/grafana//explore/correlations-editor-in-explore/#transformations) for the options and relevant settings.
1. Based on your selection, you might see one or more variables populate, or you might need to provide more specifications in options that are displayed.
1. Select **Add transformation to correlation** to add the specified variables to the list of available variables.
@@ -57,7 +58,7 @@ For regular expressions in this dialog box, the `mapValue` referred to in other
## Correlations examples
-The following examples show how to create correlations using the Correlations Editor in Explore. If you'd like to follow these examples, make sure to set up a [test data source]({{< relref "../datasources/testdata#testdata-data-source" >}}).
+The following examples show how to create correlations using the Correlations Editor in Explore. If you'd like to follow these examples, make sure to set up a [test data source](/docs/grafana//datasources/testdata/#testdata-data-source).
### Create a text to graph correlation
@@ -65,7 +66,7 @@ This example shows how to create a correlation using Correlations Editor in Expl
Correlations allow you to use results of one query to run a new query in any data source. In this example, you will run a query that renders tabular data. The data will be used to run a different query that yields a graph result.
-To follow this example, make sure you have set up [a test data source]({{< relref "../datasources/testdata#testdata-data-source" >}}).
+To follow this example, make sure you have set up [a test data source](/docs/grafana//datasources/testdata/#testdata-data-source).
1. In Grafana, navigate to **Explore**.
1. Select the **test data source** from the dropdown menu at the top left of the page.
@@ -100,7 +101,7 @@ You can apply the same steps to any data source. Correlations allow you to creat
In this example, you will create a correlation to demonstrate how to use transformations to extract values from the log line and another field.
-To follow this example, make sure you have set up [a test data source]({{< relref "../datasources/testdata#testdata-data-source" >}}).
+To follow this example, make sure you have set up [a test data source](/docs/grafana//datasources/testdata/#testdata-data-source).
1. In Grafana, navigate to **Explore**.
1. Select the **test data source** from the dropdown menu at the top left of the page.
diff --git a/docs/sources/explore/get-started-with-explore.md b/docs/sources/explore/get-started-with-explore.md
index 7e78e4e80c3..b25f855bac9 100644
--- a/docs/sources/explore/get-started-with-explore.md
+++ b/docs/sources/explore/get-started-with-explore.md
@@ -38,14 +38,10 @@ Watch the following video to get started using Explore:
## Before you begin
-In order to access Explore, you must have either the `editor` or `administrator` role, unless the [`viewers_can_edit` option](https://grafana.com/docs/grafana//setup-grafana/configure-grafana/#viewers_can_edit) is enabled. Refer to [Role and permissions](https://grafana.com/docs/grafana//administration/roles-and-permissions/) for more information on what each role can access.
+In order to access Explore, you must have either the `editor` or `administrator` basic role or the `data sources explore` role. Refer to [Role and permissions](https://grafana.com/docs/grafana//administration/roles-and-permissions/) for more information on what each role can access.
Refer to [Role-based access control (RBAC)](https://grafana.com/docs/grafana//administration/roles-and-permissions/access-control/) in Grafana Enterprise to understand how you can manage Explore with role-based permissions.
-{{< admonition type="note" >}}
-If you are using Grafana Cloud, open a [support ticket in the Cloud Portal](https://grafana.com/auth/sign-in) to enable the `viewers_can_edit` option.
-{{< /admonition >}}
-
## Explore elements
Explore consists of a toolbar, outline, query editor, the ability to add multiple queries, a query history and a query inspector.
diff --git a/docs/sources/explore/simplified-exploration/_index.md b/docs/sources/explore/simplified-exploration/_index.md
index 60612ae02ba..360b37aee5a 100644
--- a/docs/sources/explore/simplified-exploration/_index.md
+++ b/docs/sources/explore/simplified-exploration/_index.md
@@ -8,27 +8,27 @@ title: Simplified exploration
menuTitle: Simplified exploration
weight: 100
hero:
- title: Simplified exploration with the Explore apps
+ title: Simplified exploration with the Drilldown apps
level: 1
width: 100
height: 100
- description: Use Explore Profiles to investigate and identify issues using profiling data.
+ description: Use the Grafana Drilldown apps to investigate and identify issues using telemetry data.
cards:
title_class: pt-0 lh-1
items:
- - title: Explore Metrics
+ - title: Grafana Metrics Drilldown
href: ./metrics/
description: Quickly find related metrics with a few clicks, without needing to write PromQL queries to retrieve metrics.
height: 24
- - title: Explore Logs
+ - title: Grafana Logs Drilldown
href: ./logs/
description: Visualize log volumes to easily detect anomalies or significant changes over time, without needing to compose LogQL queries.
height: 24
- - title: Explore Traces
+ - title: Grafana Traces Drilldown
href: ./traces/
description: Use Rate, Errors, and Duration (RED) metrics derived from traces to investigate and understand errors and latency issues within complex distributed systems.
height: 24
- - title: Explore Profiles
+ - title: Grafana Profiles Drilldown
href: ./profiles/
description: View and analyze high-level service performance, identify problem processes for optimization, and diagnose issues to determine root causes.
height: 24
@@ -36,14 +36,16 @@ cards:
# Simplified exploration
-The Grafana Explore apps are designed for effortless data exploration through intuitive, queryless interactions.
+The Grafana Drilldown apps are designed for effortless data exploration through intuitive, queryless interactions.
Easily explore telemetry signals with these specialized tools, tailored specifically for the Grafana databases to provide quick and accurate insights.
+{{< docs/shared source="grafana" lookup="plugins/rename-note.md" version="" >}}
+
To learn more, read:
- [From multi-line queries to no-code investigations: meeting Grafana users where they are](https://grafana.com/blog/2024/10/22/from-multi-line-queries-to-no-code-investigations-meeting-grafana-users-where-they-are/)
-- [A queryless experience for exploring metrics, logs, traces, and profiles: Introducing the Explore apps suite for Grafana](https://grafana.com/blog/2024/09/24/queryless-metrics-logs-traces-profiles/).
+- [A queryless experience for exploring metrics, logs, traces, and profiles: Introducing the Drilldown apps suite for Grafana](https://grafana.com/blog/2024/09/24/queryless-metrics-logs-traces-profiles/).
{{< youtube id="MSHeWWsHaIA" >}}
diff --git a/docs/sources/explore/simplified-exploration/metrics/index.md b/docs/sources/explore/simplified-exploration/metrics/index.md
index 127dd6cb265..eb6d23509e5 100644
--- a/docs/sources/explore/simplified-exploration/metrics/index.md
+++ b/docs/sources/explore/simplified-exploration/metrics/index.md
@@ -4,19 +4,21 @@ labels:
- cloud
- enterprise
- oss
-title: Explore Metrics
+title: Metrics Drilldown
aliases:
- ../explore-metrics/ # /docs/grafana/latest/explore/explore-metrics/
canonical: https://grafana.com/docs/grafana/latest/explore/simplified-exploration/metrics/
-description: Explore Metrics lets you browse Prometheus-compatible metrics using an intuitive, queryless experience.
+description: Grafana Metrics Drilldown lets you browse Prometheus-compatible metrics using an intuitive, queryless experience.
weight: 200
---
-# Grafana Explore Metrics
+# Grafana Metrics Drilldown
-Grafana Explore Metrics is a query-less experience for browsing **Prometheus-compatible** metrics. Quickly find related metrics with just a few simple clicks, without needing to write PromQL queries to retrieve metrics.
+Grafana Metrics Drilldown is a query-less experience for browsing **Prometheus-compatible** metrics. Quickly find related metrics with just a few simple clicks, without needing to write PromQL queries to retrieve metrics.
-With Explore Metrics, you can:
+{{< docs/shared source="grafana" lookup="plugins/rename-note.md" version="" >}}
+
+With Metrics Drilldown, you can:
- Easily segment metrics based on their labels, so you can immediately spot anomalies and identify issues.
- Automatically display the optimal visualization for each metric type (gauge vs. counter, for example) without manual setup.
@@ -25,26 +27,25 @@ With Explore Metrics, you can:
- View a history of user steps when navigating through metrics and their filters.
- Seamlessly pivot to related telemetry, including log data.
-{{< docs/play title="Explore Metrics" url="https://play.grafana.org/explore/metrics/trail?from=now-1h&to=now&var-ds=grafanacloud-demoinfra-prom&var-filters=&refresh=&metricPrefix=all" >}}
+{{< docs/play title="Metrics Drilldown" url="https://play.grafana.org/explore/metrics/trail?from=now-1h&to=now&var-ds=grafanacloud-demoinfra-prom&var-filters=&refresh=&metricPrefix=all" >}}
-You can access Explore Metrics either as a standalone experience or as part of Grafana dashboards.
+You can access Metrics Drilldown either as a standalone experience or as part of Grafana dashboards.
## Standalone experience
-To access Explore Metrics as a standalone experience:
+To access Metrics Drilldown as a standalone experience:
-1. Click the arrow next to **Explore** in the Grafana left-side menu and click **Metrics**. You are taken to an overview page that shows recent metrics, bookmarks, and the option to select a new metric exploration.
-1. To get started with a new exploration, click **+ New metric exploration**.
+1. Click the arrow next to **Drilldown** in the Grafana left-side menu and click **Metrics**. You are taken to an overview page that shows recent metrics, bookmarks, and the option to select a new metric exploration.
+1. To get started with a new exploration, click **Let's start!**.
1. Select **Prometheus** or any Prometheus-compatible data source available in the drop-down menu under **Data source**.
-1. Click **+ Add label** to select a label-value pair from the drop-down menu. You can add multiple label-value pairs. A label type will appear above the selected label with a drop-down list of options from which to choose. For example, if you select the label `container` a drop-down list of available containers appears.
+1. Click **+ Add label** to select a label-value pair from the drop-down menu. You can add multiple label-value pairs. A label type appears above the selected label with a drop-down list of options from which to choose. For example, if you select the label `container` a drop-down list of available containers appears.
1. You can also search for metrics using keywords under **Search metrics** in the search bar.
1. Use the time picker to select a date and time range from the drop-down menu or use an absolute time range.
1. Click the down arrow next to the **Refresh** icon to set a refresh rate from the drop-down menu. The default is `Off`.
-1. Click the **Settings** icon and toggle **Always keep selected metric graph in-view** to keep your main graph always in view on the Breakdown drill-down tab.
The **History** button in the upper left corner tracks every step navigating through metric exploration.
-
+
### Metrics exploration
@@ -54,19 +55,19 @@ To further explore a metric, click **Select** in the upper right corner of the m
- The **Overview** tab provides a description for each metric, as well as the metric `type` and `unit` associated with the metric. It also provides a list of labels associated with the metric. Click on any label to view drill-down visualizations.
- The **Breakdown** tab depicts time series visualizations for each of the label-value pairs for the selected metric. You can further drill down on each label and click **Add to filter** to add the label/value pair into your filters. You can also change the **View** from grid to rows.
-- The **Related metrics** tab depicts related metrics with relevant key words. You can repeat the drill down process for any related metric. Toggle **SHow previews** to preview visualizations.
+- The **Related metrics** tab depicts related metrics with relevant key words. You can repeat the drill down process for any related metric. Toggle **Show previews** to preview visualizations.
-Once you have gathered your metrics exploration data you can:
+After you have gathered your metrics exploration data you can:
-- Click the **Explore** icon on the right side to open the graph in Explore, where you can modify the query or add the graph to a dashboard or incident.
-- Click the **Share** icon on the right side to copy the metric drill down URL to the clipboard so it can be shared.
+- Click the **Open in Explore** icon on the right side to open the graph in Explore, where you can modify the query or add the graph to a dashboard or incident.
+- Click the **Copy URL** icon on the right side to copy the metric drill down URL to the clipboard so it can be shared.
- Click the **Star** icon on the right side to bookmark and save the metrics exploration.
## Dashboard experience
-To access Explore Metrics via a dashboard:
+To access Metrics Drilldown via a dashboard:
1. Navigate to your dashboard.
1. Select a time series panel.
-1. Click the panel menu in the upper right and select **Explore Metrics**. If there are multiple metrics, click on the one you want to explore.
-1. You will see a slide out drawer with the Metrics Experience, starting with the drill down. You can access the standalone experience by clicking **Open** in the upper right.
+1. Click the panel menu in the upper right and select **Metrics Drilldown**. If there are multiple metrics, click on the one you want to explore.
+1. You see a slide out drawer with the Metrics Experience, starting with the drill down. You can access the standalone experience by clicking **Open** in the upper right.
diff --git a/docs/sources/explore/trace-integration.md b/docs/sources/explore/trace-integration.md
index f9b0779b12d..532bb3ca8f2 100644
--- a/docs/sources/explore/trace-integration.md
+++ b/docs/sources/explore/trace-integration.md
@@ -157,7 +157,8 @@ The node graph requires data to be returned from the data source in a specific f
## Service graph
-A service graph visualizes span metrics, including rates, error rates, and durations (RED), along with service relationships. Once the requirements are configured, this pre-configured view is immediately available.
+A service graph visualizes rates, error rates, and durations (RED), along with service relationships.
+After the requirements are configured, this pre-configured view is immediately available.
For additional information refer to the following documentation:
diff --git a/docs/sources/fundamentals/exemplars/index.md b/docs/sources/fundamentals/exemplars/index.md
index 363bc122b47..4181c50cac5 100644
--- a/docs/sources/fundamentals/exemplars/index.md
+++ b/docs/sources/fundamentals/exemplars/index.md
@@ -20,21 +20,31 @@ weight: 800
# Introduction to exemplars
-An exemplar is a specific trace representative of measurement taken in a given time interval. While metrics excel at giving you an aggregated view of your system, traces give you a fine grained view of a single request; exemplars are a way to link the two.
+An exemplar is a specific trace representative of measurement taken in a given time interval.
+While metrics excel at giving you an aggregated view of your system, traces give you a fine grained view of a single request; exemplars are a way to link the two.
-Suppose your company website is experiencing a surge in traffic volumes. While more than eighty percent of the users are able to access the website in under two seconds, some users are experiencing a higher than normal response time resulting in bad user experience.
+Suppose your company website is experiencing a surge in traffic volumes.
+While more than eighty percent of the users are able to access the website in under two seconds, some users are experiencing a higher than normal response time resulting in bad user experience.
-To identify the factors that are contributing to the latency, you must compare a trace for a fast response against a trace for a slow response. Given the vast amount of data in a typical production environment, it will be extremely laborious and time-consuming effort.
+To identify the factors that are contributing to the latency, you must compare a trace for a fast response against a trace for a slow response.
+Given the vast amount of data in a typical production environment, it's an extremely laborious and time-consuming effort.
-Use exemplars to help isolate problems within your data distribution by pinpointing query traces exhibiting high latency within a time interval. Once you localize the latency problem to a few exemplar traces, you can combine it with additional system based information or location properties to perform a root cause analysis faster, leading to quick resolutions to performance issues.
+Use exemplars to help isolate problems within your data distribution by pinpointing query traces exhibiting high latency within a time interval.
+After you localize the latency problem to a few exemplar traces, you can combine it with additional system based information or location properties to perform a root cause analysis faster, leading to quick resolutions to performance issues.
-Support for exemplars is available for the Prometheus data source only. Once you enable the functionality, exemplar data is available by default. For more information on exemplar configuration and how to enable exemplars, refer to [configuring exemplars in the Prometheus data source]({{< relref "../../datasources/prometheus/configure-prometheus-data-source#exemplars" >}}).
+Support for exemplars is available for the Prometheus data source only.
+After you enable the functionality, exemplar data is available by default.
+For more information on exemplar configuration and how to enable exemplars, refer to [configuring exemplars in the Prometheus data source](../../datasources/prometheus/configure-prometheus-data-source/#exemplars).
-Grafana shows exemplars alongside a metric in the Explore view and in dashboards. Each exemplar displays as a highlighted star. You can hover your cursor over an exemplar to view the unique trace ID, which is a combination of a key value pair. To investigate further, click the blue button next to the `traceID` property.
+Grafana shows exemplars alongside a metric in the Explore view and in dashboards.
+Each exemplar displays as a highlighted star.
+You can hover your cursor over an exemplar to view the unique trace ID, which is a combination of a key value pair.
+To investigate further, click the blue button next to the `traceID` property.
{{< figure src="/media/docs/grafana/exemplars/screenshot-exemplars.png" class="docs-image--no-shadow" max-width= "750px" caption="Screenshot showing the detail window of an exemplar" >}}
-Refer to [View exemplar data]({{< relref "#view-exemplar-data" >}}) for instructions on how to drill down and view exemplar trace details from metrics and logs. To know more about exemplars, refer to the blogpost [Intro to exemplars, which enable Grafana Tempo’s distributed tracing at massive scale](/blog/2021/03/31/intro-to-exemplars-which-enable-grafana-tempos-distributed-tracing-at-massive-scale/).
+Refer to [View exemplar data](#view-exemplar-data) for instructions on how to drill down and view exemplar trace details from metrics and logs.
+To know more about exemplars, refer to the blog post [Intro to exemplars, which enable Grafana Tempo’s distributed tracing at massive scale](/blog/2021/03/31/intro-to-exemplars-which-enable-grafana-tempos-distributed-tracing-at-massive-scale/).
## View exemplar data
@@ -42,15 +52,19 @@ When support for exemplar support is enabled for a Prometheus data source, you c
### In Explore
-Explore visualizes exemplar traces as highlighted stars alongside metrics data. For more information on how Explore visualizes trace data, refer to [Tracing in Explore]({{< relref "../../explore/trace-integration" >}}).
+Explore visualizes exemplar traces as highlighted stars alongside metrics data.
+For more information on how Explore visualizes trace data, refer to [Tracing in Explore](../../explore/trace-integration/).
To examine the details of an exemplar trace:
-1. Place your cursor over an exemplar (highlighted star). Depending on the trace data source you are using, you will see a blue button with the label `Query with `. In the following example, the tracing data source is Tempo.
+1. Place your cursor over an exemplar (highlighted star).
+ Depending on the trace data source you are using, you may see a blue button with the label `Query with `.
+ In the following example, the tracing data source is Tempo.
{{< figure src="/media/docs/grafana/exemplars/screenshot-exemplar-details.png" class="docs-image--no-shadow" max-width= "350px" caption="Screenshot showing exemplar details" >}}
-1. Click the **Query with Tempo** option next to the `traceID` property. The trace details, including the spans within the trace are listed in a separate panel on the right.
+1. Click the **Query with Tempo** option next to the `traceID` property.
+ The trace details, including the spans within the trace are listed in a separate panel on the right.
{{< figure src="/media/docs/grafana/exemplars/screenshot-exemplar-explore-view.png" class="docs-image--no-shadow" max-width= "900px" caption="Explorer view with panel showing trace details" >}}
@@ -58,13 +72,20 @@ For more information on how to drill down and analyze the trace and span details
### In logs
-You can also view exemplar trace details from the Loki logs in Explore. Use regex within the Derived fields links for Loki to extract the `traceID` information. Now when you expand Loki logs, you can see a `traceID` property under the **Detected fields** section. To learn more about how to extract a part of a log message into an internal or external link, refer to [using derived fields in Loki]({{< relref "../../explore/logs-integration" >}}).
+You can also view exemplar trace details from the Loki logs in Explore.
+Use regular expressions within the Derived fields links for Loki to extract the `traceID` information.
+Now when you expand Loki logs, you can see a `traceID` property under the **Detected fields** section.
+To learn more about how to extract a part of a log message into an internal or external link, refer to [using derived fields in Loki](../../explore/logs-integration/).
To view the details of an exemplar trace:
-1. Expand a log line and scroll down to the `Fields` section. Depending on your backend trace data source, you will see a blue button with the label ``.
+1. Expand a log line and scroll down to the `Fields` section.
+ Depending on your backend trace data source, you may see a blue button with the label ``.
-1. Click the blue button next to the `traceID` property. Typically, it will have the name of the backend data source. In the following example, the tracing data source is Tempo. The trace details, including the spans within the trace are listed in a separate panel on the right.
+1. Click the blue button next to the `traceID` property.
+ Typically, it has the name of the backend data source.
+ In the following example, the tracing data source is Tempo.
+ The trace details, including the spans within the trace are listed in a separate panel on the right.
{{< figure src="/media/docs/grafana/exemplars/screenshot-exemplar-loki-logs.png" class="docs-image--no-shadow" max-width= "750px" caption="Explorer view with panel showing trace details" >}}
@@ -78,16 +99,20 @@ This panel shows the details of the trace in different segments.
You can add more traces to the results using the `Add query` button.
-- The next segment shows the entire span for the specific trace as a narrow strip. All levels of the trace from the client all the way down to database query is displayed, which provides a bird's eye view of the time distribution across all layers over which the HTTP request was processed.
+- The next segment shows the entire span for the specific trace as a narrow strip.
+ All levels of the trace from the client all the way down to database query is displayed, which provides a bird's eye view of the time distribution across all layers over which the HTTP request was processed.
1. You can click within this strip view to display a magnified view of a smaller time segment within the span. This magnified view shows up in the bottom segment of the panel.
1. In the magnified view, you can expand or collapse the various levels of the trace to drill down to the specific span of interest.
- For example, if the strip view shows that most of the latency was within the app layer, you can expand the trace down the app layer to investigate the problem further. To expand a particular layer of span, click the left icon. The same button can collapse an expanded span.
+ For example, if the strip view shows that most of the latency was within the app layer, you can expand the trace down the app layer to investigate the problem further.
+ To expand a particular layer of span, click the left icon.
+ The same button can collapse an expanded span.
- To see the details of the span at any level, click the span itself.
- This displays additional metadata associated with the span. The metadata itself is initially shown in a narrow strip but you can see more details by clicking the metadata strip.
+ This displays additional metadata associated with the span.
+ The metadata itself is initially shown in a narrow strip but you can see more details by clicking the metadata strip.
{{< figure src="/media/docs/grafana/exemplars/screenshot-exemplar-span-details.png" class="docs-image--no-shadow" max-width= "600px" caption="Span details" >}}
diff --git a/docs/sources/getting-started/_index.md b/docs/sources/getting-started/_index.md
index 6252d05cd40..752757401dd 100644
--- a/docs/sources/getting-started/_index.md
+++ b/docs/sources/getting-started/_index.md
@@ -14,6 +14,6 @@ weight: 9
Grafana helps you collect, correlate, and visualize data with beautiful dashboards — the open source data visualization and monitoring solution that drives informed decisions, enhances system performance, and streamlines troubleshooting.
-This section provides guidance to our open source community about how to build your first dashboard after you have installed Grafana. It also provides step-by-step instructions on how to add a Prometheus, InfluxDB, or an MS SQL Server data source. If you are connecting a different data source, please refer to our complete list of supported [Data sources]({{< relref "../datasources" >}}). If you would like to learn how to get started with Grafana Cloud, our fully managed observability stack, visit the [Grafana Cloud documentation](https://grafana.com/docs/grafana-cloud/quickstart/) for more information.
+This section provides guidance to our open source community about how to build your first dashboard after you have installed Grafana. It also provides step-by-step instructions on how to add a Prometheus, InfluxDB, or an MS SQL Server data source. If you are connecting a different data source, please refer to our complete list of supported [Data sources](../datasources/). If you would like to learn how to get started with Grafana Cloud, our fully managed observability stack, visit the [Grafana Cloud documentation](https://grafana.com/docs/grafana-cloud/quickstart/) for more information.
{{< section >}}
diff --git a/docs/sources/getting-started/get-started-grafana-influxdb.md b/docs/sources/getting-started/get-started-grafana-influxdb.md
index d6a163a1219..fed06324346 100644
--- a/docs/sources/getting-started/get-started-grafana-influxdb.md
+++ b/docs/sources/getting-started/get-started-grafana-influxdb.md
@@ -38,11 +38,11 @@ Windows users might need to make additional adjustments. Look for special instru
You can have more than one InfluxDB data source defined in Grafana.
-1. Follow the general instructions to [add a data source]({{< relref "../datasources#add-a-data-source" >}}).
+1. Follow the general instructions to [add a data source](../../datasources/#add-a-data-source).
1. Decide if you will use InfluxQL or Flux as your query language.
- - [Configure the data source]({{< relref "../datasources/influxdb#configure-the-data-source" >}}) for your chosen query language.
+ - [Configure the data source](../../datasources/influxdb/#configure-the-data-source) for your chosen query language.
Each query language has its own unique data source settings.
- - For querying features specific to each language, see the data source's [query editor documentation]({{< relref "../datasources/influxdb/query-editor" >}}).
+ - For querying features specific to each language, see the data source's [query editor documentation](../../datasources/influxdb/query-editor/).
##### InfluxDB guides
@@ -75,8 +75,8 @@ Grafana displays a list of possible series. Click one to select it, and Grafana
Create a simple Flux query.
-1. [Add a panel]({{< relref "../dashboards/build-dashboards/create-dashboard" >}}).
-1. In the query editor, select your InfluxDB-Flux data source. For more information, refer to [Queries]({{< relref "../panels-visualizations/query-transform-data" >}}).
+1. [Add a panel](../../dashboards/build-dashboards/create-dashboard/).
+1. In the query editor, select your InfluxDB-Flux data source. For more information, refer to [Queries](../../panels-visualizations/query-transform-data/).
1. Select the **Table** visualization.
1. In the query editor text field, enter `buckets()` and then click outside of the query editor.
@@ -96,12 +96,12 @@ You can also create Flux queries in the InfluxDB Explore view.

-1. In Grafana, [add a panel]({{< relref "../dashboards/build-dashboards/create-dashboard" >}}) and then paste your Flux code into the query editor.
+1. In Grafana, [add a panel](../../dashboards/build-dashboards/create-dashboard/) and then paste your Flux code into the query editor.
1. Click **Apply**. Your new panel should be visible with data from your Flux query.
#### Check InfluxDB metrics in Grafana Explore
-In your Grafana instance, go to the [Explore]({{< relref "../explore" >}}) view and build queries to experiment with the metrics you want to monitor. Here you can also debug issues related to collecting metrics.
+In your Grafana instance, go to the [Explore](../../explore/) view and build queries to experiment with the metrics you want to monitor. Here you can also debug issues related to collecting metrics.
#### Start building dashboards
@@ -109,5 +109,5 @@ There you go! Use Explore and Data Explorer to experiment with your data, and ad
Here are some resources to learn more:
-- Grafana documentation: [InfluxDB data source]({{< relref "../datasources/influxdb" >}})
+- Grafana documentation: [InfluxDB data source](../../datasources/influxdb/)
- InfluxDB documentation: [Comparison of Flux vs InfluxQL](https://docs.influxdata.com/influxdb/v1.8/flux/flux-vs-influxql/)
diff --git a/docs/sources/getting-started/get-started-grafana-ms-sql-server.md b/docs/sources/getting-started/get-started-grafana-ms-sql-server.md
index 2ca4dcac2b4..9b714940d4b 100644
--- a/docs/sources/getting-started/get-started-grafana-ms-sql-server.md
+++ b/docs/sources/getting-started/get-started-grafana-ms-sql-server.md
@@ -24,7 +24,7 @@ MS SQL Server can be installed on Windows or Linux operating systems and also on
You can install MS SQL Server on the host running Grafana or on a remote server. To install the software from the [downloads page](https://www.microsoft.com/en-us/sql-server/sql-server-downloads), follow their setup prompts.
-If you are on a Windows host but want to use Grafana and MS SQL data source on a Linux environment, refer to the [WSL to set up your Grafana development environment](/blog/2021/03/03/.how-to-set-up-a-grafana-development-environment-on-a-windows-pc-using-wsl). This will allow you to leverage the resources available in [grafana/grafana](https://github.com/grafana/grafana) GitHub repository. Here you will find a collection of supported data sources, including MS SQL Server, along with test data and pre-configured dashboards for use.
+If you are on a Windows host but want to use Grafana and MS SQL data source on a Linux environment, refer to the [WSL to set up your Grafana development environment](/blog/2021/03/03/how-to-set-up-a-grafana-development-environment-on-a-windows-pc-using-wsl) blog post. This will allow you to leverage the resources available in [grafana/grafana](https://github.com/grafana/grafana) GitHub repository. Here you will find a collection of supported data sources, including MS SQL Server, along with test data and pre-configured dashboards for use.
#### Add the MS SQL data source
@@ -99,6 +99,6 @@ Optionally, play around this dashboard and customize it to:
Now that you have gained some idea of using the pre-packaged MS SQL data source and some test data, the next step is to setup your own instance of MS SQL Server database and data your development or sandbox area.
-To fetch data from your own instance of MS SQL Server, add the data source using instructions in Step 4 of this topic. In Grafana [Explore]({{< relref "../explore" >}}) build queries to experiment with the metrics you want to monitor.
+To fetch data from your own instance of MS SQL Server, add the data source using instructions in Step 4 of this topic. In Grafana [Explore](../../explore/) build queries to experiment with the metrics you want to monitor.
-Once you have a curated list of queries, create [dashboards]({{< relref "../dashboards" >}}) to render metrics from the SQL Server database. For troubleshooting, user permissions, known issues, and query examples, refer to [Using Microsoft SQL Server in Grafana]({{< relref "../datasources/mssql" >}}).
+Once you have a curated list of queries, create [dashboards](../../dashboards/) to render metrics from the SQL Server database. For troubleshooting, user permissions, known issues, and query examples, refer to [Using Microsoft SQL Server in Grafana](../../datasources/mssql/).
diff --git a/docs/sources/getting-started/get-started-grafana-prometheus.md b/docs/sources/getting-started/get-started-grafana-prometheus.md
index 1ed833b034a..188460d7896 100644
--- a/docs/sources/getting-started/get-started-grafana-prometheus.md
+++ b/docs/sources/getting-started/get-started-grafana-prometheus.md
@@ -114,11 +114,11 @@ To configure your Prometheus instance to work with Grafana locally instead of Gr
#### Check Prometheus metrics in Grafana Explore view
-In your Grafana instance, go to the [Explore]({{< relref "../explore" >}}) view and build queries to experiment with the metrics you want to monitor. Here you can also debug issues related to collecting metrics from Prometheus.
+In your Grafana instance, go to the [Explore](../../explore/) view and build queries to experiment with the metrics you want to monitor. Here you can also debug issues related to collecting metrics from Prometheus.
#### Start building dashboards
-Now that you have a curated list of queries, create [dashboards]({{< relref "../dashboards" >}}) to render system metrics monitored by Prometheus. When you install Prometheus and node_exporter or windows_exporter, you will find recommended dashboards for use.
+Now that you have a curated list of queries, create [dashboards](../../dashboards/) to render system metrics monitored by Prometheus. When you install Prometheus and node_exporter or windows_exporter, you will find recommended dashboards for use.
The following image shows a dashboard with three panels showing some system metrics.
@@ -126,5 +126,5 @@ The following image shows a dashboard with three panels showing some system metr
To learn more:
-- Grafana documentation: [Prometheus data source]({{< relref "../datasources/prometheus" >}})
+- Grafana documentation: [Prometheus data source](../../datasources/prometheus/)
- Prometheus documentation: [What is Prometheus?](https://prometheus.io/docs/introduction/overview/)
diff --git a/docs/sources/introduction/_index.md b/docs/sources/introduction/_index.md
index 0c64bc5f355..9aba0f1cd48 100644
--- a/docs/sources/introduction/_index.md
+++ b/docs/sources/introduction/_index.md
@@ -16,35 +16,35 @@ weight: 5
[Grafana open source software](/oss/) enables you to query, visualize, alert on, and explore your metrics, logs, and traces wherever they are stored. Grafana OSS provides you with tools to turn your time-series database (TSDB) data into insightful graphs and visualizations. The Grafana OSS plugin framework also enables you to connect other data sources like NoSQL/SQL databases, ticketing tools like Jira or ServiceNow, and CI/CD tooling like GitLab.
-After you have [installed Grafana]({{< relref "../setup-grafana/installation" >}}) and set up your first dashboard using instructions in [Getting started with Grafana]({{< relref "../getting-started/build-first-dashboard" >}}), you will have many options to choose from depending on your requirements. For example, if you want to view weather data and statistics about your smart home, then you can create a [playlist]({{< relref "../dashboards/create-manage-playlists" >}}). If you are the administrator for an enterprise and are managing Grafana for multiple teams, then you can set up [provisioning]({{< relref "../administration/provisioning" >}}) and [authentication]({{< relref "../setup-grafana/configure-security/configure-authentication" >}}).
+After you have [installed Grafana](../setup-grafana/installation/) and set up your first dashboard using instructions in [Getting started with Grafana](../getting-started/build-first-dashboard/), you will have many options to choose from depending on your requirements. For example, if you want to view weather data and statistics about your smart home, then you can create a [playlist](../dashboards/create-manage-playlists/). If you are the administrator for an enterprise and are managing Grafana for multiple teams, then you can set up [provisioning](../administration/provisioning/) and [authentication](../setup-grafana/configure-security/configure-authentication/).
The following sections provide an overview of Grafana features and links to product documentation to help you learn more. For more guidance and ideas, check out our [Grafana Community forums](https://community.grafana.com/).
## Explore metrics, logs, and traces
-Explore your data through ad-hoc queries and dynamic drilldown. Split view and compare different time ranges, queries and data sources side by side. Refer to [Explore]({{< relref "../explore" >}}) for more information.
+Explore your data through ad-hoc queries and dynamic drilldown. Split view and compare different time ranges, queries and data sources side by side. Refer to [Explore](../explore/) for more information.
## Alerts
If you're using Grafana Alerting, then you can have alerts sent through a number of different alert notifiers, including PagerDuty, SMS, email, VictorOps, OpsGenie, or Slack.
-Alert hooks allow you to create different notifiers with a bit of code if you prefer some other channels of communication. Visually define [alert rules]({{< relref "../alerting/alerting-rules" >}}) for your most important metrics.
+Alert hooks allow you to create different notifiers with a bit of code if you prefer some other channels of communication. Visually define [alert rules](../alerting/alerting-rules/) for your most important metrics.
## Annotations
Annotate graphs with rich events from different data sources. Hover over events to see the full event metadata and tags.
-This feature, which shows up as a graph marker in Grafana, is useful for correlating data in case something goes wrong. You can create the annotations manually—just control-click on a graph and input some text—or you can fetch data from any data source. Refer to [Annotations]({{< relref "../dashboards/build-dashboards/annotate-visualizations" >}}) for more information.
+This feature, which shows up as a graph marker in Grafana, is useful for correlating data in case something goes wrong. You can create the annotations manually—just control-click on a graph and input some text—or you can fetch data from any data source. Refer to [Annotations](../dashboards/build-dashboards/annotate-visualizations/) for more information.
## Dashboard variables
-[Template variables]({{< relref "../dashboards/variables" >}}) allow you to create dashboards that can be reused for lots of different use cases. Values aren't hard-coded with these templates, so for instance, if you have a production server and a test server, you can use the same dashboard for both.
+[Template variables](../dashboards/variables/) allow you to create dashboards that can be reused for lots of different use cases. Values aren't hard-coded with these templates, so for instance, if you have a production server and a test server, you can use the same dashboard for both.
Templating allows you to drill down into your data, say, from all data to North America data, down to Texas data, and beyond. You can also share these dashboards across teams within your organization—or if you create a great dashboard template for a popular data source, you can contribute it to the whole community to customize and use.
## Configure Grafana
-If you're a Grafana administrator, then you'll want to thoroughly familiarize yourself with [Grafana configuration options]({{< relref "../setup-grafana/configure-grafana" >}}) and the [Grafana CLI]({{< relref "../cli" >}}).
+If you're a Grafana administrator, then you'll want to thoroughly familiarize yourself with [Grafana configuration options](../setup-grafana/configure-grafana/) and the [Grafana CLI](../cli/).
Configuration covers both config files and environment variables. You can set up default ports, logging levels, email IP addresses, security, and more.
@@ -54,19 +54,19 @@ Discover hundreds of [dashboards](/grafana/dashboards) and [plugins](/grafana/pl
## Authentication
-Grafana supports different authentication methods, such as LDAP and OAuth, and allows you to map users to organizations. Refer to the [User authentication overview]({{< relref "../setup-grafana/configure-security/configure-authentication" >}}) for more information.
+Grafana supports different authentication methods, such as LDAP and OAuth, and allows you to map users to organizations. Refer to the [User authentication overview](../setup-grafana/configure-security/configure-authentication/) for more information.
-In Grafana Enterprise, you can also map users to teams: If your company has its own authentication system, Grafana allows you to map the teams in your internal systems to teams in Grafana. That way, you can automatically give people access to the dashboards designated for their teams. Refer to [Grafana Enterprise]({{< relref "./grafana-enterprise" >}}) for more information.
+In Grafana Enterprise, you can also map users to teams: If your company has its own authentication system, Grafana allows you to map the teams in your internal systems to teams in Grafana. That way, you can automatically give people access to the dashboards designated for their teams. Refer to [Grafana Enterprise](grafana-enterprise/) for more information.
## Provisioning
While it's easy to click, drag, and drop to create a single dashboard, power users in need of many dashboards will want to automate the setup with a script. You can script anything in Grafana.
-For example, if you're spinning up a new Kubernetes cluster, you can also spin up a Grafana automatically with a script that would have the right server, IP address, and data sources preset and locked in so users cannot change them. It's also a way of getting control over a lot of dashboards. Refer to [Provisioning]({{< relref "../administration/provisioning" >}}) for more information.
+For example, if you're spinning up a new Kubernetes cluster, you can also spin up a Grafana automatically with a script that would have the right server, IP address, and data sources preset and locked in so users cannot change them. It's also a way of getting control over a lot of dashboards. Refer to [Provisioning](../administration/provisioning/) for more information.
## Permissions
-When organizations have one Grafana and multiple teams, they often want the ability to both keep things separate and share dashboards. You can create a team of users and then set permissions on [folders and dashboards]({{< relref "../administration/user-management/manage-dashboard-permissions" >}}), and down to the [data source level]({{< relref "../administration/data-source-management#data-source-permissions" >}}) if you're using [Grafana Enterprise]({{< relref "./grafana-enterprise" >}}).
+When organizations have one Grafana and multiple teams, they often want the ability to both keep things separate and share dashboards. You can create a team of users and then set permissions on [folders and dashboards](../administration/user-management/manage-dashboard-permissions/), and down to the [data source level](../administration/data-source-management/#data-source-permissions) if you're using [Grafana Enterprise](grafana-enterprise/).
## Other Grafana Labs OSS Projects
diff --git a/docs/sources/introduction/grafana-enterprise.md b/docs/sources/introduction/grafana-enterprise.md
index 7de85993dc6..15db695b9bc 100644
--- a/docs/sources/introduction/grafana-enterprise.md
+++ b/docs/sources/introduction/grafana-enterprise.md
@@ -13,7 +13,7 @@ weight: 200
Grafana Enterprise is a commercial edition of Grafana that includes additional features not found in the open source version.
-Building on everything you already know and love about Grafana open source, Grafana Enterprise includes [exclusive datasource plugins]({{< relref "#enterprise-data-sources" >}}) and [additional features]({{< relref "#enterprise-features" >}}). You also get 24x7x365 support and training from the core Grafana team.
+Building on everything you already know and love about Grafana open source, Grafana Enterprise includes [exclusive data source plugins](#enterprise-data-sources) and [additional features](#enterprise-features). You also get 24x7x365 support and training from the core Grafana team.
To learn more about Grafana Enterprise, refer to [our product page](/enterprise).
@@ -21,7 +21,7 @@ To learn more about Grafana Enterprise, refer to [our product page](/enterprise)
Many Grafana Enterprise features are also available in [Grafana Cloud](/docs/grafana-cloud) Free, Pro, and Advanced accounts. For details, refer to [Grafana Cloud pricing](/pricing/#featuresTable).
-To migrate to Grafana Cloud, refer to [Migrate from Grafana Enterprise to Grafana Cloud](/docs/grafana-cloud/account-management/e2c-guide/).
+To migrate to Grafana Cloud, refer to [Migrate from Grafana Enterprise to Grafana Cloud](/docs/grafana//administration/migration-guide/)
## Authentication
@@ -29,48 +29,48 @@ Grafana Enterprise includes integrations with more ways to authenticate your use
### Team sync
-[Team sync]({{< relref "../setup-grafana/configure-security/configure-team-sync" >}}) allows you to set up synchronization between teams in Grafana and teams in your auth provider so that your users automatically end up in the right team.
+[Team sync](/docs/grafana//setup-grafana/configure-security/configure-team-sync/) allows you to set up synchronization between teams in Grafana and teams in your auth provider so that your users automatically end up in the right team.
Supported auth providers:
-- [Auth Proxy]({{< relref "../setup-grafana/configure-security/configure-authentication/auth-proxy#team-sync-enterprise-only" >}})
-- [Azure AD](https://grafana.com/docs/grafana//configure-security/configure-authentication/azuread#group-sync-enterprise-only)
-- [Generic OAuth integration](https://grafana.com/docs/grafana//configure-security/configure-authentication/generic-oauth#configure-group-synchronization" >}})
-- [GitHub OAuth](https://grafana.com/docs/grafana//configure-security/configure-authentication/github#configure-group-synchronization)
-- [GitLab OAuth](https://grafana.com/docs/grafana//configure-security/configure-authentication/gitlab#configure-group-synchronization)
-- [Google OAuth](https://grafana.com/docs/grafana//configure-security/configure-authentication/google#configure-group-synchronization)
-- [LDAP](https://grafana.com/docs/grafana//configure-security/configure-authentication/enhanced-ldap#ldap-group-synchronization)
-- [Okta](https://grafana.com/docs/grafana//configure-security/configure-authentication/okta#configure-group-synchronization-enterprise-only)
-- [SAML](https://grafana.com/docs/grafana//configure-security/configure-authentication/saml#configure-group-synchronization)
+- [Auth Proxy](https://grafana.com/docs/grafana//setup-grafana/configure-security/configure-authentication/auth-proxy#team-sync-enterprise-only)
+- [Azure AD](https://grafana.com/docs/grafana//setup-grafana/configure-security/configure-authentication/azuread#group-sync-enterprise-only)
+- [Generic OAuth integration](https://grafana.com/docs/grafana//setup-grafana/configure-security/configure-authentication/generic-oauth#configure-group-synchronization)
+- [GitHub OAuth](https://grafana.com/docs/grafana//setup-grafana/configure-security/configure-authentication/github#configure-group-synchronization)
+- [GitLab OAuth](https://grafana.com/docs/grafana//setup-grafana/configure-security/configure-authentication/gitlab#configure-group-synchronization)
+- [Google OAuth](https://grafana.com/docs/grafana//setup-grafana/configure-security/configure-authentication/google#configure-group-synchronization)
+- [LDAP](https://grafana.com/docs/grafana//setup-grafana/configure-security/configure-authentication/enhanced-ldap#ldap-group-synchronization)
+- [Okta](https://grafana.com/docs/grafana//setup-grafana/configure-security/configure-authentication/okta#configure-group-synchronization-enterprise-only)
+- [SAML](https://grafana.com/docs/grafana/