From 43ee7acecdaad439219a57e28512fff2f83fd745 Mon Sep 17 00:00:00 2001 From: Josh Hunt Date: Wed, 14 Jul 2021 11:36:11 +0100 Subject: [PATCH] AzureMonitor: Make all query properties optional (#36701) * start to make all query fields optional * fix other types * fix optional types in fields * Pfeedback! * Clean up types --- .../__mocks__/query.ts | 2 - .../app_insights/app_insights_datasource.ts | 13 +- .../azure_log_analytics_datasource.ts | 15 +- .../azure_monitor/azure_monitor_datasource.ts | 45 +-- .../azure_resource_graph_datasource.test.ts | 2 - .../azure_resource_graph_datasource.ts | 7 +- .../components/ArgQueryEditor/QueryField.tsx | 2 +- .../InsightsAnalyticsEditor/index.tsx | 4 +- .../LogsQueryEditor/FormatAsField.tsx | 2 +- .../components/LogsQueryEditor/QueryField.tsx | 6 +- .../LogsQueryEditor/ResourceField.tsx | 4 +- .../LogsQueryEditor/WorkspaceField.tsx | 65 ----- .../LogsQueryEditor/useMigrations.ts | 2 +- .../MetricsQueryEditor/AggregationField.tsx | 2 +- .../MetricsQueryEditor/DimensionFields.tsx | 16 +- .../MetricsQueryEditor/LegendFormatField.tsx | 2 +- .../MetricsQueryEditor/MetricNameField.tsx | 4 +- .../MetricNamespaceField.tsx | 4 +- .../MetricsQueryEditor.test.tsx | 4 +- .../ResourceGroupsField.tsx | 2 +- .../MetricsQueryEditor/ResourceNameField.tsx | 4 +- .../MetricsQueryEditor/ResourceTypeField.tsx | 4 +- .../MetricsQueryEditor/TimeGrainField.tsx | 2 +- .../MetricsQueryEditor/TopField.tsx | 2 +- .../QueryEditor/QueryEditor.test.tsx | 66 +---- .../components/QueryEditor/QueryEditor.tsx | 28 +- .../components/SubscriptionField.tsx | 4 +- .../components/metrics.ts | 15 +- .../datasource.ts | 87 ++++-- .../insights_analytics_datasource.ts | 13 +- .../query_ctrl.ts | 13 +- .../types/index.ts | 263 +----------------- .../types/query.ts | 105 +++++++ .../types/types.ts | 181 ++++++++++++ 34 files changed, 480 insertions(+), 510 deletions(-) delete mode 100644 public/app/plugins/datasource/grafana-azure-monitor-datasource/components/LogsQueryEditor/WorkspaceField.tsx create mode 100644 public/app/plugins/datasource/grafana-azure-monitor-datasource/types/query.ts create mode 100644 public/app/plugins/datasource/grafana-azure-monitor-datasource/types/types.ts diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/__mocks__/query.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/__mocks__/query.ts index 56c2cf54de6..883c4452e58 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/__mocks__/query.ts +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/__mocks__/query.ts @@ -13,7 +13,6 @@ export default function createMockQuery(): AzureMonitorQuery { azureResourceGraph: { query: 'Resources | summarize count()', - resultFormat: 'time_series', }, azureMonitor: { @@ -42,6 +41,5 @@ export default function createMockQuery(): AzureMonitorQuery { refId: 'A', subscription: '99999999-cccc-bbbb-aaaa-9106972f9572', subscriptions: ['99999999-cccc-bbbb-aaaa-9106972f9572'], - format: 'dunno lol', // unsure what this value should be. It's not there at runtime, but it's in the ts interface }; } diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/app_insights/app_insights_datasource.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/app_insights/app_insights_datasource.ts index 07c93a56da4..78798241160 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/app_insights/app_insights_datasource.ts +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/app_insights/app_insights_datasource.ts @@ -61,14 +61,18 @@ export default class AppInsightsDatasource extends DataSourceWithBackend { - const item = target.appInsights!; + applyTemplateVariables(target: AzureMonitorQuery, scopedVars: ScopedVars): AzureMonitorQuery { + const item = target.appInsights; + + if (!item) { + return target; + } const old: any = item; // fix for timeGrainUnit which is a deprecated/removed field name if (old.timeGrainCount) { item.timeGrain = TimegrainConverter.createISO8601Duration(old.timeGrainCount, item.timeGrainUnit); - } else if (item.timeGrainUnit && item.timeGrain !== 'auto') { + } else if (item.timeGrain && item.timeGrainUnit && item.timeGrain !== 'auto') { item.timeGrain = TimegrainConverter.createISO8601Duration(item.timeGrain, item.timeGrainUnit); } @@ -95,9 +99,7 @@ export default class AppInsightsDatasource extends DataSourceWithBackend templateSrv.replace(d, scopedVars)), dimensionFilter: templateSrv.replace(item.dimensionFilter, scopedVars), alias: item.alias, - format: target.format, }, }; } diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_log_analytics/azure_log_analytics_datasource.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_log_analytics/azure_log_analytics_datasource.ts index 0c73a29d66d..104d450c95f 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_log_analytics/azure_log_analytics_datasource.ts +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_log_analytics/azure_log_analytics_datasource.ts @@ -112,8 +112,11 @@ export default class AzureLogAnalyticsDatasource extends DataSourceWithBackend< return transformMetadataToKustoSchema(metadata, resourceUri); } - applyTemplateVariables(target: AzureMonitorQuery, scopedVars: ScopedVars): Record { + applyTemplateVariables(target: AzureMonitorQuery, scopedVars: ScopedVars): AzureMonitorQuery { const item = target.azureLogAnalytics; + if (!item) { + return target; + } const templateSrv = getTemplateSrv(); const resource = templateSrv.replace(item.resource, scopedVars); @@ -123,21 +126,19 @@ export default class AzureLogAnalyticsDatasource extends DataSourceWithBackend< workspace = this.defaultOrFirstWorkspace; } - const subscriptionId = templateSrv.replace(target.subscription || this.defaultSubscriptionId, scopedVars); const query = templateSrv.replace(item.query, scopedVars, this.interpolateVariable); return { refId: target.refId, - format: target.format, queryType: AzureQueryType.LogAnalytics, - subscriptionId: subscriptionId, + azureLogAnalytics: { resultFormat: item.resultFormat, - query: query, + query, resource, - // TODO: Workspace is deprecated and should be migrated to Resources - workspace: workspace, + // Workspace was removed in Grafana 8, but remains for backwards compat + workspace, }, }; } diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_monitor/azure_monitor_datasource.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_monitor/azure_monitor_datasource.ts index 3e6496572cf..ff5f1d44f22 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_monitor/azure_monitor_datasource.ts +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_monitor/azure_monitor_datasource.ts @@ -77,6 +77,7 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend { + applyTemplateVariables(target: AzureMonitorQuery, scopedVars: ScopedVars): AzureMonitorQuery { const item = target.azureMonitor; + if (!item) { + // return target; + throw new Error('Query is not a valid Azure Monitor Metrics query'); + } + // fix for timeGrainUnit which is a deprecated/removed field name - if (item.timeGrainUnit && item.timeGrain !== 'auto') { + if (item.timeGrain && item.timeGrainUnit && item.timeGrain !== 'auto') { item.timeGrain = TimegrainConverter.createISO8601Duration(item.timeGrain, item.timeGrainUnit); } @@ -191,7 +199,7 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend f.dimension && f.dimension !== 'None') .map((f) => { const filter = templateSrv.replace(f.filter ?? '', scopedVars); @@ -219,7 +227,6 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend { }; expect(ctx.ds.applyTemplateVariables(target)).toStrictEqual({ azureResourceGraph: { query: 'Resources | var1-foo', resultFormat: 'table' }, - format: undefined, queryType: 'Azure Resource Graph', refId: undefined, subscriptions: undefined, @@ -94,7 +93,6 @@ describe('AzureResourceGraphDatasource', () => { query: `resources | where $__contains(name, 'var3-foo','var3-baz')`, resultFormat: 'table', }, - format: undefined, queryType: 'Azure Resource Graph', refId: undefined, subscriptions: undefined, diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_resource_graph/azure_resource_graph_datasource.ts b/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_resource_graph/azure_resource_graph_datasource.ts index da71c28c160..4ac37c91bd3 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_resource_graph/azure_resource_graph_datasource.ts +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/azure_resource_graph/azure_resource_graph_datasource.ts @@ -12,16 +12,17 @@ export default class AzureResourceGraphDatasource extends DataSourceWithBackend< return !!item.azureResourceGraph?.query; } - applyTemplateVariables(target: AzureMonitorQuery, scopedVars: ScopedVars): Record { + applyTemplateVariables(target: AzureMonitorQuery, scopedVars: ScopedVars): AzureMonitorQuery { const item = target.azureResourceGraph; + if (!item) { + return target; + } const templateSrv = getTemplateSrv(); - const query = templateSrv.replace(item.query, scopedVars, this.interpolateVariable); return { refId: target.refId, - format: target.format, queryType: AzureQueryType.AzureResourceGraph, subscriptions: target.subscriptions, azureResourceGraph: { diff --git a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/ArgQueryEditor/QueryField.tsx b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/ArgQueryEditor/QueryField.tsx index c4330fa7db5..9f05f8a16ee 100644 --- a/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/ArgQueryEditor/QueryField.tsx +++ b/public/app/plugins/datasource/grafana-azure-monitor-datasource/components/ArgQueryEditor/QueryField.tsx @@ -18,7 +18,7 @@ const QueryField: React.FC = ({ query, onQueryChange return ( = ({ query
= ({ query = ({ query, datasource, o } useEffect(() => { - if (!query.azureLogAnalytics.resource) { + if (!query.azureLogAnalytics?.resource) { return; } @@ -54,7 +54,7 @@ const QueryField: React.FC = ({ query, datasource, o }); }); }); - }, [datasource.azureLogAnalyticsDatasource, query.azureLogAnalytics.resource]); + }, [datasource.azureLogAnalyticsDatasource, query.azureLogAnalytics?.resource]); const handleEditorMount = useCallback((editor: MonacoEditor, monaco: Monaco) => { monacoPromiseRef.current?.resolve?.({ editor, monaco }); @@ -75,7 +75,7 @@ const QueryField: React.FC = ({ query, datasource, o return ( = ({ query, datasource, onQueryChange }) => { const styles = useStyles2(getStyles); - const { resource } = query.azureLogAnalytics; + const { resource } = query.azureLogAnalytics ?? {}; const [pickerIsOpen, setPickerIsOpen] = useState(false); @@ -58,7 +58,7 @@ const ResourceField: React.FC = ({ query, datasource = ({ - query, - datasource, - subscriptionId, - variableOptionGroup, - onQueryChange, - setError, -}) => { - const [workspaces, setWorkspaces] = useState([]); - - useEffect(() => { - if (!subscriptionId) { - workspaces.length > 0 && setWorkspaces([]); - return; - } - - datasource - .getAzureLogAnalyticsWorkspaces(subscriptionId) - .then((results) => { - setWorkspaces(results.map(toOption)); - }) - .catch((err) => setError(ERROR_SOURCE, err)); - }, [datasource, setError, subscriptionId, workspaces.length]); - - const handleChange = useCallback( - (change: SelectableValue) => { - if (!change.value) { - return; - } - - onQueryChange({ - ...query, - azureLogAnalytics: { - ...query.azureLogAnalytics, - workspace: change.value, - }, - }); - }, - [onQueryChange, query] - ); - - const options = useMemo(() => [...workspaces, variableOptionGroup], [workspaces, variableOptionGroup]); - - return ( - - = ({ query, dimensionOptions, onQueryChange }) => { + const dimensionFilters = useMemo(() => query.azureMonitor?.dimensionFilters ?? [], [ + query.azureMonitor?.dimensionFilters, + ]); + const setDimensionFilters = useCallback( (newFilters: AzureMetricDimension[]) => { onQueryChange({ @@ -25,17 +29,17 @@ const DimensionFields: React.FC = ({ query, dimensionOptio const addFilter = useCallback(() => { setDimensionFilters([ - ...query.azureMonitor.dimensionFilters, + ...dimensionFilters, { dimension: '', operator: 'eq', filter: '', }, ]); - }, [query.azureMonitor.dimensionFilters, setDimensionFilters]); + }, [dimensionFilters, setDimensionFilters]); const removeFilter = (index: number) => { - const newFilters = [...query.azureMonitor.dimensionFilters]; + const newFilters = [...dimensionFilters]; newFilters.splice(index, 1); setDimensionFilters(newFilters); }; @@ -45,7 +49,7 @@ const DimensionFields: React.FC = ({ query, dimensionOptio fieldName: Key, value: AzureMetricDimension[Key] ) => { - const newFilters = [...query.azureMonitor.dimensionFilters]; + const newFilters = [...dimensionFilters]; const newFilter = newFilters[filterIndex]; newFilter[fieldName] = value; setDimensionFilters(newFilters); @@ -60,7 +64,7 @@ const DimensionFields: React.FC = ({ query, dimensionOptio return ( - {query.azureMonitor.dimensionFilters.map((filter, index) => ( + {dimensionFilters.map((filter, index) => ( = ({ const [isLoading, setIsLoading] = useState(false); useEffect(() => { - const { resourceGroup, metricDefinition, resourceName } = query.azureMonitor; + const { resourceGroup, metricDefinition, resourceName } = query.azureMonitor ?? {}; if (!(subscriptionId && resourceGroup && metricDefinition && resourceName)) { metricNamespaces.length > 0 && setMetricNamespaces([]); return; @@ -73,7 +73,7 @@ const MetricNamespaceField: React.FC = ({ = ({ const [resourceNames, setResourceNames] = useState([]); useEffect(() => { - const { resourceGroup, metricDefinition } = query.azureMonitor; + const { resourceGroup, metricDefinition } = query.azureMonitor ?? {}; if (!(subscriptionId && resourceGroup && metricDefinition)) { resourceNames.length > 0 && setResourceNames([]); @@ -56,7 +56,7 @@ const ResourceNameField: React.FC = ({ const options = useMemo(() => [...resourceNames, variableOptionGroup], [resourceNames, variableOptionGroup]); - const selectedResourceNameValue = findOption(resourceNames, query.azureMonitor.resourceName); + const selectedResourceNameValue = findOption(resourceNames, query.azureMonitor?.resourceName); return ( = ({