From 7a026d90e912bfc14a1cddea292a647ace8c3ea8 Mon Sep 17 00:00:00 2001 From: Andres Martinez Gotor Date: Mon, 16 Jan 2023 17:47:27 +0100 Subject: [PATCH] AzureMonitor: Set multiple resources for Logs (#61545) --- .../__mocks__/query.ts | 2 +- .../azure_log_analytics_datasource.test.ts | 24 +++++++++---------- .../azure_log_analytics_datasource.ts | 8 +++---- .../azure_monitor_datasource.test.ts | 2 +- .../LogsQueryEditor/LogsQueryEditor.tsx | 6 ++++- .../components/LogsQueryEditor/QueryField.tsx | 6 ++--- .../LogsQueryEditor/useMigrations.ts | 2 +- .../components/ResourcePicker/utils.test.ts | 2 +- .../components/ResourcePicker/utils.ts | 2 +- .../grafanaTemplateVariableFns.ts | 2 +- .../grafanaTemplateVariables.test.ts | 2 +- .../types/query.ts | 5 +++- .../utils/migrateAnnotation.test.ts | 3 ++- .../utils/migrateAnnotation.ts | 2 +- .../utils/migrateQuery.test.ts | 12 ++++++++++ .../utils/migrateQuery.ts | 16 +++++++++++++ 16 files changed, 66 insertions(+), 30 deletions(-) diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/__mocks__/query.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/__mocks__/query.ts index 12d14c1f449..4b8d43f11a8 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/__mocks__/query.ts +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/__mocks__/query.ts @@ -17,7 +17,7 @@ export default function createMockQuery(overrides?: Partial): '//change this example to create your own time series query\n //the table to query (e.g. Usage, Heartbeat, Perf)\n| where $__timeFilter(TimeGenerated) //this is a macro used to show the full chart’s time range, choose the datetime column here\n| summarize count() by , bin(TimeGenerated, $__interval) //change “group by column” to a column in your table, such as “Computer”. The $__interval macro is used to auto-select the time grain. Can also use 1h, 5m etc.\n| order by TimeGenerated asc', resultFormat: 'time_series', workspace: 'e3fe4fde-ad5e-4d60-9974-e2f3562ffdf2', - resource: 'test-resource', + resources: ['test-resource'], ...overrides?.azureLogAnalytics, }, diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_log_analytics/azure_log_analytics_datasource.test.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_log_analytics/azure_log_analytics_datasource.test.ts index 3d56a7be3b5..3b4a11b5bf3 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_log_analytics/azure_log_analytics_datasource.test.ts +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_log_analytics/azure_log_analytics_datasource.test.ts @@ -1,5 +1,3 @@ -import { get, set } from 'lodash'; - import { toUtc } from '@grafana/data'; import { TemplateSrv } from 'app/features/templating/template_srv'; @@ -237,7 +235,7 @@ describe('AzureLogAnalyticsDatasource', () => { const ds = new AzureMonitorDatasource(ctx.instanceSettings, templateSrv); query.queryType = AzureQueryType.LogAnalytics; - query.azureLogAnalytics = { resource: `$${singleVariable.name}` }; + query.azureLogAnalytics = { resources: [`$${singleVariable.name}`] }; expect(ds.targetContainsTemplate(query)).toEqual(true); }); @@ -270,7 +268,7 @@ describe('AzureLogAnalyticsDatasource', () => { const query: AzureMonitorQuery = { refId: 'A', azureLogAnalytics: { - resource: '/sub/124/rg/cloud/vm/server', + resources: ['/sub/124/rg/cloud/vm/server'], query: 'perf | take 100', }, }; @@ -303,7 +301,7 @@ describe('AzureLogAnalyticsDatasource', () => { refId: 'A', hide: true, azureLogAnalytics: { - resource: '/sub/124/rg/cloud/vm/server', + resources: ['/sub/124/rg/cloud/vm/server'], query: 'perf | take 100', }, }; @@ -315,7 +313,7 @@ describe('AzureLogAnalyticsDatasource', () => { const query: AzureMonitorQuery = { refId: 'A', azureLogAnalytics: { - resource: '/sub/124/rg/cloud/vm/server', + resources: ['/sub/124/rg/cloud/vm/server'], }, }; @@ -352,9 +350,9 @@ describe('AzureLogAnalyticsDatasource', () => { templateSrv.init(Array.from(templateVariables.values()).map((item) => item.templateVariable)); const query = createMockQuery(); const azureLogAnalytics: { [index: string]: any } = {}; - for (const [path, templateVariable] of templateVariables.entries()) { - set(azureLogAnalytics, path, `$${templateVariable.variableName}`); - } + azureLogAnalytics.query = '$query'; + azureLogAnalytics.workspace = '$workspace'; + azureLogAnalytics.resources = ['$resource']; query.queryType = AzureQueryType.LogAnalytics; query.azureLogAnalytics = { ...query.azureLogAnalytics, @@ -362,9 +360,11 @@ describe('AzureLogAnalyticsDatasource', () => { }; const templatedQuery = ctx.ds.interpolateVariablesInQueries([query], {}); expect(templatedQuery[0]).toHaveProperty('datasource'); - for (const [path, templateVariable] of templateVariables.entries()) { - expect(get(templatedQuery[0].azureLogAnalytics, path)).toEqual(templateVariable.templateVariable.current.value); - } + expect(templatedQuery[0].azureLogAnalytics).toMatchObject({ + query: templateVariables.get('query')?.templateVariable.current.value, + workspace: templateVariables.get('workspace')?.templateVariable.current.value, + resources: [templateVariables.get('resource')?.templateVariable.current.value], + }); }); }); }); diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_log_analytics/azure_log_analytics_datasource.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_log_analytics/azure_log_analytics_datasource.ts index 0fb89e1060c..42984e611b8 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_log_analytics/azure_log_analytics_datasource.ts +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_log_analytics/azure_log_analytics_datasource.ts @@ -66,7 +66,7 @@ export default class AzureLogAnalyticsDatasource extends DataSourceWithBackend< return ( item.hide !== true && !!item.azureLogAnalytics?.query && - (!!item.azureLogAnalytics.resource || !!item.azureLogAnalytics.workspace) + (!!item.azureLogAnalytics.resources?.length || !!item.azureLogAnalytics.workspace) ); } @@ -124,10 +124,10 @@ export default class AzureLogAnalyticsDatasource extends DataSourceWithBackend< } const templateSrv = getTemplateSrv(); - const resource = templateSrv.replace(item.resource, scopedVars); + const resources = item.resources?.map((r) => templateSrv.replace(r, scopedVars)); let workspace = templateSrv.replace(item.workspace, scopedVars); - if (!workspace && !resource && this.firstWorkspace) { + if (!workspace && !resources && this.firstWorkspace) { workspace = this.firstWorkspace; } @@ -140,7 +140,7 @@ export default class AzureLogAnalyticsDatasource extends DataSourceWithBackend< azureLogAnalytics: { resultFormat: item.resultFormat, query, - resource, + resources, // Workspace was removed in Grafana 8, but remains for backwards compat workspace, diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_monitor/azure_monitor_datasource.test.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_monitor/azure_monitor_datasource.test.ts index 622bdfc88ea..98934049c87 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_monitor/azure_monitor_datasource.test.ts +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_monitor/azure_monitor_datasource.test.ts @@ -924,7 +924,7 @@ describe('AzureMonitorDatasource', () => { const ds = new AzureMonitorDatasource(ctx.instanceSettings, templateSrv); query.queryType = AzureQueryType.AzureMonitor; - query.azureLogAnalytics = { resource: `$${singleVariable.name}` }; + query.azureLogAnalytics = { resources: [`$${singleVariable.name}`] }; expect(ds.targetContainsTemplate(query)).toEqual(false); }); }); diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/LogsQueryEditor/LogsQueryEditor.tsx b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/LogsQueryEditor/LogsQueryEditor.tsx index e924cce236b..f6c612caffe 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/LogsQueryEditor/LogsQueryEditor.tsx +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/LogsQueryEditor/LogsQueryEditor.tsx @@ -53,7 +53,11 @@ const LogsQueryEditor: React.FC = ({ ResourceRowType.Resource, ResourceRowType.Variable, ]} - resource={query.azureLogAnalytics?.resource ?? ''} + resource={ + query.azureLogAnalytics?.resources && query.azureLogAnalytics.resources.length + ? query.azureLogAnalytics.resources[0] + : '' + } queryType="logs" /> diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/LogsQueryEditor/QueryField.tsx b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/LogsQueryEditor/QueryField.tsx index 46fceccb2d9..c0ba93b623d 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/LogsQueryEditor/QueryField.tsx +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/LogsQueryEditor/QueryField.tsx @@ -33,12 +33,12 @@ const QueryField: React.FC = ({ query, datasource, o } useEffect(() => { - if (!query.azureLogAnalytics?.resource) { + if (!query.azureLogAnalytics?.resources || !query.azureLogAnalytics.resources.length) { return; } const promises = [ - datasource.azureLogAnalyticsDatasource.getKustoSchema(query.azureLogAnalytics.resource), + datasource.azureLogAnalyticsDatasource.getKustoSchema(query.azureLogAnalytics.resources[0]), getPromise(), ] as const; @@ -56,7 +56,7 @@ const QueryField: React.FC = ({ query, datasource, o worker?.setSchema(schema, 'https://help.kusto.windows.net', 'Samples'); }); }); - }, [datasource.azureLogAnalyticsDatasource, query.azureLogAnalytics?.resource]); + }, [datasource.azureLogAnalyticsDatasource, query.azureLogAnalytics?.resources]); const handleEditorMount = useCallback((editor: MonacoEditor, monaco: Monaco) => { monacoPromiseRef.current?.resolve?.({ editor, monaco }); diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/LogsQueryEditor/useMigrations.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/LogsQueryEditor/useMigrations.ts index 33ba224000e..9c5beb75421 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/LogsQueryEditor/useMigrations.ts +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/LogsQueryEditor/useMigrations.ts @@ -9,7 +9,7 @@ async function migrateWorkspaceQueryToResourceQuery( query: AzureMonitorQuery, onChange: (newQuery: AzureMonitorQuery) => void ) { - if (query.azureLogAnalytics?.workspace !== undefined && !query.azureLogAnalytics.resource) { + if (query.azureLogAnalytics?.workspace !== undefined && !query.azureLogAnalytics.resources) { const isWorkspaceGUID = isGUIDish(query.azureLogAnalytics.workspace); let resource: string; diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/ResourcePicker/utils.test.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/ResourcePicker/utils.test.ts index dbe224d5900..273272d61c4 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/ResourcePicker/utils.test.ts +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/ResourcePicker/utils.test.ts @@ -166,7 +166,7 @@ describe('AzureMonitor ResourcePicker utils', () => { describe('setResource', () => { it('updates a resource with a resource URI for Log Analytics', () => { expect(setResource(createMockQuery(), '/subscription/sub')).toMatchObject({ - azureLogAnalytics: { resource: '/subscription/sub' }, + azureLogAnalytics: { resources: ['/subscription/sub'] }, }); }); diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/ResourcePicker/utils.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/ResourcePicker/utils.ts index 37900a6d151..105936d0fa7 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/ResourcePicker/utils.ts +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/ResourcePicker/utils.ts @@ -139,7 +139,7 @@ export function setResource(query: AzureMonitorQuery, resource?: string | AzureM ...query, azureLogAnalytics: { ...query.azureLogAnalytics, - resource, + resources: [resource], }, }; } diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/grafanaTemplateVariableFns.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/grafanaTemplateVariableFns.ts index 24b3894d3b3..0ed9de7dd36 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/grafanaTemplateVariableFns.ts +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/grafanaTemplateVariableFns.ts @@ -246,7 +246,7 @@ const createLogAnalyticsTemplateVariableQuery = async ( queryType: AzureQueryType.LogAnalytics, azureLogAnalytics: { query: rawQuery, - resource, + resources: [resource], }, subscription: defaultSubscriptionId, }; diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/grafanaTemplateVariables.test.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/grafanaTemplateVariables.test.ts index 33819e29751..07e78821810 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/grafanaTemplateVariables.test.ts +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/grafanaTemplateVariables.test.ts @@ -219,7 +219,7 @@ describe('migrateStringQueriesToObjectQueries', () => { queryType: AzureQueryType.LogAnalytics, azureLogAnalytics: { query: 'some kind of kql query', - resource: '', + resources: [''], }, subscription: 'defaultSubscriptionId', }, diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/types/query.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/types/query.ts index 6cb1392bdd1..316091d5aa6 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/types/query.ts +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/types/query.ts @@ -92,9 +92,12 @@ export interface AzureMetricQuery { export interface AzureLogsQuery { query?: string; resultFormat?: string; - resource?: string; + resources?: string[]; workspace?: string; + + /** @deprecated Use resources instead */ + resource?: string; } /** diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/utils/migrateAnnotation.test.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/utils/migrateAnnotation.test.ts index c55c9a4e985..bfd74252441 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/utils/migrateAnnotation.test.ts +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/utils/migrateAnnotation.test.ts @@ -37,8 +37,9 @@ const NEW_ANNOTATION: AnnotationQuery = { queryType: AzureQueryType.LogAnalytics, azureLogAnalytics: { query: 'AzureActivity\r\n| where $__timeFilter() \r\n| project TimeGenerated, Text=OperationName', - resource: + resources: [ '/subscriptions/abc-123-def-456/resourcegroups/our-datasource/providers/microsoft.operationalinsights/workspaces/azureactivitylog', + ], }, }, }; diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/utils/migrateAnnotation.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/utils/migrateAnnotation.ts index c630d34805f..31247ec7a78 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/utils/migrateAnnotation.ts +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/utils/migrateAnnotation.ts @@ -20,7 +20,7 @@ export default function migrateAnnotation(annotation: AnnotationQuery { ); }); }); + + it('should migrate a sigle resource for Logs', () => { + const q = { + ...modernMetricsQuery, + azureLogAnalytics: { + ...modernMetricsQuery.azureLogAnalytics, + resource: 'foo', + }, + }; + const result = migrateQuery(q); + expect(result.azureLogAnalytics?.resources).toEqual(['foo']); + }); }); diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/utils/migrateQuery.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/utils/migrateQuery.ts index bf8a895e69b..69149cc24fe 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/utils/migrateQuery.ts +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/utils/migrateQuery.ts @@ -32,6 +32,10 @@ export default function migrateQuery(query: AzureMonitorQuery): AzureMonitorQuer workingQuery = migrateResourceGroupAndName(workingQuery); } + if (workingQuery.azureLogAnalytics?.resource) { + workingQuery = migrateLogsResource(workingQuery); + } + return workingQuery; } @@ -172,3 +176,15 @@ function migrateResourceGroupAndName(query: AzureMonitorQuery): AzureMonitorQuer return workingQuery; } + +function migrateLogsResource(query: AzureMonitorQuery): AzureMonitorQuery { + let workingQuery = query; + + if (workingQuery.azureLogAnalytics && workingQuery.azureLogAnalytics.resource) { + workingQuery.azureLogAnalytics.resources = [workingQuery.azureLogAnalytics.resource]; + + delete workingQuery.azureLogAnalytics.resource; + } + + return workingQuery; +}