2025-04-01 10:38:02 +09:00

285 lines
11 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { AzureMetricDimension, AzureMonitorQuery, AzureQueryType, ResultFormat } from '../types';
import migrateQuery from './migrateQuery';
const azureMonitorQueryV8 = {
azureMonitor: {
aggregation: 'Average',
dimensionFilters: [],
metricName: 'dependencies/duration',
metricNamespace: 'microsoft.insights/components',
resourceGroup: 'cloud-datasources',
resourceName: 'AppInsightsTestData',
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: ResultFormat.TimeSeries,
},
datasource: {
type: 'grafana-azure-monitor-datasource',
uid: 'sD-ZuB87k',
},
queryType: AzureQueryType.AzureMonitor,
refId: 'A',
subscription: '44693801-6ee6-49de-9b2d-9106972f9572',
};
const azureMonitorQueryV9_0 = {
azureMonitor: {
aggregation: 'Average',
dimensionFilters: [],
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: '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: ResultFormat.TimeSeries,
},
datasource: {
type: 'grafana-azure-monitor-datasource',
uid: 'sD-ZuB87k',
},
queryType: AzureQueryType.AzureMonitor,
refId: 'A',
};
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 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: ResultFormat.TimeSeries,
workspace: 'mock-workspace-id',
dashboardTime: false,
},
azureMonitor: {
aggregation: 'Average',
alias: '{{ dimensionvalue }}',
allowedTimeGrainsMs: [60000, 300000, 900000, 1800000, 3600000, 21600000, 43200000, 86400000],
dimensionFilters: [{ dimension: 'dependency/success', filters: ['*'], operator: 'eq' }],
metricName: 'dependencies/duration',
metricNamespace: 'microsoft.insights/components',
resources: [
{
resourceGroup: 'cloud-datasources',
resourceName: '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);
// 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 v8 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 } });
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 } });
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 } });
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 } });
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 } });
expect(result).toMatchObject(
expect.objectContaining({
azureMonitor: expect.objectContaining({
dimensionFilters: [
{
dimension: dimensionFilters[0].dimension,
operator: dimensionFilters[0].operator,
filters: ['testFilter'],
},
],
}),
})
);
});
it('correctly removes outdated fields', () => {
const result = migrateQuery({
...azureMonitorQueryV8,
azureMonitor: { dimension: 'testDimension', dimensionFilter: 'testFilter' },
});
expect(result).toMatchObject(
expect.objectContaining({
azureMonitor: expect.objectContaining({
dimensionFilters: [
{
dimension: 'testDimension',
operator: 'eq',
filters: ['testFilter'],
},
],
}),
})
);
expect(result.azureMonitor).not.toHaveProperty('dimension');
expect(result.azureMonitor).not.toHaveProperty('dimensionFilter');
});
it('correctly migrates a metric definition', () => {
const result = migrateQuery({ ...azureMonitorQueryV8, azureMonitor: { metricDefinition: 'ms.ns/mn' } });
expect(result).toMatchObject(
expect.objectContaining({
azureMonitor: expect.objectContaining({
metricNamespace: 'ms.ns/mn',
metricDefinition: undefined,
}),
})
);
});
it('correctly adds the dashboardTime property', () => {
const result = migrateQuery({ ...azureMonitorQueryV8 });
expect(result).toMatchObject(
expect.objectContaining({
azureLogAnalytics: expect.objectContaining({
dashboardTime: false,
}),
})
);
});
});
describe('migrating from a v9.0 query to the latest query version', () => {
it('will parse the resource URI', () => {
const result = migrateQuery(azureMonitorQueryV9_0);
expect(result).toMatchObject(
expect.objectContaining({
subscription: modernMetricsQuery.subscription,
azureMonitor: expect.objectContaining({
metricNamespace: modernMetricsQuery.azureMonitor!.metricNamespace,
resources: modernMetricsQuery.azureMonitor!.resources,
resourceUri: undefined,
}),
})
);
});
it('correctly remove outdated fields', () => {
const result = migrateQuery(azureMonitorQueryV9_0);
expect(result).toMatchObject(
expect.objectContaining({
azureMonitor: expect.objectContaining({
resources: modernMetricsQuery.azureMonitor!.resources,
}),
})
);
expect(result.azureMonitor).not.toHaveProperty('resourceGroup');
expect(result.azureMonitor).not.toHaveProperty('resourceName');
});
it('correctly adds the dashboardTime property', () => {
const result = migrateQuery({ ...azureMonitorQueryV9_0 });
expect(result).toMatchObject(
expect.objectContaining({
azureLogAnalytics: expect.objectContaining({
dashboardTime: false,
}),
})
);
});
});
it('should migrate a single resource for Logs', () => {
const q = {
...modernMetricsQuery,
azureLogAnalytics: {
...modernMetricsQuery.azureLogAnalytics,
resource: 'foo',
},
};
const result = migrateQuery(q);
expect(result.azureLogAnalytics?.resources).toEqual(['foo']);
});
it('correctly migrates intersectTime to dashboardTime', () => {
const query = modernMetricsQuery;
delete query.azureLogAnalytics?.dashboardTime;
const result = migrateQuery({
...query,
azureLogAnalytics: { ...query.azureLogAnalytics, intersectTime: true },
});
expect(result).toMatchObject(
expect.objectContaining({
azureLogAnalytics: expect.objectContaining({
dashboardTime: true,
}),
})
);
});
});