Azure Monitor: Migrate metrics queries to use a resource URI (#47696)

* migrate old query to new query

* remove new prefixed data fetchers

* fix lint

* add test cases for v7 and v8 query versions

* add mock ids in test

* add clarifying comment

* add types for azure monitor api data fetchers

* add additional comment to explain the types
This commit is contained in:
Kevin Yu 2022-04-20 05:00:39 -07:00 committed by GitHub
parent 79c06fdddc
commit 01c22ee366
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 395 additions and 363 deletions

View File

@ -16,9 +16,9 @@ export default function createMockDatasource(overrides?: DeepPartial<Datasource>
},
getSubscriptions: jest.fn().mockResolvedValueOnce([]),
defaultSubscriptionId: 'subscriptionId',
newGetMetricNamespaces: jest.fn().mockResolvedValueOnce([]),
newGetMetricNames: jest.fn().mockResolvedValueOnce([]),
newGetMetricMetadata: jest.fn().mockResolvedValueOnce({
getMetricNamespaces: jest.fn().mockResolvedValueOnce([]),
getMetricNames: jest.fn().mockResolvedValueOnce([]),
getMetricMetadata: jest.fn().mockResolvedValueOnce({
primaryAggType: 'Average',
supportedAggTypes: ['Average', 'Maximum', 'Minimum'],
supportedTimeGrains: [],
@ -31,14 +31,6 @@ export default function createMockDatasource(overrides?: DeepPartial<Datasource>
getResourceGroups: jest.fn().mockResolvedValueOnce([]),
getMetricDefinitions: jest.fn().mockResolvedValueOnce([]),
getResourceNames: jest.fn().mockResolvedValueOnce([]),
getMetricNamespaces: jest.fn().mockResolvedValueOnce([]),
getMetricNames: jest.fn().mockResolvedValueOnce([]),
getMetricMetadata: jest.fn().mockResolvedValueOnce({
primaryAggType: 'Average',
supportedAggTypes: ['Average', 'Maximum', 'Minimum'],
supportedTimeGrains: [],
dimensions: [],
}),
azureLogAnalyticsDatasource: {
getKustoSchema: () => Promise.resolve(),

View File

@ -26,7 +26,7 @@ describe('AzureMonitorDatasource', () => {
ctx.instanceSettings = {
name: 'test',
url: 'http://azuremonitor.com',
jsonData: { subscriptionId: '9935389e-9122-4ef9-95f9-1513dd24753f', cloudName: 'azuremonitor' },
jsonData: { subscriptionId: 'mock-subscription-id', cloudName: 'azuremonitor' },
} as unknown as DataSourceInstanceSettings<AzureDataSourceJsonData>;
ctx.ds = new AzureMonitorDatasource(ctx.instanceSettings);
});
@ -76,11 +76,11 @@ describe('AzureMonitorDatasource', () => {
});
});
describe('When performing newGetMetricNamespaces', () => {
describe('When performing getMetricNamespaces', () => {
const response = {
value: [
{
id: '/subscriptions/9935389e-9122-4ef9-95f9-1513dd24753f/resourceGroups/nodeapp/providers/microsoft.insights/components/resource1/providers/microsoft.insights/metricNamespaces/Azure.ApplicationInsights',
id: '/subscriptions/mock-subscription-id/resourceGroups/nodeapp/providers/microsoft.insights/components/resource1/providers/microsoft.insights/metricNamespaces/Azure.ApplicationInsights',
name: 'Azure.ApplicationInsights',
type: 'Microsoft.Insights/metricNamespaces',
classification: 'Custom',
@ -89,7 +89,7 @@ describe('AzureMonitorDatasource', () => {
},
},
{
id: '/subscriptions/9935389e-9122-4ef9-95f9-1513dd24753f/resourceGroups/nodeapp/providers/microsoft.insights/components/resource1/providers/microsoft.insights/metricNamespaces/microsoft.insights-components',
id: '/subscriptions/mock-subscription-id/resourceGroups/nodeapp/providers/microsoft.insights/components/resource1/providers/microsoft.insights/metricNamespaces/microsoft.insights-components',
name: 'microsoft.insights-components',
type: 'Microsoft.Insights/metricNamespaces',
classification: 'Platform',
@ -102,7 +102,7 @@ describe('AzureMonitorDatasource', () => {
beforeEach(() => {
ctx.ds.azureMonitorDatasource.getResource = jest.fn().mockImplementation((path: string) => {
const basePath = 'azuremonitor/subscriptions/9935389e-9122-4ef9-95f9-1513dd24753f/resourceGroups/nodeapp';
const basePath = 'azuremonitor/subscriptions/mock-subscription-id/resourceGroups/nodeapp';
const expected =
basePath +
'/providers/microsoft.insights/components/resource1' +
@ -114,9 +114,10 @@ describe('AzureMonitorDatasource', () => {
it('should return list of Metric Namspaces', () => {
return ctx.ds.azureMonitorDatasource
.newGetMetricNamespaces(
'/subscriptions/9935389e-9122-4ef9-95f9-1513dd24753f/resourceGroups/nodeapp/providers/microsoft.insights/components/resource1'
)
.getMetricNamespaces({
resourceUri:
'/subscriptions/mock-subscription-id/resourceGroups/nodeapp/providers/microsoft.insights/components/resource1',
})
.then((results: Array<{ text: string; value: string }>) => {
expect(results.length).toEqual(2);
expect(results[0].text).toEqual('Azure.ApplicationInsights');
@ -127,7 +128,7 @@ describe('AzureMonitorDatasource', () => {
});
});
describe('When performing newGetMetricNames', () => {
describe('When performing getMetricNames', () => {
const response = {
value: [
{
@ -165,7 +166,7 @@ describe('AzureMonitorDatasource', () => {
beforeEach(() => {
ctx.ds.azureMonitorDatasource.getResource = jest.fn().mockImplementation((path: string) => {
const basePath = 'azuremonitor/subscriptions/9935389e-9122-4ef9-95f9-1513dd24753f/resourceGroups/nodeapp';
const basePath = 'azuremonitor/subscriptions/mock-subscription-id/resourceGroups/nodeapp';
const expected =
basePath +
'/providers/microsoft.insights/components/resource1' +
@ -177,10 +178,11 @@ describe('AzureMonitorDatasource', () => {
it('should return list of Metric Definitions', () => {
return ctx.ds.azureMonitorDatasource
.newGetMetricNames(
'/subscriptions/9935389e-9122-4ef9-95f9-1513dd24753f/resourceGroups/nodeapp/providers/microsoft.insights/components/resource1',
'default'
)
.getMetricNames({
resourceUri:
'/subscriptions/mock-subscription-id/resourceGroups/nodeapp/providers/microsoft.insights/components/resource1',
metricNamespace: 'default',
})
.then((results: Array<{ text: string; value: string }>) => {
expect(results.length).toEqual(2);
expect(results[0].text).toEqual('Used capacity');
@ -191,7 +193,7 @@ describe('AzureMonitorDatasource', () => {
});
});
describe('When performing newGetMetricMetadata', () => {
describe('When performing getMetricMetadata', () => {
const response = {
value: [
{
@ -229,7 +231,7 @@ describe('AzureMonitorDatasource', () => {
beforeEach(() => {
ctx.ds.azureMonitorDatasource.getResource = jest.fn().mockImplementation((path: string) => {
const basePath = 'azuremonitor/subscriptions/9935389e-9122-4ef9-95f9-1513dd24753f/resourceGroups/nodeapp';
const basePath = 'azuremonitor/subscriptions/mock-subscription-id/resourceGroups/nodeapp';
const expected =
basePath +
'/providers/microsoft.insights/components/resource1' +
@ -241,11 +243,12 @@ describe('AzureMonitorDatasource', () => {
it('should return Aggregation metadata for a Metric', () => {
return ctx.ds.azureMonitorDatasource
.newGetMetricMetadata(
'/subscriptions/9935389e-9122-4ef9-95f9-1513dd24753f/resourceGroups/nodeapp/providers/microsoft.insights/components/resource1',
'default',
'UsedCapacity'
)
.getMetricMetadata({
resourceUri:
'/subscriptions/mock-subscription-id/resourceGroups/nodeapp/providers/microsoft.insights/components/resource1',
metricNamespace: 'default',
metricName: 'UsedCapacity',
})
.then((results) => {
expect(results.primaryAggType).toEqual('Total');
expect(results.supportedAggTypes.length).toEqual(6);
@ -342,7 +345,7 @@ describe('AzureMonitorDatasource', () => {
beforeEach(() => {
ctx.ds.azureMonitorDatasource.getResource = jest.fn().mockImplementation((path: string) => {
const basePath = 'azuremonitor/subscriptions/9935389e-9122-4ef9-95f9-1513dd24753f/resourceGroups';
const basePath = 'azuremonitor/subscriptions/mock-subscription-id/resourceGroups';
expect(path).toBe(basePath + '/nodesapp/resources?api-version=2021-04-01');
return Promise.resolve(response);
});
@ -350,7 +353,7 @@ describe('AzureMonitorDatasource', () => {
it('should return list of Metric Definitions with no duplicates and no unsupported namespaces', () => {
return ctx.ds
.getMetricDefinitions('9935389e-9122-4ef9-95f9-1513dd24753f', 'nodesapp')
.getMetricDefinitions('mock-subscription-id', 'nodesapp')
.then((results: Array<{ text: string; value: string }>) => {
expect(results.length).toEqual(7);
expect(results[0].text).toEqual('Network interface');
@ -372,12 +375,12 @@ describe('AzureMonitorDatasource', () => {
});
describe('When performing getResourceNames', () => {
let subscription = '9935389e-9122-4ef9-95f9-1513dd24753f';
let subscription = 'mock-subscription-id';
let resourceGroup = 'nodeapp';
let metricDefinition = 'microsoft.insights/components';
beforeEach(() => {
subscription = '9935389e-9122-4ef9-95f9-1513dd24753f';
subscription = 'mock-subscription-id';
resourceGroup = 'nodeapp';
metricDefinition = 'microsoft.insights/components';
});
@ -552,7 +555,7 @@ describe('AzureMonitorDatasource', () => {
beforeEach(() => {
ctx.ds.azureMonitorDatasource.getResource = jest.fn().mockImplementation((path: string) => {
const basePath = 'azuremonitor/subscriptions/9935389e-9122-4ef9-95f9-1513dd24753f/resourceGroups/nodeapp';
const basePath = 'azuremonitor/subscriptions/mock-subscription-id/resourceGroups/nodeapp';
const expected =
basePath +
'/providers/microsoft.insights/components/resource1' +
@ -563,14 +566,14 @@ describe('AzureMonitorDatasource', () => {
});
it('should return list of Metric Definitions', () => {
return ctx.ds
.getMetricNames(
'9935389e-9122-4ef9-95f9-1513dd24753f',
'nodeapp',
'microsoft.insights/components',
'resource1',
'default'
)
return ctx.ds.azureMonitorDatasource
.getMetricNames({
subscription: 'mock-subscription-id',
resourceGroup: 'nodeapp',
metricDefinition: 'microsoft.insights/components',
resourceName: 'resource1',
metricNamespace: 'default',
})
.then((results: Array<{ text: string; value: string }>) => {
expect(results.length).toEqual(2);
expect(results[0].text).toEqual('Used capacity');
@ -619,7 +622,7 @@ describe('AzureMonitorDatasource', () => {
beforeEach(() => {
ctx.ds.azureMonitorDatasource.getResource = jest.fn().mockImplementation((path: string) => {
const basePath = 'azuremonitor/subscriptions/9935389e-9122-4ef9-95f9-1513dd24753f/resourceGroups/nodeapp';
const basePath = 'azuremonitor/subscriptions/mock-subscription-id/resourceGroups/nodeapp';
const expected =
basePath +
'/providers/microsoft.insights/components/resource1' +
@ -630,15 +633,15 @@ describe('AzureMonitorDatasource', () => {
});
it('should return Aggregation metadata for a Metric', () => {
return ctx.ds
.getMetricMetadata(
'9935389e-9122-4ef9-95f9-1513dd24753f',
'nodeapp',
'microsoft.insights/components',
'resource1',
'default',
'UsedCapacity'
)
return ctx.ds.azureMonitorDatasource
.getMetricMetadata({
subscription: 'mock-subscription-id',
resourceGroup: 'nodeapp',
metricDefinition: 'microsoft.insights/components',
resourceName: 'resource1',
metricNamespace: 'default',
metricName: 'UsedCapacity',
})
.then((results) => {
expect(results.primaryAggType).toEqual('Total');
expect(results.supportedAggTypes.length).toEqual(6);
@ -688,7 +691,7 @@ describe('AzureMonitorDatasource', () => {
beforeEach(() => {
ctx.ds.azureMonitorDatasource.getResource = jest.fn().mockImplementation((path: string) => {
const basePath = 'azuremonitor/subscriptions/9935389e-9122-4ef9-95f9-1513dd24753f/resourceGroups/nodeapp';
const basePath = 'azuremonitor/subscriptions/mock-subscription-id/resourceGroups/nodeapp';
const expected =
basePath +
'/providers/microsoft.insights/components/resource1' +
@ -699,15 +702,15 @@ describe('AzureMonitorDatasource', () => {
});
it('should return dimensions for a Metric that has dimensions', () => {
return ctx.ds
.getMetricMetadata(
'9935389e-9122-4ef9-95f9-1513dd24753f',
'nodeapp',
'microsoft.insights/components',
'resource1',
'default',
'Transactions'
)
return ctx.ds.azureMonitorDatasource
.getMetricMetadata({
subscription: 'mock-subscription-id',
resourceGroup: 'nodeapp',
metricDefinition: 'microsoft.insights/components',
resourceName: 'resource1',
metricNamespace: 'default',
metricName: 'Transactions',
})
.then((results: any) => {
expect(results.dimensions).toMatchInlineSnapshot(`
Array [
@ -759,15 +762,15 @@ describe('AzureMonitorDatasource', () => {
});
it('should return an empty array for a Metric that does not have dimensions', () => {
return ctx.ds
.getMetricMetadata(
'9935389e-9122-4ef9-95f9-1513dd24753f',
'nodeapp',
'microsoft.insights/components',
'resource1',
'default',
'FreeCapacity'
)
return ctx.ds.azureMonitorDatasource
.getMetricMetadata({
subscription: 'mock-subscription-id',
resourceGroup: 'nodeapp',
metricDefinition: 'microsoft.insights/components',
resourceName: 'resource1',
metricNamespace: 'default',
metricName: 'FreeCapacity',
})
.then((results: any) => {
expect(results.dimensions.length).toEqual(0);
});

View File

@ -16,6 +16,9 @@ import {
AzureMonitorResourceGroupsResponse,
AzureQueryType,
DatasourceValidationResult,
GetMetricNamespacesQuery,
GetMetricNamesQuery,
GetMetricMetadataQuery,
} from '../types';
import { routeNames } from '../utils/common';
import ResponseParser from './response_parser';
@ -236,102 +239,35 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend<AzureM
});
}
getMetricNamespaces(subscriptionId: string, resourceGroup: string, metricDefinition: string, resourceName: string) {
getMetricNamespaces(query: GetMetricNamespacesQuery) {
const url = UrlBuilder.buildAzureMonitorGetMetricNamespacesUrl(
this.resourcePath,
subscriptionId,
resourceGroup,
metricDefinition,
resourceName,
this.apiPreviewVersion
this.apiPreviewVersion,
this.replaceTemplateVariables(query)
);
return this.getResource(url).then((result: any) => {
return ResponseParser.parseResponseValues(result, 'name', 'properties.metricNamespaceName');
});
}
newGetMetricNamespaces(resourceUri: string) {
const templateSrv = getTemplateSrv();
const url = UrlBuilder.newBuildAzureMonitorGetMetricNamespacesUrl(
this.resourcePath,
templateSrv.replace(resourceUri),
this.apiPreviewVersion
);
return this.getResource(url).then((result: AzureMonitorMetricNamespacesResponse) => {
return ResponseParser.parseResponseValues(result, 'name', 'properties.metricNamespaceName');
});
}
getMetricNames(
subscriptionId: string,
resourceGroup: string,
metricDefinition: string,
resourceName: string,
metricNamespace: string
) {
getMetricNames(query: GetMetricNamesQuery) {
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl(
this.resourcePath,
subscriptionId,
resourceGroup,
metricDefinition,
resourceName,
metricNamespace,
this.apiVersion
this.apiVersion,
this.replaceTemplateVariables(query)
);
return this.getResource(url).then((result: any) => {
return ResponseParser.parseResponseValues(result, 'name.localizedValue', 'name.value');
});
}
newGetMetricNames(resourceUri: string, metricNamespace: string) {
const templateSrv = getTemplateSrv();
const url = UrlBuilder.newBuildAzureMonitorGetMetricNamesUrl(
this.resourcePath,
templateSrv.replace(resourceUri),
templateSrv.replace(metricNamespace),
this.apiVersion
);
return this.getResource(url).then((result: AzureMonitorMetricNamesResponse) => {
return ResponseParser.parseResponseValues(result, 'name.localizedValue', 'name.value');
});
}
getMetricMetadata(
subscriptionId: string,
resourceGroup: string,
metricDefinition: string,
resourceName: string,
metricNamespace: string,
metricName: string
) {
getMetricMetadata(query: GetMetricMetadataQuery) {
const { metricName } = query;
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl(
this.resourcePath,
subscriptionId,
resourceGroup,
metricDefinition,
resourceName,
metricNamespace,
this.apiVersion
this.apiVersion,
this.replaceTemplateVariables(query)
);
return this.getResource(url).then((result: any) => {
return ResponseParser.parseMetadata(result, metricName);
});
}
newGetMetricMetadata(resourceUri: string, metricNamespace: string, metricName: string) {
const templateSrv = getTemplateSrv();
const url = UrlBuilder.newBuildAzureMonitorGetMetricNamesUrl(
this.resourcePath,
templateSrv.replace(resourceUri),
templateSrv.replace(metricNamespace),
this.apiVersion
);
return this.getResource(url).then((result: AzureMonitorMetricsMetadataResponse) => {
return ResponseParser.parseMetadata(result, metricName);
});
@ -398,4 +334,16 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend<AzureM
private isValidConfigField(field?: string): boolean {
return typeof field === 'string' && field.length > 0;
}
private replaceTemplateVariables<T extends { [K in keyof T]: string }>(query: T) {
const templateSrv = getTemplateSrv();
const workingQuery: { [K in keyof T]: string } = { ...query };
const keys = Object.keys(query) as Array<keyof T>;
keys.forEach((key) => {
workingQuery[key] = templateSrv.replace(workingQuery[key]);
});
return workingQuery;
}
}

View File

@ -1,13 +1,19 @@
import UrlBuilder from './url_builder';
describe('AzureMonitorUrlBuilder', () => {
describe('buildResourceUri', () => {
it('builds a resource uri when the required properties are provided', () => {
expect(UrlBuilder.buildResourceUri('sub', 'group', 'Microsoft.NetApp/netAppAccounts', 'name')).toEqual(
'/subscriptions/sub/resourceGroups/group/providers/Microsoft.NetApp/netAppAccounts/name'
);
});
});
describe('when a resource uri is provided', () => {
it('builds a getMetricNamesnamespace url', () => {
const url = UrlBuilder.newBuildAzureMonitorGetMetricNamespacesUrl(
'',
'/subscriptions/sub/resource-uri/resource',
'2017-05-01-preview'
);
const url = UrlBuilder.buildAzureMonitorGetMetricNamespacesUrl('', '2017-05-01-preview', {
resourceUri: '/subscriptions/sub/resource-uri/resource',
});
expect(url).toBe(
'/subscriptions/sub/resource-uri/resource/providers/microsoft.insights/metricNamespaces?api-version=2017-05-01-preview'
);
@ -16,12 +22,10 @@ describe('AzureMonitorUrlBuilder', () => {
describe('when a resource uri and metric namespace is provided', () => {
it('builds a getMetricNames url', () => {
const url = UrlBuilder.newBuildAzureMonitorGetMetricNamesUrl(
'',
'/subscriptions/sub/resource-uri/resource',
'Microsoft.Sql/servers',
'2017-05-01-preview'
);
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl('', '2017-05-01-preview', {
resourceUri: '/subscriptions/sub/resource-uri/resource',
metricNamespace: 'Microsoft.Sql/servers',
});
expect(url).toBe(
'/subscriptions/sub/resource-uri/resource/providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview&metricnamespace=Microsoft.Sql%2Fservers'
);
@ -31,14 +35,12 @@ describe('AzureMonitorUrlBuilder', () => {
describe('Legacy query object', () => {
describe('when metric definition is Microsoft.NetApp/netAppAccounts/capacityPools/volumes', () => {
it('should build the getMetricNamespaces url in the even longer format', () => {
const url = UrlBuilder.buildAzureMonitorGetMetricNamespacesUrl(
'',
'sub1',
'rg',
'Microsoft.NetApp/netAppAccounts/capacityPools/volumes',
'rn1/rn2/rn3',
'2017-05-01-preview'
);
const url = UrlBuilder.buildAzureMonitorGetMetricNamespacesUrl('', '2017-05-01-preview', {
subscription: 'sub1',
resourceGroup: 'rg',
metricDefinition: 'Microsoft.NetApp/netAppAccounts/capacityPools/volumes',
resourceName: 'rn1/rn2/rn3',
});
expect(url).toBe(
'/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.NetApp/netAppAccounts/rn1/capacityPools/rn2/volumes/rn3/' +
'providers/microsoft.insights/metricNamespaces?api-version=2017-05-01-preview'
@ -48,14 +50,12 @@ describe('AzureMonitorUrlBuilder', () => {
describe('when metric definition is Microsoft.Sql/servers/databases', () => {
it('should build the getMetricNamespaces url in the longer format', () => {
const url = UrlBuilder.buildAzureMonitorGetMetricNamespacesUrl(
'',
'sub1',
'rg',
'Microsoft.Sql/servers/databases',
'rn1/rn2',
'2017-05-01-preview'
);
const url = UrlBuilder.buildAzureMonitorGetMetricNamespacesUrl('', '2017-05-01-preview', {
subscription: 'sub1',
resourceGroup: 'rg',
metricDefinition: 'Microsoft.Sql/servers/databases',
resourceName: 'rn1/rn2',
});
expect(url).toBe(
'/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.Sql/servers/rn1/databases/rn2/' +
'providers/microsoft.insights/metricNamespaces?api-version=2017-05-01-preview'
@ -65,14 +65,12 @@ describe('AzureMonitorUrlBuilder', () => {
describe('when metric definition is Microsoft.Sql/servers', () => {
it('should build the getMetricNamespaces url in the shorter format', () => {
const url = UrlBuilder.buildAzureMonitorGetMetricNamespacesUrl(
'',
'sub1',
'rg',
'Microsoft.Sql/servers',
'rn',
'2017-05-01-preview'
);
const url = UrlBuilder.buildAzureMonitorGetMetricNamespacesUrl('', '2017-05-01-preview', {
subscription: 'sub1',
resourceGroup: 'rg',
metricDefinition: 'Microsoft.Sql/servers',
resourceName: 'rn',
});
expect(url).toBe(
'/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.Sql/servers/rn/' +
'providers/microsoft.insights/metricNamespaces?api-version=2017-05-01-preview'
@ -82,15 +80,13 @@ describe('AzureMonitorUrlBuilder', () => {
describe('when metric definition is Microsoft.NetApp/netAppAccounts/capacityPools/volumes and the metricNamespace is default', () => {
it('should build the getMetricNames url in the even longer format', () => {
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl(
'',
'sub1',
'rg',
'Microsoft.NetApp/netAppAccounts/capacityPools/volumes',
'rn1/rn2/rn3',
'default',
'2017-05-01-preview'
);
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl('', '2017-05-01-preview', {
subscription: 'sub1',
resourceGroup: 'rg',
metricDefinition: 'Microsoft.NetApp/netAppAccounts/capacityPools/volumes',
resourceName: 'rn1/rn2/rn3',
metricNamespace: 'default',
});
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=default'
@ -100,15 +96,13 @@ describe('AzureMonitorUrlBuilder', () => {
describe('when metric definition is Microsoft.Sql/servers/databases and the metricNamespace is default', () => {
it('should build the getMetricNames url in the longer format', () => {
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl(
'',
'sub1',
'rg',
'Microsoft.Sql/servers/databases',
'rn1/rn2',
'default',
'2017-05-01-preview'
);
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl('', '2017-05-01-preview', {
subscription: 'sub1',
resourceGroup: 'rg',
metricDefinition: 'Microsoft.Sql/servers/databases',
resourceName: 'rn1/rn2',
metricNamespace: 'default',
});
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=default'
@ -118,15 +112,13 @@ describe('AzureMonitorUrlBuilder', () => {
describe('when metric definition is Microsoft.Sql/servers and the metricNamespace is default', () => {
it('should build the getMetricNames url in the shorter format', () => {
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl(
'',
'sub1',
'rg',
'Microsoft.Sql/servers',
'rn',
'default',
'2017-05-01-preview'
);
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl('', '2017-05-01-preview', {
subscription: 'sub1',
resourceGroup: 'rg',
metricDefinition: 'Microsoft.Sql/servers',
resourceName: 'rn',
metricNamespace: 'default',
});
expect(url).toBe(
'/subscriptions/sub1/resourceGroups/rg/providers/Microsoft.Sql/servers/rn/' +
'providers/microsoft.insights/metricdefinitions?api-version=2017-05-01-preview&metricnamespace=default'
@ -136,15 +128,13 @@ describe('AzureMonitorUrlBuilder', () => {
describe('when metric definition is Microsoft.Storage/storageAccounts/blobServices and the metricNamespace is default', () => {
it('should build the getMetricNames url in the longer format', () => {
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl(
'',
'sub1',
'rg',
'Microsoft.Storage/storageAccounts/blobServices',
'rn1/default',
'default',
'2017-05-01-preview'
);
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl('', '2017-05-01-preview', {
subscription: 'sub1',
resourceGroup: 'rg',
metricDefinition: 'Microsoft.Storage/storageAccounts/blobServices',
resourceName: 'rn1/default',
metricNamespace: 'default',
});
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=default'
@ -154,15 +144,13 @@ describe('AzureMonitorUrlBuilder', () => {
describe('when metric definition is Microsoft.Storage/storageAccounts/fileServices and the metricNamespace is default', () => {
it('should build the getMetricNames url in the longer format', () => {
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl(
'',
'sub1',
'rg',
'Microsoft.Storage/storageAccounts/fileServices',
'rn1/default',
'default',
'2017-05-01-preview'
);
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl('', '2017-05-01-preview', {
subscription: 'sub1',
resourceGroup: 'rg',
metricDefinition: 'Microsoft.Storage/storageAccounts/fileServices',
resourceName: 'rn1/default',
metricNamespace: 'default',
});
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=default'
@ -172,15 +160,13 @@ describe('AzureMonitorUrlBuilder', () => {
describe('when metric definition is Microsoft.Storage/storageAccounts/tableServices and the metricNamespace is default', () => {
it('should build the getMetricNames url in the longer format', () => {
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl(
'',
'sub1',
'rg',
'Microsoft.Storage/storageAccounts/tableServices',
'rn1/default',
'default',
'2017-05-01-preview'
);
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl('', '2017-05-01-preview', {
subscription: 'sub1',
resourceGroup: 'rg',
metricDefinition: 'Microsoft.Storage/storageAccounts/tableServices',
resourceName: 'rn1/default',
metricNamespace: 'default',
});
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=default'
@ -190,15 +176,13 @@ describe('AzureMonitorUrlBuilder', () => {
describe('when metric definition is Microsoft.Storage/storageAccounts/queueServices and the metricNamespace is default', () => {
it('should build the getMetricNames url in the longer format', () => {
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl(
'',
'sub1',
'rg',
'Microsoft.Storage/storageAccounts/queueServices',
'rn1/default',
'default',
'2017-05-01-preview'
);
const url = UrlBuilder.buildAzureMonitorGetMetricNamesUrl('', '2017-05-01-preview', {
subscription: 'sub1',
resourceGroup: 'rg',
metricDefinition: 'Microsoft.Storage/storageAccounts/queueServices',
resourceName: 'rn1/default',
metricNamespace: 'default',
});
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=default'

View File

@ -1,58 +1,47 @@
import { GetMetricNamespacesQuery, GetMetricNamesQuery } from '../types';
export default class UrlBuilder {
static buildAzureMonitorGetMetricNamespacesUrl(
baseUrl: string,
static buildResourceUri(
subscriptionId: string,
resourceGroup: string,
metricDefinition: string,
resourceName: string,
apiVersion: string
resourceName: string
) {
const metricDefinitionArray = metricDefinition.split('/');
const resourceNameArray = resourceName.split('/');
const provider = metricDefinitionArray.shift();
const urlArray = [baseUrl, 'subscriptions', subscriptionId, 'resourceGroups', resourceGroup, 'providers', provider];
const urlArray = ['/subscriptions', subscriptionId, 'resourceGroups', resourceGroup, 'providers', provider];
for (const i in metricDefinitionArray) {
urlArray.push(metricDefinitionArray[i]);
urlArray.push(resourceNameArray[i]);
}
const urlPrefix = urlArray.join('/');
return `${urlPrefix}/providers/microsoft.insights/metricNamespaces?api-version=${apiVersion}`;
return urlArray.join('/');
}
static buildAzureMonitorGetMetricNamesUrl(
baseUrl: string,
subscriptionId: string,
resourceGroup: string,
metricDefinition: string,
resourceName: string,
metricNamespace: string,
apiVersion: string
) {
const metricDefinitionArray = metricDefinition.split('/');
const resourceNameArray = resourceName.split('/');
const provider = metricDefinitionArray.shift();
const urlArray = [baseUrl, 'subscriptions', subscriptionId, 'resourceGroups', resourceGroup, 'providers', provider];
for (const i in metricDefinitionArray) {
urlArray.push(metricDefinitionArray[i]);
urlArray.push(resourceNameArray[i]);
static buildAzureMonitorGetMetricNamespacesUrl(baseUrl: string, apiVersion: string, query: GetMetricNamespacesQuery) {
let resourceUri: string;
if ('resourceUri' in query) {
resourceUri = query.resourceUri;
} else {
const { subscription, resourceGroup, metricDefinition, resourceName } = query;
resourceUri = UrlBuilder.buildResourceUri(subscription, resourceGroup, metricDefinition, resourceName);
}
const urlPrefix = urlArray.join('/');
return (
`${urlPrefix}/providers/microsoft.insights/metricdefinitions?api-version=${apiVersion}` +
`&metricnamespace=${encodeURIComponent(metricNamespace)}`
);
}
static newBuildAzureMonitorGetMetricNamespacesUrl(baseUrl: string, resourceUri: string, apiVersion: string) {
return `${baseUrl}${resourceUri}/providers/microsoft.insights/metricNamespaces?api-version=${apiVersion}`;
}
static newBuildAzureMonitorGetMetricNamesUrl(
baseUrl: string,
resourceUri: string,
metricNamespace: string,
apiVersion: string
) {
static buildAzureMonitorGetMetricNamesUrl(baseUrl: string, apiVersion: string, query: GetMetricNamesQuery) {
let resourceUri: string;
const { metricNamespace } = query;
if ('resourceUri' in query) {
resourceUri = query.resourceUri;
} else {
const { subscription, resourceGroup, metricDefinition, resourceName } = query;
resourceUri = UrlBuilder.buildResourceUri(subscription, resourceGroup, metricDefinition, resourceName);
}
return (
`${baseUrl}${resourceUri}/providers/microsoft.insights/metricdefinitions?api-version=${apiVersion}` +
`&metricnamespace=${encodeURIComponent(metricNamespace)}`

View File

@ -79,7 +79,7 @@ describe('Azure Monitor QueryEditor', () => {
const mockDatasource = createMockDatasource();
const onChange = jest.fn();
const mockQuery = createMockQuery();
mockDatasource.getMetricNames = jest.fn().mockResolvedValue([
mockDatasource.azureMonitorDatasource.getMetricNames = jest.fn().mockResolvedValue([
{
value: 'metric-a',
text: 'Metric A',

View File

@ -247,11 +247,11 @@ describe('AzureMonitor: metrics dataHooks', () => {
.fn()
.mockResolvedValue([opt('Web server', 'web-server'), opt('Job server', 'job-server')]);
datasource.getMetricNames = jest
datasource.azureMonitorDatasource.getMetricNames = jest
.fn()
.mockResolvedValue([opt('Percentage CPU', 'percentage-cpu'), opt('Free memory', 'free-memory')]);
datasource.getMetricNamespaces = jest
datasource.azureMonitorDatasource.getMetricNamespaces = jest
.fn()
.mockResolvedValue([opt('Compute Virtual Machine', 'azure/vmc'), opt('Database NS', 'azure/dbns')]);
});

View File

@ -153,7 +153,12 @@ export const useMetricNamespaces: DataHook = (query, datasource, onChange, setEr
return;
}
const results = await datasource.getMetricNamespaces(subscription, resourceGroup, metricDefinition, resourceName);
const results = await datasource.azureMonitorDatasource.getMetricNamespaces({
subscription,
resourceGroup,
metricDefinition,
resourceName,
});
const options = formatOptions(results, metricNamespace);
// Do some cleanup of the query state if need be
@ -180,13 +185,13 @@ export const useMetricNames: DataHook = (query, datasource, onChange, setError)
return;
}
const results = await datasource.getMetricNames(
const results = await datasource.azureMonitorDatasource.getMetricNames({
subscription,
resourceGroup,
metricDefinition,
resourceName,
metricNamespace
);
metricNamespace,
});
const options = formatOptions(results, metricName);
@ -217,8 +222,8 @@ export const useMetricMetadata = (query: AzureMonitorQuery, datasource: Datasour
return;
}
datasource
.getMetricMetadata(subscription, resourceGroup, metricDefinition, resourceName, metricNamespace, metricName)
datasource.azureMonitorDatasource
.getMetricMetadata({ subscription, resourceGroup, metricDefinition, resourceName, metricNamespace, metricName })
.then((metadata) => {
// TODO: Move the aggregationTypes and timeGrain defaults into `getMetricMetadata`
const aggregations = (metadata.supportedAggTypes || [metadata.primaryAggType]).map((v) => ({

View File

@ -160,7 +160,7 @@ describe('MetricsQueryEditor', () => {
const mockDatasource = createMockDatasource({ resourcePickerData });
const onChange = jest.fn();
const mockQuery = createMockQuery();
mockDatasource.azureMonitorDatasource.newGetMetricNames = jest.fn().mockResolvedValue([
mockDatasource.azureMonitorDatasource.getMetricNames = jest.fn().mockResolvedValue([
{
value: 'metric-a',
text: 'Metric A',

View File

@ -130,11 +130,11 @@ describe('AzureMonitor: metrics dataHooks', () => {
.fn()
.mockResolvedValue([opt('Web server', 'web-server'), opt('Job server', 'job-server')]);
datasource.azureMonitorDatasource.newGetMetricNames = jest
datasource.azureMonitorDatasource.getMetricNames = jest
.fn()
.mockResolvedValue([opt('Percentage CPU', 'percentage-cpu'), opt('Free memory', 'free-memory')]);
datasource.azureMonitorDatasource.newGetMetricNamespaces = jest
datasource.azureMonitorDatasource.getMetricNamespaces = jest
.fn()
.mockResolvedValue([opt('Compute Virtual Machine', 'azure/vmc'), opt('Database NS', 'azure/dbns')]);
});

View File

@ -29,7 +29,7 @@ export const useMetricNamespaces: DataHook = (query, datasource, onChange, setEr
return;
}
const results = await datasource.azureMonitorDatasource.newGetMetricNamespaces(resourceUri);
const results = await datasource.azureMonitorDatasource.getMetricNamespaces({ resourceUri });
const options = formatOptions(results, metricNamespace);
// Do some cleanup of the query state if need be
@ -55,7 +55,7 @@ export const useMetricNames: DataHook = (query, datasource, onChange, setError)
return;
}
const results = await datasource.azureMonitorDatasource.newGetMetricNames(resourceUri, metricNamespace);
const results = await datasource.azureMonitorDatasource.getMetricNames({ resourceUri, metricNamespace });
const options = formatOptions(results, metricName);
return options;
@ -87,7 +87,7 @@ export const useMetricMetadata = (query: AzureMonitorQuery, datasource: Datasour
}
datasource.azureMonitorDatasource
.newGetMetricMetadata(resourceUri, metricNamespace, metricName)
.getMetricMetadata({ resourceUri, metricNamespace, metricName })
.then((metadata) => {
// TODO: Move the aggregationTypes and timeGrain defaults into `getMetricMetadata`
const aggregations = (metadata.supportedAggTypes || [metadata.primaryAggType]).map((v) => ({

View File

@ -218,49 +218,6 @@ export default class Datasource extends DataSourceApi<AzureMonitorQuery, AzureDa
);
}
getMetricNames(
subscriptionId: string,
resourceGroup: string,
metricDefinition: string,
resourceName: string,
metricNamespace: string
) {
return this.azureMonitorDatasource.getMetricNames(
this.replaceTemplateVariable(subscriptionId),
this.replaceTemplateVariable(resourceGroup),
this.replaceTemplateVariable(metricDefinition),
this.replaceTemplateVariable(resourceName),
this.replaceTemplateVariable(metricNamespace)
);
}
getMetricNamespaces(subscriptionId: string, resourceGroup: string, metricDefinition: string, resourceName: string) {
return this.azureMonitorDatasource.getMetricNamespaces(
this.replaceTemplateVariable(subscriptionId),
this.replaceTemplateVariable(resourceGroup),
this.replaceTemplateVariable(metricDefinition),
this.replaceTemplateVariable(resourceName)
);
}
getMetricMetadata(
subscriptionId: string,
resourceGroup: string,
metricDefinition: string,
resourceName: string,
metricNamespace: string,
metricName: string
) {
return this.azureMonitorDatasource.getMetricMetadata(
this.replaceTemplateVariable(subscriptionId),
this.replaceTemplateVariable(resourceGroup),
this.replaceTemplateVariable(metricDefinition),
this.replaceTemplateVariable(resourceName),
this.replaceTemplateVariable(metricNamespace),
this.replaceTemplateVariable(metricName)
);
}
/* Application Insights API method */
getAppInsightsMetricNames() {
return this.appInsightsDatasource?.getMetricNames();

View File

@ -209,3 +209,50 @@ export interface AzureResourceGraphOptions {
allowPartialScopes: boolean;
resultFormat: 'objectArray' | 'table';
}
// Azure Monitor Metrics query API data fetcher argument types.
// The types prefixed by Legacy are applicable to pre-version 9 of Grafana
// that do not have a resourceUri, instead the resourceUri is built up from
// the subscription, resource group, metric definition (a.k.a. resource type)
// and the resource name.
export type GetMetricNamespacesQuery = AzureGetMetricNamespacesQuery | LegacyAzureGetMetricNamespacesQuery;
export type GetMetricNamesQuery = AzureGetMetricNamesQuery | LegacyAzureGetMetricNamesQuery;
export type GetMetricMetadataQuery = AzureGetMetricMetadataQuery | LegacyAzureGetMetricMetadataQuery;
export interface AzureGetMetricNamespacesQuery {
resourceUri: string;
}
export interface LegacyAzureGetMetricNamespacesQuery {
subscription: string;
resourceGroup: string;
metricDefinition: string;
resourceName: string;
}
export interface AzureGetMetricNamesQuery {
resourceUri: string;
metricNamespace: string;
}
export interface LegacyAzureGetMetricNamesQuery {
subscription: string;
resourceGroup: string;
metricDefinition: string;
resourceName: string;
metricNamespace: string;
}
export interface AzureGetMetricMetadataQuery {
resourceUri: string;
metricNamespace: string;
metricName: string;
}
export interface LegacyAzureGetMetricMetadataQuery {
subscription: string;
resourceGroup: string;
metricDefinition: string;
resourceName: string;
metricNamespace: string;
metricName: string;
}

View File

@ -1,13 +1,62 @@
import { AzureMonitorQuery, AzureQueryType } from '../types';
import migrateQuery from './migrateQuery';
const azureMonitorQueryV7 = {
appInsights: { dimension: [], metricName: 'select', timeGrain: 'auto' },
azureLogAnalytics: {
query:
'//change this example to create your own time series query\n<table name> //the table to query (e.g. Usage, Heartbeat, Perf)\n| where $__timeFilter(TimeGenerated) //this is a macro used to show the full charts time range, choose the datetime column here\n| summarize count() by <group by column>, 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: 'mock-workspace-id',
},
azureMonitor: {
aggregation: 'Average',
allowedTimeGrainsMs: [60000, 300000, 900000, 1800000, 3600000, 21600000, 43200000, 86400000],
dimensionFilters: [{ dimension: 'dependency/success', filter: '', operator: 'eq' }],
metricDefinition: 'microsoft.insights/components',
metricName: 'dependencies/duration',
metricNamespace: 'microsoft.insights/components',
resourceGroup: 'cloud-datasources',
resourceName: 'AppInsightsTestData',
timeGrain: 'auto',
top: '10',
},
insightsAnalytics: {
query: '',
resultFormat: 'time_series',
},
queryType: AzureQueryType.AzureMonitor,
refId: 'A',
subscription: '44693801-6ee6-49de-9b2d-9106972f9572',
};
const azureMonitorQueryV8 = {
azureMonitor: {
aggregation: 'Average',
dimensionFilters: [],
metricDefinition: 'microsoft.insights/components',
metricName: 'dependencies/duration',
metricNamespace: 'microsoft.insights/components',
resourceGroup: 'cloud-datasources',
resourceName: 'AppInsightsTestData',
timeGrain: 'auto',
},
datasource: {
type: 'grafana-azure-monitor-datasource',
uid: 'sD-ZuB87k',
},
queryType: AzureQueryType.AzureMonitor,
refId: 'A',
subscription: '44693801-6ee6-49de-9b2d-9106972f9572',
};
const modernMetricsQuery: AzureMonitorQuery = {
appInsights: { dimension: [], metricName: 'select', timeGrain: 'auto' },
azureLogAnalytics: {
query:
'//change this example to create your own time series query\n<table name> //the table to query (e.g. Usage, Heartbeat, Perf)\n| where $__timeFilter(TimeGenerated) //this is a macro used to show the full charts time range, choose the datetime column here\n| summarize count() by <group by column>, 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',
workspace: 'mock-workspace-id',
},
azureMonitor: {
aggregation: 'Average',
@ -19,6 +68,8 @@ const modernMetricsQuery: AzureMonitorQuery = {
metricNamespace: 'microsoft.insights/components',
resourceGroup: 'cloud-datasources',
resourceName: 'AppInsightsTestData',
resourceUri:
'/subscriptions/44693801-6ee6-49de-9b2d-9106972f9572/resourceGroups/cloud-datasources/providers/microsoft.insights/components/AppInsightsTestData',
timeGrain: 'PT5M',
top: '10',
},
@ -37,4 +88,32 @@ describe('AzureMonitor: migrateQuery', () => {
// MUST use .toBe because we want to assert that the identity of unmigrated queries remains the same
expect(modernMetricsQuery).toBe(result);
});
describe('migrating from a v7 query to the latest query version', () => {
it('should build a resource uri', () => {
const result = migrateQuery(azureMonitorQueryV7);
expect(result).toMatchObject(
expect.objectContaining({
azureMonitor: expect.objectContaining({
resourceUri:
'/subscriptions/44693801-6ee6-49de-9b2d-9106972f9572/resourceGroups/cloud-datasources/providers/microsoft.insights/components/AppInsightsTestData',
}),
})
);
});
});
describe('migrating from a v8 query to the latest query version', () => {
it('should build a resource uri', () => {
const result = migrateQuery(azureMonitorQueryV8);
expect(result).toMatchObject(
expect.objectContaining({
azureMonitor: expect.objectContaining({
resourceUri:
'/subscriptions/44693801-6ee6-49de-9b2d-9106972f9572/resourceGroups/cloud-datasources/providers/microsoft.insights/components/AppInsightsTestData',
}),
})
);
});
});
});

View File

@ -4,6 +4,7 @@ import {
setTimeGrain as setMetricsTimeGrain,
} from '../components/MetricsQueryEditor/setQueryValue';
import TimegrainConverter from '../time_grain_converter';
import UrlBuilder from '../azure_monitor/url_builder';
import { AzureMonitorQuery, AzureQueryType, DeprecatedAzureQueryType } from '../types';
const OLD_DEFAULT_DROPDOWN_VALUE = 'select';
@ -21,6 +22,7 @@ export default function migrateQuery(query: AzureMonitorQuery): AzureMonitorQuer
workingQuery = migrateToDefaultNamespace(workingQuery);
workingQuery = migrateApplicationInsightsDimensions(workingQuery);
workingQuery = migrateMetricsDimensionFilters(workingQuery);
workingQuery = migrateResourceUri(workingQuery);
return workingQuery;
}
@ -121,7 +123,6 @@ function migrateApplicationInsightsDimensions(query: AzureMonitorQuery): AzureMo
return query;
}
// Exported because its also used directly in the datasource.ts for some reason
function migrateMetricsDimensionFilters(query: AzureMonitorQuery): AzureMonitorQuery {
let workingQuery = query;
@ -133,6 +134,33 @@ function migrateMetricsDimensionFilters(query: AzureMonitorQuery): AzureMonitorQ
return workingQuery;
}
// Azure Monitor metric queries prior to Grafana version 9 did not include a `resourceUri`.
// The resourceUri was previously constructed with the subscription id, resource group,
// metric definition (a.k.a. resource type), and the resource name.
function migrateResourceUri(query: AzureMonitorQuery): AzureMonitorQuery {
const azureMonitorQuery = query.azureMonitor;
if (!azureMonitorQuery || azureMonitorQuery.resourceUri) {
return query;
}
const { subscription } = query;
const { resourceGroup, metricDefinition, resourceName } = azureMonitorQuery;
if (!(subscription && resourceGroup && metricDefinition && resourceName)) {
return query;
}
const resourceUri = UrlBuilder.buildResourceUri(subscription, resourceGroup, metricDefinition, resourceName);
return {
...query,
azureMonitor: {
...azureMonitorQuery,
resourceUri,
},
};
}
// datasource.ts also contains some migrations, which have been moved to here. Unsure whether
// they should also do all the other migrations...
export function datasourceMigrations(query: AzureMonitorQuery): AzureMonitorQuery {
@ -159,6 +187,7 @@ export function datasourceMigrations(query: AzureMonitorQuery): AzureMonitorQuer
if (workingQuery.queryType === AzureQueryType.AzureMonitor && workingQuery.azureMonitor) {
workingQuery = migrateMetricsDimensionFilters(workingQuery);
workingQuery = migrateResourceUri(workingQuery);
}
return workingQuery;

View File

@ -270,7 +270,9 @@ describe('VariableSupport', () => {
azureLogAnalyticsDatasource: {
defaultSubscriptionId: 'defaultSubscriptionId',
},
getMetricNamespaces: jest.fn().mockResolvedValueOnce(expectedResults),
azureMonitorDatasource: {
getMetricNamespaces: jest.fn().mockResolvedValueOnce(expectedResults),
},
})
);
const mockRequest = {
@ -296,7 +298,9 @@ describe('VariableSupport', () => {
const expectedResults = ['test'];
const variableSupport = new VariableSupport(
createMockDatasource({
getMetricNamespaces: jest.fn().mockResolvedValueOnce(expectedResults),
azureMonitorDatasource: {
getMetricNamespaces: jest.fn().mockResolvedValueOnce(expectedResults),
},
})
);
const mockRequest = {
@ -325,7 +329,9 @@ describe('VariableSupport', () => {
azureLogAnalyticsDatasource: {
defaultSubscriptionId: 'defaultSubscriptionId',
},
getMetricNames: jest.fn().mockResolvedValueOnce(expectedResults),
azureMonitorDatasource: {
getMetricNames: jest.fn().mockResolvedValueOnce(expectedResults),
},
})
);
const mockRequest = {
@ -351,7 +357,9 @@ describe('VariableSupport', () => {
const expectedResults = ['test'];
const variableSupport = new VariableSupport(
createMockDatasource({
getMetricNames: jest.fn().mockResolvedValueOnce(expectedResults),
azureMonitorDatasource: {
getMetricNames: jest.fn().mockResolvedValueOnce(expectedResults),
},
})
);
const mockRequest = {
@ -478,7 +486,9 @@ describe('VariableSupport', () => {
azureLogAnalyticsDatasource: {
defaultSubscriptionId: 'defaultSubscriptionId',
},
getMetricNames: jest.fn().mockResolvedValueOnce([]),
azureMonitorDatasource: {
getMetricNames: jest.fn().mockResolvedValueOnce([]),
},
})
);
const mockRequest = {

View File

@ -81,22 +81,11 @@ export class VariableSupport extends CustomVariableSupport<DataSource, AzureMoni
}
if (query.kind === 'MetricNamespaceQuery') {
return this.datasource.getMetricNamespaces(
this.replaceVariable(query.subscription),
this.replaceVariable(query.resourceGroup),
this.replaceVariable(query.metricDefinition),
this.replaceVariable(query.resourceName)
);
return this.datasource.azureMonitorDatasource.getMetricNamespaces(query);
}
if (query.kind === 'MetricNamesQuery') {
return this.datasource.getMetricNames(
this.replaceVariable(query.subscription),
this.replaceVariable(query.resourceGroup),
this.replaceVariable(query.metricDefinition),
this.replaceVariable(query.resourceName),
this.replaceVariable(query.metricNamespace)
);
return this.datasource.azureMonitorDatasource.getMetricNames(query);
}
if (query.kind === 'WorkspacesQuery') {