From a41e6ae45343e786c8b93415d06909668d3c7fbf Mon Sep 17 00:00:00 2001 From: "Grot (@grafanabot)" <43478413+grafanabot@users.noreply.github.com> Date: Mon, 12 Sep 2022 12:28:32 +0200 Subject: [PATCH] AzureMonitor: Fix custom namespaces (#54937) (#55018) (cherry picked from commit 879ee82b83e73e4543ac181035693a1c8252ba54) Co-authored-by: Adam Simpson --- .../metrics/azuremonitor-datasource.go | 9 ++++-- .../metrics/azuremonitor-datasource_test.go | 21 +++++++++++++ pkg/tsdb/azuremonitor/types/types.go | 1 + .../__mocks__/query.ts | 1 + .../azure_monitor_datasource.test.ts | 10 +++--- .../azure_monitor/azure_monitor_datasource.ts | 2 ++ .../azure_monitor/url_builder.test.ts | 31 ++++++++++++++----- .../azure_monitor/url_builder.ts | 9 +++--- .../MetricNamespaceField.tsx | 8 ++--- .../MetricsQueryEditor/dataHooks.ts | 17 +++++----- .../MetricsQueryEditor/setQueryValue.test.ts | 14 +++++++++ .../MetricsQueryEditor/setQueryValue.ts | 7 +++-- .../types/query.ts | 1 + .../types/types.ts | 4 +++ 14 files changed, 100 insertions(+), 35 deletions(-) create mode 100644 public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/setQueryValue.test.ts diff --git a/pkg/tsdb/azuremonitor/metrics/azuremonitor-datasource.go b/pkg/tsdb/azuremonitor/metrics/azuremonitor-datasource.go index c3cb16f8eac..7d7018f8e94 100644 --- a/pkg/tsdb/azuremonitor/metrics/azuremonitor-datasource.go +++ b/pkg/tsdb/azuremonitor/metrics/azuremonitor-datasource.go @@ -113,8 +113,13 @@ func (e *AzureMonitorDatasource) buildQueries(queries []backend.DataQuery, dsInf params.Add("timespan", fmt.Sprintf("%v/%v", query.TimeRange.From.UTC().Format(time.RFC3339), query.TimeRange.To.UTC().Format(time.RFC3339))) params.Add("interval", timeGrain) params.Add("aggregation", azJSONModel.Aggregation) - params.Add("metricnames", azJSONModel.MetricName) // MetricName or MetricNames ? - params.Add("metricnamespace", azJSONModel.MetricNamespace) + params.Add("metricnames", azJSONModel.MetricName) + + if azJSONModel.CustomNamespace != "" { + params.Add("metricnamespace", azJSONModel.CustomNamespace) + } else { + params.Add("metricnamespace", azJSONModel.MetricNamespace) + } // old model dimension := strings.TrimSpace(azJSONModel.Dimension) diff --git a/pkg/tsdb/azuremonitor/metrics/azuremonitor-datasource_test.go b/pkg/tsdb/azuremonitor/metrics/azuremonitor-datasource_test.go index 27ba75c83ee..2372092babc 100644 --- a/pkg/tsdb/azuremonitor/metrics/azuremonitor-datasource_test.go +++ b/pkg/tsdb/azuremonitor/metrics/azuremonitor-datasource_test.go @@ -250,6 +250,27 @@ func TestAzureMonitorBuildQueries(t *testing.T) { } } +func TestCustomNamespace(t *testing.T) { + datasource := &AzureMonitorDatasource{} + + t.Run("it should set the metricNamespace to a customNamespace value if customNamespace is present as a parameter", func(t *testing.T) { + q := []backend.DataQuery{ + { + JSON: []byte(`{ + "azureMonitor": { + "customNamespace": "custom/namespace" + } + }`), + }, + } + + result, err := datasource.buildQueries(q, types.DatasourceInfo{}) + require.NoError(t, err) + expected := "custom/namespace" + require.Equal(t, expected, result[0].Params.Get("metricnamespace")) + }) +} + func makeDates(startDate time.Time, count int, interval time.Duration) (times []time.Time) { for i := 0; i < count; i++ { times = append(times, startDate.Add(interval*time.Duration(i))) diff --git a/pkg/tsdb/azuremonitor/types/types.go b/pkg/tsdb/azuremonitor/types/types.go index bcab47c199b..ff0d868991d 100644 --- a/pkg/tsdb/azuremonitor/types/types.go +++ b/pkg/tsdb/azuremonitor/types/types.go @@ -115,6 +115,7 @@ type AzureMonitorJSONQuery struct { ResourceURI string `json:"resourceUri"` // These are used to reconstruct a resource URI MetricNamespace string `json:"metricNamespace"` + CustomNamespace string `json:"customNamespace"` MetricName string `json:"metricName"` ResourceGroup string `json:"resourceGroup"` ResourceName string `json:"resourceName"` 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 b8088c13049..2d08a83eb61 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 @@ -35,6 +35,7 @@ export default function createMockQuery(overrides?: Partial): dimensionFilters: [], metricName: 'Metric A', metricNamespace: 'Microsoft.Compute/virtualMachines', + customNamespace: '', resourceGroup: 'grafanastaging', resourceName: 'grafana', timeGrain: 'auto', 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 4a2de1421fe..4fba7134baa 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 @@ -192,7 +192,7 @@ describe('AzureMonitorDatasource', () => { const expected = basePath + '/providers/microsoft.insights/components/resource1' + - '/providers/microsoft.insights/metricdefinitions?api-version=2018-01-01&metricnamespace=microsoft.insights%2Fcomponents'; + '/providers/microsoft.insights/metricdefinitions?api-version=2018-01-01'; expect(path).toBe(expected); return Promise.resolve(response); }); @@ -257,7 +257,7 @@ describe('AzureMonitorDatasource', () => { const expected = basePath + '/providers/microsoft.insights/components/resource1' + - '/providers/microsoft.insights/metricdefinitions?api-version=2018-01-01&metricnamespace=microsoft.insights%2Fcomponents'; + '/providers/microsoft.insights/metricdefinitions?api-version=2018-01-01'; expect(path).toBe(expected); return Promise.resolve(response); }); @@ -594,7 +594,7 @@ describe('AzureMonitorDatasource', () => { const expected = basePath + '/providers/microsoft.insights/components/resource1' + - '/providers/microsoft.insights/metricdefinitions?api-version=2018-01-01&metricnamespace=microsoft.insights%2Fcomponents'; + '/providers/microsoft.insights/metricdefinitions?api-version=2018-01-01'; expect(path).toBe(expected); return Promise.resolve(response); }); @@ -660,7 +660,7 @@ describe('AzureMonitorDatasource', () => { const expected = basePath + '/providers/microsoft.insights/components/resource1' + - '/providers/microsoft.insights/metricdefinitions?api-version=2018-01-01&metricnamespace=microsoft.insights%2Fcomponents'; + '/providers/microsoft.insights/metricdefinitions?api-version=2018-01-01'; expect(path).toBe(expected); return Promise.resolve(response); }); @@ -728,7 +728,7 @@ describe('AzureMonitorDatasource', () => { const expected = basePath + '/providers/microsoft.insights/components/resource1' + - '/providers/microsoft.insights/metricdefinitions?api-version=2018-01-01&metricnamespace=microsoft.insights%2Fcomponents'; + '/providers/microsoft.insights/metricdefinitions?api-version=2018-01-01'; expect(path).toBe(expected); return Promise.resolve(response); }); diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_monitor/azure_monitor_datasource.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_monitor/azure_monitor_datasource.ts index 5fb9226c020..2c168a2f1b9 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_monitor/azure_monitor_datasource.ts +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_monitor/azure_monitor_datasource.ts @@ -94,6 +94,7 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend { templateSrv ); expect(url).toBe( - '/subscriptions/sub/resource-uri/resource/providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview&metricnamespace=Microsoft.Sql%2Fservers' + '/subscriptions/sub/resource-uri/resource/providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview' + ); + }); + + it('handles a custom namespace', () => { + const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl( + '', + '2017-05-01-preview', + { + resourceUri: '/subscriptions/sub/resource-uri/resource', + customNamespace: 'custom/namespace', + }, + templateSrv + ); + expect(url).toBe( + '/subscriptions/sub/resource-uri/resource/providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview&metricnamespace=custom%2Fnamespace' ); }); }); @@ -259,7 +274,7 @@ describe('AzureMonitorUrlBuilder', () => { ); expect(url).toBe( '/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.NetApp/netAppAccounts/rn1/capacityPools/rn2/volumes/rn3/' + - 'providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview&metricnamespace=Microsoft.NetApp%2FnetAppAccounts%2FcapacityPools%2Fvolumes' + 'providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview' ); }); }); @@ -279,7 +294,7 @@ describe('AzureMonitorUrlBuilder', () => { ); expect(url).toBe( '/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.Sql/servers/rn1/databases/rn2/' + - 'providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview&metricnamespace=Microsoft.Sql%2Fservers%2Fdatabases' + 'providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview' ); }); }); @@ -299,7 +314,7 @@ describe('AzureMonitorUrlBuilder', () => { ); expect(url).toBe( '/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.Sql/servers/rn/' + - 'providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview&metricnamespace=Microsoft.Sql%2Fservers' + 'providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview' ); }); }); @@ -319,7 +334,7 @@ describe('AzureMonitorUrlBuilder', () => { ); expect(url).toBe( '/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.Storage/storageAccounts/rn1/blobServices/default/' + - 'providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview&metricnamespace=Microsoft.Storage%2FstorageAccounts%2FblobServices' + 'providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview' ); }); }); @@ -339,7 +354,7 @@ describe('AzureMonitorUrlBuilder', () => { ); expect(url).toBe( '/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.Storage/storageAccounts/rn1/fileServices/default/' + - 'providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview&metricnamespace=Microsoft.Storage%2FstorageAccounts%2FfileServices' + 'providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview' ); }); }); @@ -359,7 +374,7 @@ describe('AzureMonitorUrlBuilder', () => { ); expect(url).toBe( '/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.Storage/storageAccounts/rn1/tableServices/default/' + - 'providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview&metricnamespace=Microsoft.Storage%2FstorageAccounts%2FtableServices' + 'providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview' ); }); }); @@ -379,7 +394,7 @@ describe('AzureMonitorUrlBuilder', () => { ); expect(url).toBe( '/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.Storage/storageAccounts/rn1/queueServices/default/' + - 'providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview&metricnamespace=Microsoft.Storage%2FstorageAccounts%2FqueueServices' + 'providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview' ); }); }); diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_monitor/url_builder.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_monitor/url_builder.ts index 9caa26ccdc7..22fc7a38006 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_monitor/url_builder.ts +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_monitor/url_builder.ts @@ -81,8 +81,7 @@ export default class UrlBuilder { templateSrv: TemplateSrv ) { let resourceUri: string; - const { metricNamespace } = query; - + const { customNamespace } = query; if ('resourceUri' in query) { resourceUri = query.resourceUri; } else { @@ -94,11 +93,11 @@ export default class UrlBuilder { resourceName, }); } - let url = `${baseUrl}${resourceUri}/providers/microsoft.insights/metricdefinitions?api-version=${apiVersion}`; - if (metricNamespace) { - url += `&metricnamespace=${encodeURIComponent(metricNamespace)}`; + if (customNamespace) { + url += `&metricnamespace=${encodeURIComponent(customNamespace)}`; } + return url; } } diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/MetricNamespaceField.tsx b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/MetricNamespaceField.tsx index a1a70b6e2e6..124c20a6a3b 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/MetricNamespaceField.tsx +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/MetricsQueryEditor/MetricNamespaceField.tsx @@ -6,7 +6,7 @@ import { Select } from '@grafana/ui'; import { AzureQueryEditorFieldProps, AzureMonitorOption } from '../../types'; import { Field } from '../Field'; -import { setMetricNamespace } from './setQueryValue'; +import { setCustomNamespace } from './setQueryValue'; interface MetricNamespaceFieldProps extends AzureQueryEditorFieldProps { metricNamespaces: AzureMonitorOption[]; @@ -24,7 +24,7 @@ const MetricNamespaceField: React.FC = ({ return; } - const newQuery = setMetricNamespace(query, change.value); + const newQuery = setCustomNamespace(query, change.value); onQueryChange(newQuery); }, [onQueryChange, query] @@ -34,7 +34,7 @@ const MetricNamespaceField: React.FC = ({ const optionValues = metricNamespaces .map((m) => m.value.toLowerCase()) .concat(variableOptionGroup.options.map((p) => p.value)); - const value = query.azureMonitor?.metricNamespace; + const value = query.azureMonitor?.customNamespace || query.azureMonitor?.metricNamespace; if (value && !optionValues.includes(value.toLowerCase())) { options.push({ label: value, value }); } @@ -43,7 +43,7 @@ const MetricNamespaceField: React.FC = ({