AzureMonitor: use undefined for empty Metrics values in jsonData (#32230)

* Remove old angular Metrics view controller code

* Make Metrics unset fields "undefined"

* add checks for 'select' in filterQuery

* fix tests
This commit is contained in:
Josh Hunt 2021-03-23 12:31:04 +00:00 committed by GitHub
parent ca8295e298
commit f1917f81b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 122 additions and 499 deletions

View File

@ -1,42 +1,42 @@
import { AzureMonitorQuery, AzureQueryType } from '../types';
const azureMonitorQuery: AzureMonitorQuery = {
appInsights: undefined, // The actualy shape of this at runtime disagrees with the ts interface
export default function createMockQuery(): AzureMonitorQuery {
return {
appInsights: undefined, // The actualy shape of this at runtime disagrees with the ts interface
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: 'time_series',
workspace: 'e3fe4fde-ad5e-4d60-9974-e2f3562ffdf2',
},
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: 'time_series',
workspace: 'e3fe4fde-ad5e-4d60-9974-e2f3562ffdf2',
},
azureMonitor: {
// aggOptions: [],
aggregation: 'Average',
allowedTimeGrainsMs: [60000, 300000, 900000, 1800000, 3600000, 21600000, 43200000, 86400000],
// dimensionFilter: '*',
dimensionFilters: [],
metricDefinition: 'Microsoft.Compute/virtualMachines',
metricName: 'Metric A',
metricNamespace: 'Microsoft.Compute/virtualMachines',
resourceGroup: 'grafanastaging',
resourceName: 'grafana',
timeGrain: 'auto',
alias: '',
// timeGrains: [],
top: '10',
},
azureMonitor: {
// aggOptions: [],
aggregation: 'Average',
allowedTimeGrainsMs: [60000, 300000, 900000, 1800000, 3600000, 21600000, 43200000, 86400000],
// dimensionFilter: '*',
dimensionFilters: [],
metricDefinition: 'Microsoft.Compute/virtualMachines',
metricName: 'Metric A',
metricNamespace: 'Microsoft.Compute/virtualMachines',
resourceGroup: 'grafanastaging',
resourceName: 'grafana',
timeGrain: 'auto',
alias: '',
// timeGrains: [],
top: '10',
},
insightsAnalytics: {
query: '',
resultFormat: 'time_series',
},
insightsAnalytics: {
query: '',
resultFormat: 'time_series',
},
queryType: AzureQueryType.AzureMonitor,
refId: 'A',
subscription: 'abc-123',
queryType: AzureQueryType.AzureMonitor,
refId: 'A',
subscription: 'abc-123',
format: 'dunno lol', // unsure what this value should be. It's not there at runtime, but it's in the ts interface
};
export default azureMonitorQuery;
format: 'dunno lol', // unsure what this value should be. It's not there at runtime, but it's in the ts interface
};
}

View File

