mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
* Add support for multiselect - Add filters param to Dimensions - Update existing tests - Add MultiSelect component - Add helper function to determine valid options - Update labels hook to account for custom values - Update go type - Add function to build valid filters string * Additional go tests - Ensure query targets are built correctly * Update DimensionFields frontend test - Corrently rerender components - Additional test for multiple labels selection - Better selection of options in react-select components * Fix lint issue * Reset filters when operator or dimension changes * Terminology * Update test * Add backend migration - Update types (deprecate Filter field) - Add migration logic - Update tests - Update dimension filters buliding * Add migration test code * Simplify some logic * Add frontend deprecation notice * Add frontend migration logic and migration tests * Update setting of filter values * Update DimensionFields test * Fix linting issues * PR comment updates - Remove unnecessary if/else condition - Don't set filter default value as queries should be migrated - Add comment explaining why sw operator only accepts one value - Remove unnecessary test for merging of old and new filters * Nit on terminology Co-authored-by: Andres Martinez Gotor <andres.martinez@grafana.com> * Rename migrations for clarity Co-authored-by: Andres Martinez Gotor <andres.martinez@grafana.com>
199 lines
8.4 KiB
TypeScript
199 lines
8.4 KiB
TypeScript
import { AzureMetricDimension, 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 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);
|
||
|
||
// 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',
|
||
}),
|
||
})
|
||
);
|
||
});
|
||
});
|
||
|
||
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 } });
|
||
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'],
|
||
},
|
||
],
|
||
}),
|
||
})
|
||
);
|
||
});
|
||
});
|
||
});
|