123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299 |
- import React from 'react';
- import { getTemplateSrv } from '@grafana/runtime';
- import { AzureMetricDimension, AzureMonitorErrorish, AzureMonitorQuery, AzureQueryType } from '../types';
- import migrateQuery from './migrateQuery';
- let replaceMock = jest.fn().mockImplementation((s: string) => s);
- jest.mock('@grafana/runtime', () => {
- const original = jest.requireActual('@grafana/runtime');
- return {
- ...original,
- getTemplateSrv: () => ({
- replace: replaceMock,
- }),
- };
- });
- let templateSrv = getTemplateSrv();
- let setErrorMock = jest.fn();
- 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 chart’s 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 = {
- 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 chart’s 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',
- alias: '{{ dimensionvalue }}',
- allowedTimeGrainsMs: [60000, 300000, 900000, 1800000, 3600000, 21600000, 43200000, 86400000],
- dimensionFilters: [{ dimension: 'dependency/success', filters: ['*'], operator: 'eq' }],
- metricDefinition: 'microsoft.insights/components',
- metricName: 'dependencies/duration',
- 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',
- },
- azureResourceGraph: { resultFormat: 'table' },
- queryType: AzureQueryType.AzureMonitor,
- refId: 'A',
- subscription: '44693801-6ee6-49de-9b2d-9106972f9572',
- subscriptions: ['44693801-6ee6-49de-9b2d-9106972f9572'],
- };
- describe('AzureMonitor: migrateQuery', () => {
- it('modern queries should not change', () => {
- const result = migrateQuery(modernMetricsQuery, templateSrv, setErrorMock);
- // 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, templateSrv, setErrorMock);
- 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, templateSrv, setErrorMock);
- expect(result).toMatchObject(
- expect.objectContaining({
- azureMonitor: expect.objectContaining({
- resourceUri:
- '/subscriptions/44693801-6ee6-49de-9b2d-9106972f9572/resourceGroups/cloud-datasources/providers/microsoft.insights/components/AppInsightsTestData',
- }),
- })
- );
- });
- it('should not build a resource uri with an unsupported namespace template variable', () => {
- replaceMock = jest
- .fn()
- .mockImplementation((s: string) => s.replace('$ns', 'Microsoft.Storage/storageAccounts/tableServices'));
- setErrorMock = jest
- .fn()
- .mockImplementation((errorSource: string, error: AzureMonitorErrorish) => 'Template Var error');
- const errorElement = React.createElement(
- 'div',
- null,
- `Failed to create resource URI. Validate the metric definition template variable against supported cases `,
- React.createElement(
- 'a',
- {
- href: 'https://grafana.com/docs/grafana/latest/datasources/azuremonitor/template-variables/',
- },
- 'here.'
- )
- );
- templateSrv = getTemplateSrv();
- const query = {
- ...azureMonitorQueryV8,
- azureMonitor: {
- ...azureMonitorQueryV8.azureMonitor,
- metricDefinition: '$ns',
- },
- };
- const result = migrateQuery(query, templateSrv, setErrorMock);
- expect(result.azureMonitor?.resourceUri).toBeUndefined();
- expect(setErrorMock).toHaveBeenCalledWith('Resource URI migration', errorElement);
- });
- it('should not build a resource uri with unsupported resource name template variable', () => {
- replaceMock = jest.fn().mockImplementation((s: string) => s.replace('$resource', 'resource/default'));
- setErrorMock = jest
- .fn()
- .mockImplementation((errorSource: string, error: AzureMonitorErrorish) => 'Template Var error');
- const errorElement = React.createElement(
- 'div',
- null,
- `Failed to create resource URI. Validate the resource name template variable against supported cases `,
- React.createElement(
- 'a',
- {
- href: 'https://grafana.com/docs/grafana/latest/datasources/azuremonitor/template-variables/',
- },
- 'here.'
- )
- );
- templateSrv = getTemplateSrv();
- const query = {
- ...azureMonitorQueryV8,
- azureMonitor: {
- ...azureMonitorQueryV8.azureMonitor,
- resourceName: '$resource',
- },
- };
- const result = migrateQuery(query, templateSrv, setErrorMock);
- expect(result.azureMonitor?.resourceUri).toBeUndefined();
- expect(setErrorMock).toHaveBeenCalledWith('Resource URI migration', errorElement);
- });
- });
- describe('migrating from a v9 query to the latest query version', () => {
- it('will not change valid dimension filters', () => {
- const dimensionFilters: AzureMetricDimension[] = [
- { dimension: 'TestDimension', operator: 'eq', filters: ['testFilter'] },
- ];
- const result = migrateQuery(
- { ...azureMonitorQueryV8, azureMonitor: { dimensionFilters } },
- templateSrv,
- setErrorMock
- );
- expect(result).toMatchObject(
- expect.objectContaining({
- azureMonitor: expect.objectContaining({
- dimensionFilters,
- }),
- })
- );
- });
- it('correctly updates old filter containing wildcard', () => {
- const dimensionFilters: AzureMetricDimension[] = [{ dimension: 'TestDimension', operator: 'eq', filter: '*' }];
- const result = migrateQuery(
- { ...azureMonitorQueryV8, azureMonitor: { dimensionFilters } },
- templateSrv,
- setErrorMock
- );
- expect(result).toMatchObject(
- expect.objectContaining({
- azureMonitor: expect.objectContaining({
- dimensionFilters: [
- { dimension: dimensionFilters[0].dimension, operator: dimensionFilters[0].operator, filters: ['*'] },
- ],
- }),
- })
- );
- });
- it('correctly updates old filter containing value', () => {
- const dimensionFilters: AzureMetricDimension[] = [{ dimension: 'TestDimension', operator: 'eq', filter: 'test' }];
- const result = migrateQuery(
- { ...azureMonitorQueryV8, azureMonitor: { dimensionFilters } },
- templateSrv,
- setErrorMock
- );
- expect(result).toMatchObject(
- expect.objectContaining({
- azureMonitor: expect.objectContaining({
- dimensionFilters: [
- { dimension: dimensionFilters[0].dimension, operator: dimensionFilters[0].operator, filters: ['test'] },
- ],
- }),
- })
- );
- });
- it('correctly ignores wildcard if filters has a value', () => {
- const dimensionFilters: AzureMetricDimension[] = [
- { dimension: 'TestDimension', operator: 'eq', filter: '*', filters: ['testFilter'] },
- ];
- const result = migrateQuery(
- { ...azureMonitorQueryV8, azureMonitor: { dimensionFilters } },
- templateSrv,
- setErrorMock
- );
- expect(result).toMatchObject(
- expect.objectContaining({
- azureMonitor: expect.objectContaining({
- dimensionFilters: [
- {
- dimension: dimensionFilters[0].dimension,
- operator: dimensionFilters[0].operator,
- filters: ['testFilter'],
- },
- ],
- }),
- })
- );
- });
- it('correctly ignores duplicates', () => {
- const dimensionFilters: AzureMetricDimension[] = [
- { dimension: 'TestDimension', operator: 'eq', filter: 'testFilter', filters: ['testFilter'] },
- ];
- const result = migrateQuery(
- { ...azureMonitorQueryV8, azureMonitor: { dimensionFilters } },
- templateSrv,
- setErrorMock
- );
- expect(result).toMatchObject(
- expect.objectContaining({
- azureMonitor: expect.objectContaining({
- dimensionFilters: [
- {
- dimension: dimensionFilters[0].dimension,
- operator: dimensionFilters[0].operator,
- filters: ['testFilter'],
- },
- ],
- }),
- })
- );
- });
- });
- });
|