CloudWatch: filter alert queries (#47222)

This commit is contained in:
Isabella Siu 2022-04-04 12:06:31 -04:00 committed by GitHub
parent 1c34cc8b91
commit b1c68b5a12
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 129 additions and 120 deletions

View File

@ -10,8 +10,13 @@ import {
namespaceVariable,
setupMockedDataSource,
} from './__mocks__/CloudWatchDataSource';
import { CloudWatchDatasource } from './datasource';
import { CloudWatchLogsQueryStatus, CloudWatchMetricsQuery, MetricEditorMode, MetricQueryType } from './types';
import {
CloudWatchLogsQuery,
CloudWatchLogsQueryStatus,
CloudWatchMetricsQuery,
MetricEditorMode,
MetricQueryType,
} from './types';
describe('datasource', () => {
describe('query', () => {
@ -144,12 +149,26 @@ describe('datasource', () => {
});
});
describe('filterMetricQuery', () => {
describe('filterQuery', () => {
const datasource = setupMockedDataSource().datasource;
describe('CloudWatchLogsQuery', () => {
const baseQuery: CloudWatchLogsQuery = {
queryMode: 'Logs',
id: '',
region: '',
refId: '',
logGroupNames: ['foo', 'bar'],
};
it('should return false if empty logGroupNames', () => {
expect(datasource.filterQuery({ ...baseQuery, logGroupNames: undefined })).toBeFalsy();
});
it('should return true if has logGroupNames', () => {
expect(datasource.filterQuery(baseQuery)).toBeTruthy();
});
});
describe('CloudWatchMetricsQuery', () => {
let baseQuery: CloudWatchMetricsQuery;
let datasource: CloudWatchDatasource;
beforeEach(() => {
datasource = setupMockedDataSource().datasource;
baseQuery = {
id: '',
region: 'us-east-2',
@ -166,12 +185,11 @@ describe('datasource', () => {
});
it('should error if invalid mode', async () => {
expect(() => datasource.filterMetricQuery(baseQuery)).toThrowError('invalid metric editor mode');
expect(() => datasource.filterQuery(baseQuery)).toThrowError('invalid metric editor mode');
});
describe('metric search queries', () => {
beforeEach(() => {
datasource = setupMockedDataSource().datasource;
baseQuery = {
...baseQuery,
namespace: 'AWS/EC2',
@ -183,31 +201,30 @@ describe('datasource', () => {
});
it('should not allow builder queries that dont have namespace, metric or statistic', async () => {
expect(datasource.filterMetricQuery({ ...baseQuery, statistic: undefined })).toBeFalsy();
expect(datasource.filterMetricQuery({ ...baseQuery, metricName: undefined })).toBeFalsy();
expect(datasource.filterMetricQuery({ ...baseQuery, namespace: '' })).toBeFalsy();
expect(datasource.filterQuery({ ...baseQuery, statistic: undefined })).toBeFalsy();
expect(datasource.filterQuery({ ...baseQuery, metricName: undefined })).toBeFalsy();
expect(datasource.filterQuery({ ...baseQuery, namespace: '' })).toBeFalsy();
});
it('should allow builder queries that have namespace, metric or statistic', async () => {
expect(datasource.filterMetricQuery(baseQuery)).toBeTruthy();
expect(datasource.filterQuery(baseQuery)).toBeTruthy();
});
it('should not allow code queries that dont have an expression', async () => {
expect(
datasource.filterMetricQuery({ ...baseQuery, expression: undefined, metricEditorMode: MetricEditorMode.Code })
datasource.filterQuery({ ...baseQuery, expression: undefined, metricEditorMode: MetricEditorMode.Code })
).toBeFalsy();
});
it('should allow code queries that have an expression', async () => {
expect(
datasource.filterMetricQuery({ ...baseQuery, expression: 'x * 2', metricEditorMode: MetricEditorMode.Code })
datasource.filterQuery({ ...baseQuery, expression: 'x * 2', metricEditorMode: MetricEditorMode.Code })
).toBeTruthy();
});
});
describe('metric search expression queries', () => {
beforeEach(() => {
datasource = setupMockedDataSource().datasource;
baseQuery = {
...baseQuery,
metricQueryType: MetricQueryType.Search,
@ -215,21 +232,20 @@ describe('datasource', () => {
};
});
it('should not allow queries that dont have an expresssion', async () => {
const valid = datasource.filterMetricQuery(baseQuery);
it('should not allow queries that dont have an expression', async () => {
const valid = datasource.filterQuery(baseQuery);
expect(valid).toBeFalsy();
});
it('should allow queries that have an expresssion', async () => {
it('should allow queries that have an expression', async () => {
baseQuery.expression = 'SUM([a,x])';
const valid = datasource.filterMetricQuery(baseQuery);
const valid = datasource.filterQuery(baseQuery);
expect(valid).toBeTruthy();
});
});
describe('metric query queries', () => {
beforeEach(() => {
datasource = setupMockedDataSource().datasource;
baseQuery = {
...baseQuery,
metricQueryType: MetricQueryType.Query,
@ -238,17 +254,19 @@ describe('datasource', () => {
});
it('should not allow queries that dont have a sql expresssion', async () => {
const valid = datasource.filterMetricQuery(baseQuery);
const valid = datasource.filterQuery(baseQuery);
expect(valid).toBeFalsy();
});
it('should allow queries that have a sql expresssion', async () => {
baseQuery.sqlExpression = 'select SUM(CPUUtilization) from "AWS/EC2"';
const valid = datasource.filterMetricQuery(baseQuery);
const valid = datasource.filterQuery(baseQuery);
expect(valid).toBeTruthy();
});
});
});
});
describe('resource requests', () => {
it('should map resource response to metric response', async () => {
const datasource = setupMockedDataSource().datasource;

View File

@ -234,22 +234,15 @@ export class CloudWatchDatasource
);
};
filterMetricQuery({
region,
metricQueryType,
metricEditorMode,
expression,
metricName,
namespace,
sqlExpression,
statistic,
dimensions,
...rest
}: CloudWatchMetricsQuery): boolean {
filterQuery(query: CloudWatchQuery): boolean {
if (query.queryMode === 'Logs') {
return !!query.logGroupNames?.length;
}
const { region, metricQueryType, metricEditorMode, expression, metricName, namespace, sqlExpression, statistic } =
query;
if (!region) {
return false;
}
if (metricQueryType === MetricQueryType.Search && metricEditorMode === MetricEditorMode.Builder) {
return !!namespace && !!metricName && !!statistic;
} else if (metricQueryType === MetricQueryType.Search && metricEditorMode === MetricEditorMode.Code) {
@ -266,9 +259,7 @@ export class CloudWatchDatasource
metricQueries: CloudWatchMetricsQuery[],
options: DataQueryRequest<CloudWatchQuery>
): Observable<DataQueryResponse> => {
const validMetricsQueries = metricQueries
.filter(this.filterMetricQuery)
.map((item: CloudWatchMetricsQuery): MetricQuery => {
const validMetricsQueries = metricQueries.map((item: CloudWatchMetricsQuery): MetricQuery => {
item.region = this.templateSrv.replace(this.getActualRegion(item.region), options.scopedVars);
item.namespace = this.replace(item.namespace, options.scopedVars, true, 'namespace');
item.metricName = this.replace(item.metricName, options.scopedVars, true, 'metric name');