mirror of
https://github.com/grafana/grafana.git
synced 2025-02-09 23:16:16 -06:00
AzureMonitor: Fix auto-selection of time-grain for metrics. (#49278)
* Update query editor to fix auto time-grain selection * Update new query editor to fix auto time-grain selection * Remove log and fix lint issues * Add test for useMetricMetadata - Add necessary types * More test updates - Update old dataHooks test - Ensure query changes Co-authored-by: Kevin Yu <kevinwcyu@users.noreply.github.com> Co-authored-by: Andres Martinez Gotor <andres.mgotor@gmail.com> Co-authored-by: Erik Sundell <erik.sundell87@gmail.com>
This commit is contained in:
parent
bd320ee0b3
commit
2780651ea8
@ -106,6 +106,7 @@ func (e *AzureMonitorDatasource) buildQueries(queries []backend.DataQuery, dsInf
|
||||
|
||||
timeGrain := azJSONModel.TimeGrain
|
||||
timeGrains := azJSONModel.AllowedTimeGrainsMs
|
||||
|
||||
if timeGrain == "auto" {
|
||||
timeGrain, err = azTime.SetAutoTimeGrain(query.Interval.Milliseconds(), timeGrains)
|
||||
if err != nil {
|
||||
|
@ -6,7 +6,10 @@ import { AzureMetricQuery, AzureMonitorOption, AzureMonitorQuery, AzureQueryType
|
||||
|
||||
import {
|
||||
DataHook,
|
||||
MetricMetadata,
|
||||
MetricsMetadataHook,
|
||||
updateSubscriptions,
|
||||
useMetricMetadata,
|
||||
useMetricNames,
|
||||
useMetricNamespaces,
|
||||
useResourceGroups,
|
||||
@ -23,7 +26,7 @@ const opt = (text: string, value: string) => ({ text, value });
|
||||
|
||||
interface TestScenario {
|
||||
name: string;
|
||||
hook: DataHook;
|
||||
hook: DataHook | MetricsMetadataHook;
|
||||
|
||||
// For convenience, only need to define the azureMonitor part of the query for some tests
|
||||
emptyQueryPartial: AzureMetricQuery;
|
||||
@ -31,7 +34,7 @@ interface TestScenario {
|
||||
topLevelCustomProperties?: Partial<AzureMonitorQuery>;
|
||||
|
||||
expectedCustomPropertyResults?: Array<AzureMonitorOption<string>>;
|
||||
expectedOptions: AzureMonitorOption[];
|
||||
expectedOptions: AzureMonitorOption[] | MetricMetadata;
|
||||
}
|
||||
|
||||
describe('AzureMonitor: metrics dataHooks', () => {
|
||||
@ -255,7 +258,25 @@ describe('AzureMonitor: metrics dataHooks', () => {
|
||||
datasource.azureMonitorDatasource.getMetricNamespaces = jest
|
||||
.fn()
|
||||
.mockResolvedValue([opt('Compute Virtual Machine', 'azure/vmc'), opt('Database NS', 'azure/dbns')]);
|
||||
|
||||
datasource.azureMonitorDatasource.getMetricMetadata = jest.fn().mockResolvedValue({
|
||||
primaryAggType: 'Average',
|
||||
supportedAggTypes: ['Average'],
|
||||
supportedTimeGrains: [
|
||||
{ label: 'Auto', value: 'auto' },
|
||||
{ label: '1 minute', value: 'PT1M' },
|
||||
{ label: '5 minutes', value: 'PT5M' },
|
||||
{ label: '15 minutes', value: 'PT15M' },
|
||||
{ label: '30 minutes', value: 'PT30M' },
|
||||
{ label: '1 hour', value: 'PT1H' },
|
||||
{ label: '6 hours', value: 'PT6H' },
|
||||
{ label: '12 hours', value: 'PT12H' },
|
||||
{ label: '1 day', value: 'P1D' },
|
||||
],
|
||||
dimensions: [],
|
||||
});
|
||||
});
|
||||
|
||||
describe.each(testTable)('scenario %#: $name', (scenario) => {
|
||||
it('returns values', async () => {
|
||||
const query = {
|
||||
@ -280,6 +301,60 @@ describe('AzureMonitor: metrics dataHooks', () => {
|
||||
expect(result.current).toEqual(scenario.expectedCustomPropertyResults);
|
||||
});
|
||||
});
|
||||
|
||||
describe('useMetricsMetadataHook', () => {
|
||||
const metricsMetadataConfig = {
|
||||
name: 'useMetricMetadata',
|
||||
hook: useMetricMetadata,
|
||||
emptyQueryPartial: {
|
||||
resourceGroup: 'web-app-development',
|
||||
metricDefinition: 'azure/vm',
|
||||
resourceName: 'web-server',
|
||||
metricNamespace: 'azure/vm',
|
||||
subscription: 'test-sub',
|
||||
metricName: 'Average CPU',
|
||||
},
|
||||
customProperties: {},
|
||||
expectedOptions: {
|
||||
aggOptions: [{ label: 'Average', value: 'Average' }],
|
||||
timeGrains: [
|
||||
{ label: 'Auto', value: 'auto' },
|
||||
{ label: '1 minute', value: 'PT1M' },
|
||||
{ label: '5 minutes', value: 'PT5M' },
|
||||
{ label: '15 minutes', value: 'PT15M' },
|
||||
{ label: '30 minutes', value: 'PT30M' },
|
||||
{ label: '1 hour', value: 'PT1H' },
|
||||
{ label: '6 hours', value: 'PT6H' },
|
||||
{ label: '12 hours', value: 'PT12H' },
|
||||
{ label: '1 day', value: 'P1D' },
|
||||
],
|
||||
dimensions: [],
|
||||
isLoading: false,
|
||||
supportedAggTypes: ['Average'],
|
||||
primaryAggType: 'Average',
|
||||
},
|
||||
};
|
||||
|
||||
it('returns values', async () => {
|
||||
const query = {
|
||||
...bareQuery,
|
||||
azureMonitor: metricsMetadataConfig.emptyQueryPartial,
|
||||
};
|
||||
const { result, waitForNextUpdate } = renderHook(() => metricsMetadataConfig.hook(query, datasource, onChange));
|
||||
await waitForNextUpdate(WAIT_OPTIONS);
|
||||
|
||||
expect(result.current).toEqual(metricsMetadataConfig.expectedOptions);
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
...query,
|
||||
azureMonitor: {
|
||||
...query.azureMonitor,
|
||||
aggregation: result.current.primaryAggType,
|
||||
timeGrain: 'auto',
|
||||
allowedTimeGrainsMs: [60_000, 300_000, 900_000, 1_800_000, 3_600_000, 21_600_000, 43_200_000, 86_400_000],
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('AzureMonitor: updateSubscriptions', () => {
|
||||
|
@ -1,6 +1,9 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { rangeUtil } from '@grafana/data';
|
||||
|
||||
import Datasource from '../../datasource';
|
||||
import TimegrainConverter from '../../time_grain_converter';
|
||||
import { AzureMonitorErrorish, AzureMonitorOption, AzureMonitorQuery } from '../../types';
|
||||
import { hasOption, toOption } from '../../utils/common';
|
||||
import { useAsyncState } from '../../utils/useAsyncState';
|
||||
@ -28,6 +31,12 @@ export type DataHook = (
|
||||
setError: SetErrorFn
|
||||
) => AzureMonitorOption[];
|
||||
|
||||
export type MetricsMetadataHook = (
|
||||
query: AzureMonitorQuery,
|
||||
datasource: Datasource,
|
||||
onChange: OnChangeFn
|
||||
) => MetricMetadata;
|
||||
|
||||
export const updateSubscriptions = (
|
||||
query: AzureMonitorQuery,
|
||||
subscriptionOptions: AzureMonitorOption[],
|
||||
@ -231,7 +240,6 @@ export const useMetricMetadata = (query: AzureMonitorQuery, datasource: Datasour
|
||||
label: v,
|
||||
value: v,
|
||||
}));
|
||||
|
||||
setMetricMetadata({
|
||||
aggOptions: aggregations,
|
||||
timeGrains: metadata.supportedTimeGrains,
|
||||
@ -255,6 +263,11 @@ export const useMetricMetadata = (query: AzureMonitorQuery, datasource: Datasour
|
||||
...query.azureMonitor,
|
||||
aggregation: newAggregation,
|
||||
timeGrain: newTimeGrain,
|
||||
allowedTimeGrainsMs: metricMetadata.timeGrains
|
||||
.filter((timeGrain) => timeGrain.value !== 'auto')
|
||||
.map((timeGrain) =>
|
||||
rangeUtil.intervalToMs(TimegrainConverter.createKbnUnitFromISO8601Duration(timeGrain.value))
|
||||
),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -3,9 +3,9 @@ import { renderHook } from '@testing-library/react-hooks';
|
||||
import createMockDatasource from '../../__mocks__/datasource';
|
||||
import Datasource from '../../datasource';
|
||||
import { AzureMetricQuery, AzureMonitorOption, AzureMonitorQuery, AzureQueryType } from '../../types';
|
||||
import { DataHook } from '../MetricsQueryEditor/dataHooks';
|
||||
import { DataHook, MetricMetadata, MetricsMetadataHook } from '../MetricsQueryEditor/dataHooks';
|
||||
|
||||
import { useMetricNames, useMetricNamespaces } from './dataHooks';
|
||||
import { useMetricNames, useMetricNamespaces, useMetricMetadata } from './dataHooks';
|
||||
|
||||
const WAIT_OPTIONS = {
|
||||
timeout: 1000,
|
||||
@ -15,7 +15,7 @@ const opt = (text: string, value: string) => ({ text, value });
|
||||
|
||||
interface TestScenario {
|
||||
name: string;
|
||||
hook: DataHook;
|
||||
hook: DataHook | MetricsMetadataHook;
|
||||
|
||||
// For convenience, only need to define the azureMonitor part of the query for some tests
|
||||
emptyQueryPartial: AzureMetricQuery;
|
||||
@ -23,7 +23,7 @@ interface TestScenario {
|
||||
topLevelCustomProperties?: Partial<AzureMonitorQuery>;
|
||||
|
||||
expectedCustomPropertyResults?: Array<AzureMonitorOption<string>>;
|
||||
expectedOptions: AzureMonitorOption[];
|
||||
expectedOptions: AzureMonitorOption[] | MetricMetadata;
|
||||
}
|
||||
|
||||
describe('AzureMonitor: metrics dataHooks', () => {
|
||||
@ -64,7 +64,6 @@ describe('AzureMonitor: metrics dataHooks', () => {
|
||||
{ label: 'metric-$ENVIRONMENT', value: 'metric-$ENVIRONMENT' },
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
name: 'useMetricNamespaces',
|
||||
hook: useMetricNamespaces,
|
||||
@ -138,7 +137,25 @@ describe('AzureMonitor: metrics dataHooks', () => {
|
||||
datasource.azureMonitorDatasource.getMetricNamespaces = jest
|
||||
.fn()
|
||||
.mockResolvedValue([opt('Compute Virtual Machine', 'azure/vmc'), opt('Database NS', 'azure/dbns')]);
|
||||
|
||||
datasource.azureMonitorDatasource.getMetricMetadata = jest.fn().mockResolvedValue({
|
||||
primaryAggType: 'Average',
|
||||
supportedAggTypes: ['Average'],
|
||||
supportedTimeGrains: [
|
||||
{ label: 'Auto', value: 'auto' },
|
||||
{ label: '1 minute', value: 'PT1M' },
|
||||
{ label: '5 minutes', value: 'PT5M' },
|
||||
{ label: '15 minutes', value: 'PT15M' },
|
||||
{ label: '30 minutes', value: 'PT30M' },
|
||||
{ label: '1 hour', value: 'PT1H' },
|
||||
{ label: '6 hours', value: 'PT6H' },
|
||||
{ label: '12 hours', value: 'PT12H' },
|
||||
{ label: '1 day', value: 'P1D' },
|
||||
],
|
||||
dimensions: [],
|
||||
});
|
||||
});
|
||||
|
||||
describe.each(testTable)('scenario %#: $name', (scenario) => {
|
||||
it('returns values', async () => {
|
||||
const query = {
|
||||
@ -163,4 +180,56 @@ describe('AzureMonitor: metrics dataHooks', () => {
|
||||
expect(result.current).toEqual(scenario.expectedCustomPropertyResults);
|
||||
});
|
||||
});
|
||||
|
||||
describe('useMetricsMetadataHook', () => {
|
||||
const metricsMetadataConfig = {
|
||||
name: 'useMetricMetadata',
|
||||
hook: useMetricMetadata,
|
||||
emptyQueryPartial: {
|
||||
resourceUri:
|
||||
'/subscriptions/99999999-cccc-bbbb-aaaa-9106972f9572/resourceGroups/grafanastaging/providers/Microsoft.Compute/virtualMachines/grafana',
|
||||
metricNamespace: 'azure/vm',
|
||||
metricName: 'Average CPU',
|
||||
},
|
||||
customProperties: {},
|
||||
expectedOptions: {
|
||||
aggOptions: [{ label: 'Average', value: 'Average' }],
|
||||
timeGrains: [
|
||||
{ label: 'Auto', value: 'auto' },
|
||||
{ label: '1 minute', value: 'PT1M' },
|
||||
{ label: '5 minutes', value: 'PT5M' },
|
||||
{ label: '15 minutes', value: 'PT15M' },
|
||||
{ label: '30 minutes', value: 'PT30M' },
|
||||
{ label: '1 hour', value: 'PT1H' },
|
||||
{ label: '6 hours', value: 'PT6H' },
|
||||
{ label: '12 hours', value: 'PT12H' },
|
||||
{ label: '1 day', value: 'P1D' },
|
||||
],
|
||||
dimensions: [],
|
||||
isLoading: false,
|
||||
supportedAggTypes: ['Average'],
|
||||
primaryAggType: 'Average',
|
||||
},
|
||||
};
|
||||
|
||||
it('returns values', async () => {
|
||||
const query = {
|
||||
...bareQuery,
|
||||
azureMonitor: metricsMetadataConfig.emptyQueryPartial,
|
||||
};
|
||||
const { result, waitForNextUpdate } = renderHook(() => metricsMetadataConfig.hook(query, datasource, onChange));
|
||||
await waitForNextUpdate(WAIT_OPTIONS);
|
||||
|
||||
expect(result.current).toEqual(metricsMetadataConfig.expectedOptions);
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
...query,
|
||||
azureMonitor: {
|
||||
...query.azureMonitor,
|
||||
aggregation: result.current.primaryAggType,
|
||||
timeGrain: 'auto',
|
||||
allowedTimeGrainsMs: [60_000, 300_000, 900_000, 1_800_000, 3_600_000, 21_600_000, 43_200_000, 86_400_000],
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,6 +1,9 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { rangeUtil } from '@grafana/data';
|
||||
|
||||
import Datasource from '../../datasource';
|
||||
import TimegrainConverter from '../../time_grain_converter';
|
||||
import { AzureMonitorOption, AzureMonitorQuery } from '../../types';
|
||||
import { toOption } from '../../utils/common';
|
||||
import { useAsyncState } from '../../utils/useAsyncState';
|
||||
@ -118,6 +121,11 @@ export const useMetricMetadata = (query: AzureMonitorQuery, datasource: Datasour
|
||||
...query.azureMonitor,
|
||||
aggregation: newAggregation,
|
||||
timeGrain: newTimeGrain,
|
||||
allowedTimeGrainsMs: metricMetadata.timeGrains
|
||||
.filter((timeGrain) => timeGrain.value !== 'auto')
|
||||
.map((timeGrain) =>
|
||||
rangeUtil.intervalToMs(TimegrainConverter.createKbnUnitFromISO8601Duration(timeGrain.value))
|
||||
),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
@ -45,13 +45,11 @@ export interface AzureMetricQuery {
|
||||
dimensionFilters?: AzureMetricDimension[];
|
||||
alias?: string;
|
||||
top?: string;
|
||||
allowedTimeGrainsMs?: number[];
|
||||
|
||||
/** @deprecated */
|
||||
timeGrainUnit?: string;
|
||||
|
||||
/** @deprecated Remove this once angular is removed */
|
||||
allowedTimeGrainsMs?: number[];
|
||||
|
||||
/** @deprecated This property was migrated to dimensionFilters and should only be accessed in the migration */
|
||||
dimension?: string;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user