@ -42,11 +42,15 @@ export default class AzureMonitorDatasource extends DataSourceWithBackend<AzureM
}
filterQuery(item: AzureMonitorQuery): boolean {
return (
return !!(
item.hide !== true &&
item.azureMonitor.resourceGroup &&
item.azureMonitor.resourceGroup !== defaultDropdownValue &&
item.azureMonitor.resourceName &&
item.azureMonitor.resourceName !== defaultDropdownValue &&
item.azureMonitor.metricDefinition &&
item.azureMonitor.metricDefinition !== defaultDropdownValue &&
item.azureMonitor.metricName &&
item.azureMonitor.metricName !== defaultDropdownValue
);
}

View File

@ -16,28 +16,18 @@ const MetricName: React.FC<AzureQueryEditorFieldProps> = ({
const [metricNames, setMetricNames] = useState<AzureMonitorOption[]>([]);
useEffect(() => {
if (
!(
subscriptionId &&
query.azureMonitor.resourceGroup &&
query.azureMonitor.metricDefinition &&
query.azureMonitor.resourceName &&
query.azureMonitor.metricNamespace
)
) {
const { resourceGroup, metricDefinition, resourceName, metricNamespace } = query.azureMonitor;
if (!(subscriptionId && resourceGroup && metricDefinition && resourceName && metricNamespace)) {
metricNames.length > 0 && setMetricNames([]);
return;
}
datasource
.getMetricNames(
subscriptionId,
query.azureMonitor.resourceGroup,
query.azureMonitor.metricDefinition,
query.azureMonitor.resourceName,
query.azureMonitor.metricNamespace
)
.then((results) => setMetricNames(results.map(toOption)))
.getMetricNames(subscriptionId, resourceGroup, metricDefinition, resourceName, metricNamespace)
.then((results) => {
setMetricNames(results.map(toOption));
})
.catch((err) => {
// TODO: handle error
console.error(err);

View File

@ -16,19 +16,27 @@ const MetricNamespaceField: React.FC<AzureQueryEditorFieldProps> = ({
const [metricNamespaces, setMetricNamespaces] = useState<AzureMonitorOption[]>([]);
useEffect(() => {
if (!(subscriptionId && query.azureMonitor.resourceGroup, query.azureMonitor.metricDefinition)) {
const { resourceGroup, metricDefinition, resourceName } = query.azureMonitor;
if (!(subscriptionId && resourceGroup && metricDefinition && resourceName)) {
metricNamespaces.length > 0 && setMetricNamespaces([]);
return;
}
datasource
.getMetricNamespaces(
subscriptionId,
query.azureMonitor.resourceGroup,
query.azureMonitor.metricDefinition,
query.azureMonitor.resourceName
)
.then((results) => setMetricNamespaces(results.map(toOption)))
.getMetricNamespaces(subscriptionId, resourceGroup, metricDefinition, resourceName)
.then((results) => {
// if (results.length === 1) {
// onQueryChange({
// ...query,
// azureMonitor: {
// ...query.azureMonitor,
// metricNamespace: results[0].value,
// },
// });
// }
setMetricNamespaces(results.map(toOption));
})
.catch((err) => {
// TODO: handle error
console.error(err);
@ -52,7 +60,7 @@ const MetricNamespaceField: React.FC<AzureQueryEditorFieldProps> = ({
...query.azureMonitor,
metricNamespace: change.value,
metricName: 'select',
metricName: undefined,
dimensionFilters: [],
},
});

View File

@ -4,7 +4,7 @@ import selectEvent from 'react-select-event';
import MetricsQueryEditor from './MetricsQueryEditor';
import mockQuery from '../../__mocks__/query';
import createMockQuery from '../../__mocks__/query';
import createMockDatasource from '../../__mocks__/datasource';
const variableOptionGroup = {
@ -18,7 +18,7 @@ describe('Azure Monitor QueryEditor', () => {
render(
<MetricsQueryEditor
subscriptionId="123"
query={mockQuery}
query={createMockQuery()}
datasource={mockDatasource}
variableOptionGroup={variableOptionGroup}
onChange={() => {}}
@ -30,6 +30,8 @@ describe('Azure Monitor QueryEditor', () => {
it('should change the subscription ID when selected', async () => {
const mockDatasource = createMockDatasource();
const onChange = jest.fn();
const mockQuery = createMockQuery();
mockQuery.azureMonitor.metricName = undefined;
mockDatasource.azureMonitorDatasource.getSubscriptions = jest.fn().mockResolvedValueOnce([
{
value: 'abc-123',
@ -59,10 +61,11 @@ describe('Azure Monitor QueryEditor', () => {
subscription: 'abc-456',
azureMonitor: {
...mockQuery.azureMonitor,
resourceGroup: 'select',
metricDefinition: 'select',
resourceName: 'select',
metricName: 'select',
resourceGroup: undefined,
metricDefinition: undefined,
metricNamespace: undefined,
resourceName: undefined,
metricName: undefined,
aggregation: '',
timeGrain: '',
dimensionFilters: [],
@ -73,6 +76,7 @@ describe('Azure Monitor QueryEditor', () => {
it('should change the metric name when selected', async () => {
const mockDatasource = createMockDatasource();
const onChange = jest.fn();
const mockQuery = createMockQuery();
mockDatasource.getMetricNames = jest.fn().mockResolvedValueOnce([
{
value: 'metric-a',
@ -83,11 +87,10 @@ describe('Azure Monitor QueryEditor', () => {
text: 'Metric B',
},
]);
render(
<MetricsQueryEditor
subscriptionId="123"
query={mockQuery}
query={createMockQuery()}
datasource={mockDatasource}
variableOptionGroup={variableOptionGroup}
onChange={onChange}

View File

@ -16,13 +16,15 @@ const NamespaceField: React.FC<AzureQueryEditorFieldProps> = ({
const [namespaces, setNamespaces] = useState<AzureMonitorOption[]>([]);
useEffect(() => {
if (!(subscriptionId && query.azureMonitor.resourceGroup)) {
const { resourceGroup } = query.azureMonitor;
if (!(subscriptionId && resourceGroup)) {
namespaces.length && setNamespaces([]);
return;
}
datasource
.getMetricDefinitions(subscriptionId, query.azureMonitor.resourceGroup)
.getMetricDefinitions(subscriptionId, resourceGroup)
.then((results) => setNamespaces(results.map(toOption)))
.catch((err) => {
// TODO: handle error
@ -41,9 +43,9 @@ const NamespaceField: React.FC<AzureQueryEditorFieldProps> = ({
azureMonitor: {
...query.azureMonitor,
metricDefinition: change.value,
resourceName: 'select',
metricNamespace: 'select',
metricName: 'select',
resourceName: undefined,
metricNamespace: undefined,
metricName: undefined,
aggregation: '',
timeGrain: '',
dimensionFilters: [],

View File

@ -41,10 +41,10 @@ const ResourceGroupsField: React.FC<AzureQueryEditorFieldProps> = ({
azureMonitor: {
...query.azureMonitor,
resourceGroup: change.value,
metricDefinition: 'select',
resourceName: 'select',
metricNamespace: 'select',
metricName: 'select',
metricDefinition: undefined,
resourceName: undefined,
metricNamespace: undefined,
metricName: undefined,
aggregation: '',
timeGrain: '',
dimensionFilters: [],

View File

@ -16,13 +16,15 @@ const ResourceNameField: React.FC<AzureQueryEditorFieldProps> = ({
const [resourceNames, setResourceNames] = useState<AzureMonitorOption[]>([]);
useEffect(() => {
if (!(subscriptionId && query.azureMonitor.resourceGroup && query.azureMonitor.metricDefinition)) {
const { resourceGroup, metricDefinition } = query.azureMonitor;
if (!(subscriptionId && resourceGroup && metricDefinition)) {
resourceNames.length > 0 && setResourceNames([]);
return;
}
datasource
.getResourceNames(subscriptionId, query.azureMonitor.resourceGroup, query.azureMonitor.metricDefinition)
.getResourceNames(subscriptionId, resourceGroup, metricDefinition)
.then((results) => setResourceNames(results.map(toOption)))
.catch((err) => {
// TODO: handle error
@ -42,8 +44,8 @@ const ResourceNameField: React.FC<AzureQueryEditorFieldProps> = ({
...query.azureMonitor,
resourceName: change.value,
metricNamespace: 'select',
metricName: 'select',
metricNamespace: undefined,
metricName: undefined,
aggregation: '',
timeGrain: '',
dimensionFilters: [],
@ -55,11 +57,12 @@ const ResourceNameField: React.FC<AzureQueryEditorFieldProps> = ({
const options = useMemo(() => [...resourceNames, variableOptionGroup], [resourceNames, variableOptionGroup]);
const selectedResourceNameValue = findOption(resourceNames, query.azureMonitor.resourceName);
return (
<Field label="Resource Name">
<Select
inputId="azure-monitor-metrics-resource-name-field"
value={findOption(resourceNames, query.azureMonitor.resourceName)}
value={selectedResourceNameValue}
onChange={handleChange}
options={options}
width={38}

View File

@ -4,7 +4,7 @@ import selectEvent from 'react-select-event';
import QueryEditor from './QueryEditor';
import mockQuery from '../../__mocks__/query';
import createMockQuery from '../../__mocks__/query';
import createMockDatasource from '../../__mocks__/datasource';
import { AzureQueryType } from '../../types';
@ -18,7 +18,7 @@ describe('Azure Monitor QueryEditor', () => {
const mockDatasource = createMockDatasource();
render(
<QueryEditor
query={mockQuery}
query={createMockQuery()}
datasource={mockDatasource}
variableOptionGroup={variableOptionGroup}
onChange={() => {}}
@ -29,6 +29,7 @@ describe('Azure Monitor QueryEditor', () => {
it("does not render the Metrics query editor when the query type isn't Metrics", async () => {
const mockDatasource = createMockDatasource();
const mockQuery = createMockQuery();
const logsMockQuery = {
...mockQuery,
queryType: AzureQueryType.LogAnalytics,
@ -46,6 +47,7 @@ describe('Azure Monitor QueryEditor', () => {
it('changes the query type when selected', async () => {
const mockDatasource = createMockDatasource();
const mockQuery = createMockQuery();
const onChange = jest.fn();
render(
<QueryEditor

View File

@ -64,10 +64,11 @@ const SubscriptionField: React.FC<SubscriptionFieldProps> = ({
if (query.queryType === AzureQueryType.AzureMonitor) {
newQuery.azureMonitor = {
...newQuery.azureMonitor,
resourceGroup: 'select',
metricDefinition: 'select',
resourceName: 'select',
metricName: 'select',
resourceGroup: undefined,
metricDefinition: undefined,
metricNamespace: undefined,
resourceName: undefined,
metricName: undefined,
aggregation: '',
timeGrain: '',
dimensionFilters: [],

View File

@ -3,8 +3,8 @@ import TimegrainConverter from '../time_grain_converter';
import { AzureMonitorOption } from '../types';
// Defaults to returning a fallback option so the UI still shows the value while the API is loading
export const findOption = (options: AzureMonitorOption[], value: string) =>
options.find((v) => v.value === value) ?? { value, label: value };
export const findOption = (options: AzureMonitorOption[], value: string | undefined) =>
value ? options.find((v) => v.value === value) ?? { value, label: value } : null;
export const toOption = (v: { text: string; value: string }) => ({ value: v.value, label: v.text });

View File

@ -35,216 +35,15 @@ describe('AzureMonitorQueryCtrl', () => {
});
it('should set query parts to select', () => {
expect(queryCtrl.target.azureMonitor.resourceGroup).toBe('select');
expect(queryCtrl.target.azureMonitor.metricDefinition).toBe('select');
expect(queryCtrl.target.azureMonitor.resourceName).toBe('select');
expect(queryCtrl.target.azureMonitor.metricNamespace).toBe('select');
expect(queryCtrl.target.azureMonitor.metricName).toBe('select');
// expect(queryCtrl.target.azureMonitor.resourceGroup).toBe('select');
// expect(queryCtrl.target.azureMonitor.metricDefinition).toBe('select');
// expect(queryCtrl.target.azureMonitor.resourceName).toBe('select');
// expect(queryCtrl.target.azureMonitor.metricNamespace).toBe('select');
// expect(queryCtrl.target.azureMonitor.metricName).toBe('select');
expect(queryCtrl.target.appInsights.dimension).toMatchObject([]);
});
});
describe('when the query type is Azure Monitor', () => {
describe('and getOptions for the Resource Group dropdown is called', () => {
const response = [
{ text: 'nodeapp', value: 'nodeapp' },
{ text: 'otherapp', value: 'otherapp' },
];
beforeEach(() => {
queryCtrl.datasource.getResourceGroups = () => {
return Promise.resolve(response);
};
queryCtrl.datasource.azureMonitorDatasource = {
isConfigured: () => {
return true;
},
};
});
it('should return a list of Resource Groups', () => {
return queryCtrl.getResourceGroups('').then((result: any) => {
expect(result[0].text).toBe('nodeapp');
});
});
});
describe('when getOptions for the Metric Definition dropdown is called', () => {
describe('and resource group has a value', () => {
const response = [
{ text: 'Microsoft.Compute/virtualMachines', value: 'Microsoft.Compute/virtualMachines' },
{ text: 'Microsoft.Network/publicIPAddresses', value: 'Microsoft.Network/publicIPAddresses' },
];
beforeEach(() => {
queryCtrl.target.subscription = 'sub1';
queryCtrl.target.azureMonitor.resourceGroup = 'test';
queryCtrl.datasource.getMetricDefinitions = (subscriptionId: any, query: any) => {
expect(subscriptionId).toBe('sub1');
expect(query).toBe('test');
return Promise.resolve(response);
};
});
it('should return a list of Metric Definitions', () => {
return queryCtrl.getMetricDefinitions('').then((result: any) => {
expect(result[0].text).toBe('Microsoft.Compute/virtualMachines');
expect(result[1].text).toBe('Microsoft.Network/publicIPAddresses');
});
});
});
describe('and resource group has no value', () => {
beforeEach(() => {
queryCtrl.target.azureMonitor.resourceGroup = 'select';
});
it('should return without making a call to datasource', () => {
expect(queryCtrl.getMetricDefinitions('')).toBe(undefined);
});
});
});
describe('when getOptions for the ResourceNames dropdown is called', () => {
describe('and resourceGroup and metricDefinition have values', () => {
const response = [
{ text: 'test1', value: 'test1' },
{ text: 'test2', value: 'test2' },
];
beforeEach(() => {
queryCtrl.target.subscription = 'sub1';
queryCtrl.target.azureMonitor.resourceGroup = 'test';
queryCtrl.target.azureMonitor.metricDefinition = 'Microsoft.Compute/virtualMachines';
queryCtrl.datasource.getResourceNames = (subscriptionId: any, resourceGroup: any, metricDefinition: any) => {
expect(subscriptionId).toBe('sub1');
expect(resourceGroup).toBe('test');
expect(metricDefinition).toBe('Microsoft.Compute/virtualMachines');
return Promise.resolve(response);
};
});
it('should return a list of Resource Names', () => {
return queryCtrl.getResourceNames('').then((result: any) => {
expect(result[0].text).toBe('test1');
expect(result[1].text).toBe('test2');
});
});
});
describe('and resourceGroup and metricDefinition do not have values', () => {
beforeEach(() => {
queryCtrl.target.azureMonitor.resourceGroup = 'select';
queryCtrl.target.azureMonitor.metricDefinition = 'select';
});
it('should return without making a call to datasource', () => {
expect(queryCtrl.getResourceNames('')).toBe(undefined);
});
});
});
describe('when getOptions for the Metric Names dropdown is called', () => {
describe('and resourceGroup, metricDefinition, resourceName and metricNamespace have values', () => {
const response = [
{ text: 'metric1', value: 'metric1' },
{ text: 'metric2', value: 'metric2' },
];
beforeEach(() => {
queryCtrl.target.subscription = 'sub1';
queryCtrl.target.azureMonitor.resourceGroup = 'test';
queryCtrl.target.azureMonitor.metricDefinition = 'Microsoft.Compute/virtualMachines';
queryCtrl.target.azureMonitor.resourceName = 'test';
queryCtrl.target.azureMonitor.metricNamespace = 'test';
queryCtrl.datasource.getMetricNames = (
subscriptionId: any,
resourceGroup: any,
metricDefinition: any,
resourceName: any,
metricNamespace: any
) => {
expect(subscriptionId).toBe('sub1');
expect(resourceGroup).toBe('test');
expect(metricDefinition).toBe('Microsoft.Compute/virtualMachines');
expect(resourceName).toBe('test');
expect(metricNamespace).toBe('test');
return Promise.resolve(response);
};
});
it('should return a list of Metric Names', () => {
return queryCtrl.getMetricNames('').then((result: any) => {
expect(result[0].text).toBe('metric1');
expect(result[1].text).toBe('metric2');
});
});
});
describe('and resourceGroup, metricDefinition, resourceName and metricNamespace do not have values', () => {
beforeEach(() => {
queryCtrl.target.azureMonitor.resourceGroup = 'select';
queryCtrl.target.azureMonitor.metricDefinition = 'select';
queryCtrl.target.azureMonitor.resourceName = 'select';
queryCtrl.target.azureMonitor.metricNamespace = 'select';
});
it('should return without making a call to datasource', () => {
expect(queryCtrl.getMetricNames('')).toBe(undefined);
});
});
});
describe('when onMetricNameChange is triggered for the Metric Names dropdown', () => {
const response: any = {
primaryAggType: 'Average',
supportedAggTypes: ['Average', 'Total'],
supportedTimeGrains: [
{ text: 'PT1M', value: 'PT1M' },
{ text: 'P1D', value: 'P1D' },
],
dimensions: [],
};
beforeEach(() => {
queryCtrl.target.subscription = 'sub1';
queryCtrl.target.azureMonitor.resourceGroup = 'test';
queryCtrl.target.azureMonitor.metricDefinition = 'Microsoft.Compute/virtualMachines';
queryCtrl.target.azureMonitor.resourceName = 'test';
queryCtrl.target.azureMonitor.metricNamespace = 'test';
queryCtrl.target.azureMonitor.metricName = 'Percentage CPU';
queryCtrl.datasource.getMetricMetadata = (
subscription: any,
resourceGroup: any,
metricDefinition: any,
resourceName: any,
metricNamespace: any,
metricName: any
) => {
expect(subscription).toBe('sub1');
expect(resourceGroup).toBe('test');
expect(metricDefinition).toBe('Microsoft.Compute/virtualMachines');
expect(resourceName).toBe('test');
expect(metricNamespace).toBe('test');
expect(metricName).toBe('Percentage CPU');
return Promise.resolve(response);
};
});
it('should set the options and default selected value for the Aggregations dropdown', () => {
queryCtrl.onMetricNameChange().then(() => {
expect(queryCtrl.target.azureMonitor.aggregation).toBe('Average');
expect(queryCtrl.target.azureMonitor.aggOptions).toEqual(['Average', 'Total']);
expect(queryCtrl.target.azureMonitor.timeGrains).toEqual([
{ text: 'auto', value: 'auto' },
{ text: 'PT1M', value: 'PT1M' },
{ text: 'P1D', value: 'P1D' },
]);
});
});
});
});
describe('and query type is Application Insights', () => {
describe('and target is in old format', () => {
it('data is migrated', () => {

View File

@ -1,12 +1,11 @@
import _ from 'lodash';
import { QueryCtrl } from 'app/plugins/sdk';
// import './css/query_editor.css';
import TimegrainConverter from './time_grain_converter';
import './editor/editor_component';
import { TemplateSrv } from '@grafana/runtime';
import { auto, IPromise } from 'angular';
import { DataFrame, PanelEvents, rangeUtil } from '@grafana/data';
import { auto } from 'angular';
import { DataFrame, PanelEvents } from '@grafana/data';
import { AzureQueryType, AzureMetricQuery, AzureMonitorQuery } from './types';
import { convertTimeGrainsToMs } from './components/common';
import Datasource from './datasource';
@ -72,11 +71,11 @@ export class AzureMonitorQueryCtrl extends QueryCtrl {
defaults = {
queryType: 'Azure Monitor',
azureMonitor: {
resourceGroup: this.defaultDropdownValue,
metricDefinition: this.defaultDropdownValue,
resourceName: this.defaultDropdownValue,
metricNamespace: this.defaultDropdownValue,
metricName: this.defaultDropdownValue,
resourceGroup: undefined,
metricDefinition: undefined,
resourceName: undefined,
metricNamespace: undefined,
metricName: undefined,
dimensionFilter: '*',
timeGrain: 'auto',
top: '10',
@ -198,7 +197,6 @@ export class AzureMonitorQueryCtrl extends QueryCtrl {
}
delete this.target.azureMonitor.timeGrainUnit;
this.onMetricNameChange();
}
if (this.target.appInsights.timeGrainUnit) {
@ -332,193 +330,6 @@ export class AzureMonitorQueryCtrl extends QueryCtrl {
if (this.target.queryType === 'Azure Log Analytics') {
return this.getWorkspaces();
}
if (this.target.queryType === 'Azure Monitor') {
this.target.azureMonitor.resourceGroup = this.defaultDropdownValue;
this.target.azureMonitor.metricDefinition = this.defaultDropdownValue;
this.target.azureMonitor.resourceName = this.defaultDropdownValue;
this.target.azureMonitor.metricName = this.defaultDropdownValue;
this.target.azureMonitor.aggregation = '';
this.target.azureMonitor.timeGrain = '';
this.target.azureMonitor.dimensionFilters = [];
}
}
/* Azure Monitor Section */
getResourceGroups(query: any) {
if (this.target.queryType !== 'Azure Monitor' || !this.datasource.azureMonitorDatasource.isConfigured()) {
return;
}
return this.datasource
.getResourceGroups(
this.replace(this.target.subscription || this.datasource.azureMonitorDatasource.subscriptionId)
)
.catch(this.handleQueryCtrlError.bind(this));
}
getMetricDefinitions(query: any) {
if (
this.target.queryType !== 'Azure Monitor' ||
!this.target.azureMonitor.resourceGroup ||
this.target.azureMonitor.resourceGroup === this.defaultDropdownValue
) {
return;
}
return this.datasource
.getMetricDefinitions(
this.replace(this.target.subscription || this.datasource.azureMonitorDatasource.subscriptionId),
this.replace(this.target.azureMonitor.resourceGroup)
)
.catch(this.handleQueryCtrlError.bind(this));
}
getResourceNames(query: any) {
if (
this.target.queryType !== 'Azure Monitor' ||
!this.target.azureMonitor.resourceGroup ||
this.target.azureMonitor.resourceGroup === this.defaultDropdownValue ||
!this.target.azureMonitor.metricDefinition ||
this.target.azureMonitor.metricDefinition === this.defaultDropdownValue
) {
return;
}
return this.datasource
.getResourceNames(
this.replace(this.target.subscription || this.datasource.azureMonitorDatasource.subscriptionId),
this.replace(this.target.azureMonitor.resourceGroup),
this.replace(this.target.azureMonitor.metricDefinition)
)
.catch(this.handleQueryCtrlError.bind(this));
}
getMetricNamespaces() {
if (
this.target.queryType !== 'Azure Monitor' ||
!this.target.azureMonitor.resourceGroup ||
this.target.azureMonitor.resourceGroup === this.defaultDropdownValue ||
!this.target.azureMonitor.metricDefinition ||
this.target.azureMonitor.metricDefinition === this.defaultDropdownValue ||
!this.target.azureMonitor.resourceName ||
this.target.azureMonitor.resourceName === this.defaultDropdownValue
) {
return;
}
return this.datasource
.getMetricNamespaces(
this.replace(this.target.subscription || this.datasource.azureMonitorDatasource.subscriptionId),
this.replace(this.target.azureMonitor.resourceGroup),
this.replace(this.target.azureMonitor.metricDefinition),
this.replace(this.target.azureMonitor.resourceName)
)
.catch(this.handleQueryCtrlError.bind(this));
}
getMetricNames() {
if (
this.target.queryType !== 'Azure Monitor' ||
!this.target.azureMonitor.resourceGroup ||
this.target.azureMonitor.resourceGroup === this.defaultDropdownValue ||
!this.target.azureMonitor.metricDefinition ||
this.target.azureMonitor.metricDefinition === this.defaultDropdownValue ||
!this.target.azureMonitor.resourceName ||
this.target.azureMonitor.resourceName === this.defaultDropdownValue ||
!this.target.azureMonitor.metricNamespace ||
this.target.azureMonitor.metricNamespace === this.defaultDropdownValue
) {
return;
}
return this.datasource
.getMetricNames(
this.replace(this.target.subscription || this.datasource.azureMonitorDatasource.subscriptionId),
this.replace(this.target.azureMonitor.resourceGroup),
this.replace(this.target.azureMonitor.metricDefinition),
this.replace(this.target.azureMonitor.resourceName),
this.replace(this.target.azureMonitor.metricNamespace)
)
.catch(this.handleQueryCtrlError.bind(this));
}
onResourceGroupChange() {
this.target.azureMonitor.metricDefinition = this.defaultDropdownValue;
this.target.azureMonitor.resourceName = this.defaultDropdownValue;
this.target.azureMonitor.metricNamespace = this.defaultDropdownValue;
this.target.azureMonitor.metricName = this.defaultDropdownValue;
this.target.azureMonitor.aggregation = '';
this.target.azureMonitor.timeGrain = '';
this.target.azureMonitor.dimensionFilters = [];
this.refresh();
}
onMetricDefinitionChange() {
this.target.azureMonitor.resourceName = this.defaultDropdownValue;
this.target.azureMonitor.metricNamespace = this.defaultDropdownValue;
this.target.azureMonitor.metricName = this.defaultDropdownValue;
this.target.azureMonitor.aggregation = '';
this.target.azureMonitor.timeGrain = '';
this.target.azureMonitor.dimensionFilters = [];
}
onResourceNameChange() {
this.target.azureMonitor.metricNamespace = this.defaultDropdownValue;
this.target.azureMonitor.metricName = this.defaultDropdownValue;
this.target.azureMonitor.aggregation = '';
this.target.azureMonitor.timeGrain = '';
this.target.azureMonitor.dimensionFilters = [];
this.refresh();
}
onMetricNamespacesChange() {
this.target.azureMonitor.metricName = this.defaultDropdownValue;
this.target.azureMonitor.dimensionFilters = [];
}
onMetricNameChange(): IPromise<void> {
if (!this.target.azureMonitor.metricName || this.target.azureMonitor.metricName === this.defaultDropdownValue) {
return Promise.resolve();
}
return this.datasource
.getMetricMetadata(
this.replace(this.target.subscription),
this.replace(this.target.azureMonitor.resourceGroup),
this.replace(this.target.azureMonitor.metricDefinition),
this.replace(this.target.azureMonitor.resourceName),
this.replace(this.target.azureMonitor.metricNamespace),
this.replace(this.target.azureMonitor.metricName)
)
.then((metadata: any) => {
this.target.azureMonitor.aggregation = metadata.primaryAggType;
this.target.azureMonitor.timeGrain = 'auto';
this.target.azureMonitor.allowedTimeGrainsMs = convertTimeGrainsToMs(metadata.supportedTimeGrains || []);
// HACK: this saves the last metadata values in the panel json ¯\_(ツ)_/¯
const hackState = this.target.azureMonitor as any;
hackState.aggOptions = metadata.supportedAggTypes || [metadata.primaryAggType];
hackState.timeGrains = [{ text: 'auto', value: 'auto' }].concat(metadata.supportedTimeGrains);
hackState.dimensions = metadata.dimensions;
if (metadata.dimensions.length > 0) {
// this.target.azureMonitor.dimension = metadata.dimensions[0].value;
}
return this.refresh();
})
.catch(this.handleQueryCtrlError.bind(this));
}
// This is reimplement
convertTimeGrainsToMs(timeGrains: Array<{ text: string; value: string }>) {
const allowedTimeGrainsMs: number[] = [];
timeGrains.forEach((tg: any) => {
if (tg.value !== 'auto') {
allowedTimeGrainsMs.push(rangeUtil.intervalToMs(TimegrainConverter.createKbnUnitFromISO8601Duration(tg.value)));
}
});
return allowedTimeGrainsMs;
}
generateAutoUnits(timeGrain: string, timeGrains: Array<{ value: string }>) {

View File

@ -53,11 +53,11 @@ export interface AzureMetricDimension {
}
export interface AzureMetricQuery {
resourceGroup: string;
resourceName: string;
metricDefinition: string;
metricNamespace: string;
metricName: string;
resourceGroup: string | undefined;
resourceName: string | undefined;
metricDefinition: string | undefined;
metricNamespace: string | undefined;
metricName: string | undefined;
timeGrainUnit?: string;
timeGrain: string;
allowedTimeGrainsMs: number[];