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>
180 lines
6.0 KiB
TypeScript
180 lines
6.0 KiB
TypeScript
import UrlBuilder from '../azure_monitor/url_builder';
|
|
import { setKustoQuery } from '../components/LogsQueryEditor/setQueryValue';
|
|
import {
|
|
appendDimensionFilter,
|
|
setTimeGrain as setMetricsTimeGrain,
|
|
} from '../components/MetricsQueryEditor/setQueryValue';
|
|
import TimegrainConverter from '../time_grain_converter';
|
|
import { AzureMetricDimension, AzureMonitorQuery, AzureQueryType } from '../types';
|
|
|
|
const OLD_DEFAULT_DROPDOWN_VALUE = 'select';
|
|
|
|
export default function migrateQuery(query: AzureMonitorQuery): AzureMonitorQuery {
|
|
let workingQuery = query;
|
|
|
|
// The old angular controller also had a `migrateApplicationInsightsKeys` migraiton that
|
|
// migrated old properties to other properties that still do not appear to be used anymore, so
|
|
// we decided to not include that migration anymore
|
|
// See https://github.com/grafana/grafana/blob/a6a09add/public/app/plugins/datasource/grafana-azure-monitor-datasource/query_ctrl.ts#L269-L288
|
|
|
|
workingQuery = migrateTimeGrains(workingQuery);
|
|
workingQuery = migrateLogAnalyticsToFromTimes(workingQuery);
|
|
workingQuery = migrateToDefaultNamespace(workingQuery);
|
|
workingQuery = migrateDimensionToDimensionFilter(workingQuery);
|
|
workingQuery = migrateResourceUri(workingQuery);
|
|
workingQuery = migrateDimensionFilterToArray(workingQuery);
|
|
|
|
return workingQuery;
|
|
}
|
|
|
|
function migrateTimeGrains(query: AzureMonitorQuery): AzureMonitorQuery {
|
|
let workingQuery = query;
|
|
|
|
if (workingQuery.azureMonitor?.timeGrainUnit && workingQuery.azureMonitor.timeGrain !== 'auto') {
|
|
const newTimeGrain = TimegrainConverter.createISO8601Duration(
|
|
workingQuery.azureMonitor.timeGrain ?? 'auto',
|
|
workingQuery.azureMonitor.timeGrainUnit
|
|
);
|
|
workingQuery = setMetricsTimeGrain(workingQuery, newTimeGrain);
|
|
|
|
delete workingQuery.azureMonitor?.timeGrainUnit;
|
|
}
|
|
|
|
return workingQuery;
|
|
}
|
|
|
|
function migrateLogAnalyticsToFromTimes(query: AzureMonitorQuery): AzureMonitorQuery {
|
|
let workingQuery = query;
|
|
|
|
if (workingQuery.azureLogAnalytics?.query?.match(/\$__from\s/gi)) {
|
|
workingQuery = setKustoQuery(
|
|
workingQuery,
|
|
workingQuery.azureLogAnalytics.query.replace(/\$__from\s/gi, '$__timeFrom() ')
|
|
);
|
|
}
|
|
|
|
if (workingQuery.azureLogAnalytics?.query?.match(/\$__to\s/gi)) {
|
|
workingQuery = setKustoQuery(
|
|
workingQuery,
|
|
workingQuery.azureLogAnalytics.query.replace(/\$__to\s/gi, '$__timeTo() ')
|
|
);
|
|
}
|
|
|
|
return workingQuery;
|
|
}
|
|
|
|
function migrateToDefaultNamespace(query: AzureMonitorQuery): AzureMonitorQuery {
|
|
const haveMetricNamespace =
|
|
query.azureMonitor?.metricNamespace && query.azureMonitor.metricNamespace !== OLD_DEFAULT_DROPDOWN_VALUE;
|
|
|
|
if (!haveMetricNamespace && query.azureMonitor?.metricDefinition) {
|
|
return {
|
|
...query,
|
|
azureMonitor: {
|
|
...query.azureMonitor,
|
|
metricNamespace: query.azureMonitor.metricDefinition,
|
|
},
|
|
};
|
|
}
|
|
|
|
return query;
|
|
}
|
|
|
|
function migrateDimensionToDimensionFilter(query: AzureMonitorQuery): AzureMonitorQuery {
|
|
let workingQuery = query;
|
|
|
|
const oldDimension = workingQuery.azureMonitor?.dimension;
|
|
if (oldDimension && oldDimension !== 'None') {
|
|
workingQuery = appendDimensionFilter(workingQuery, oldDimension, 'eq', [
|
|
workingQuery.azureMonitor?.dimensionFilter || '',
|
|
]);
|
|
}
|
|
|
|
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,
|
|
},
|
|
};
|
|
}
|
|
|
|
function migrateDimensionFilterToArray(query: AzureMonitorQuery): AzureMonitorQuery {
|
|
const azureMonitorQuery = query.azureMonitor;
|
|
|
|
if (!azureMonitorQuery) {
|
|
return query;
|
|
}
|
|
|
|
const newFilters: AzureMetricDimension[] = [];
|
|
const dimensionFilters = azureMonitorQuery.dimensionFilters;
|
|
if (dimensionFilters && dimensionFilters.length > 0) {
|
|
dimensionFilters.forEach((filter) => {
|
|
const staticProps = { dimension: filter.dimension, operator: filter.operator };
|
|
if (!filter.filters && filter.filter) {
|
|
newFilters.push({ ...staticProps, filters: [filter.filter] });
|
|
} else {
|
|
let hasFilter = false;
|
|
if (filter.filters && filter.filter) {
|
|
for (const oldFilter of filter.filters) {
|
|
if (filter.filter === oldFilter) {
|
|
hasFilter = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!hasFilter && filter.filter !== '*') {
|
|
filter.filters.push(filter.filter);
|
|
}
|
|
newFilters.push({ ...staticProps, filters: filter.filters });
|
|
}
|
|
}
|
|
});
|
|
if (newFilters.length > 0) {
|
|
return { ...query, azureMonitor: { ...azureMonitorQuery, dimensionFilters: newFilters } };
|
|
}
|
|
}
|
|
return query;
|
|
}
|
|
|
|
// 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 {
|
|
let workingQuery = query;
|
|
|
|
if (!workingQuery.queryType) {
|
|
workingQuery = {
|
|
...workingQuery,
|
|
queryType: AzureQueryType.AzureMonitor,
|
|
};
|
|
}
|
|
|
|
if (workingQuery.queryType === AzureQueryType.AzureMonitor && workingQuery.azureMonitor) {
|
|
workingQuery = migrateDimensionToDimensionFilter(workingQuery);
|
|
workingQuery = migrateResourceUri(workingQuery);
|
|
workingQuery = migrateDimensionFilterToArray(workingQuery);
|
|
}
|
|
|
|
return workingQuery;
|
|
}
|