Skip to content

Commit 11cfe80

Browse files
[Metrics UI] Fix a bug in Metric Threshold query filter construction (#70672)
Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
1 parent eb84503 commit 11cfe80

File tree

2 files changed

+65
-7
lines changed

2 files changed

+65
-7
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
import { MetricExpressionParams } from '../types';
7+
import { getElasticsearchMetricQuery } from './metric_query';
8+
9+
describe("The Metric Threshold Alert's getElasticsearchMetricQuery", () => {
10+
const expressionParams = {
11+
metric: 'system.is.a.good.puppy.dog',
12+
aggType: 'avg',
13+
timeUnit: 'm',
14+
timeSize: 1,
15+
} as MetricExpressionParams;
16+
17+
const timefield = '@timestamp';
18+
const groupBy = 'host.doggoname';
19+
20+
describe('when passed no filterQuery', () => {
21+
const searchBody = getElasticsearchMetricQuery(expressionParams, timefield, groupBy);
22+
test('includes a range filter', () => {
23+
expect(
24+
searchBody.query.bool.filter.find((filter) => filter.hasOwnProperty('range'))
25+
).toBeTruthy();
26+
});
27+
28+
test('includes a metric field filter', () => {
29+
expect(searchBody.query.bool.filter).toMatchObject(
30+
expect.arrayContaining([{ exists: { field: 'system.is.a.good.puppy.dog' } }])
31+
);
32+
});
33+
});
34+
35+
describe('when passed a filterQuery', () => {
36+
const filterQuery =
37+
// This is adapted from a real-world query that previously broke alerts
38+
// We want to make sure it doesn't override any existing filters
39+
'{"bool":{"filter":[{"bool":{"filter":[{"bool":{"must_not":[{"bool":{"should":[{"query_string":{"query":"bark*","fields":["host.name^1.0"],"type":"best_fields","default_operator":"or","max_determinized_states":10000,"enable_position_increments":true,"fuzziness":"AUTO","fuzzy_prefix_length":0,"fuzzy_max_expansions":50,"phrase_slop":0,"escape":false,"auto_generate_synonyms_phrase_query":true,"fuzzy_transpositions":true,"boost":1}}],"adjust_pure_negative":true,"minimum_should_match":"1","boost":1}}],"adjust_pure_negative":true,"boost":1}},{"bool":{"must_not":[{"bool":{"should":[{"query_string":{"query":"woof*","fields":["host.name^1.0"],"type":"best_fields","default_operator":"or","max_determinized_states":10000,"enable_position_increments":true,"fuzziness":"AUTO","fuzzy_prefix_length":0,"fuzzy_max_expansions":50,"phrase_slop":0,"escape":false,"auto_generate_synonyms_phrase_query":true,"fuzzy_transpositions":true,"boost":1}}],"adjust_pure_negative":true,"minimum_should_match":"1","boost":1}}],"adjust_pure_negative":true,"boost":1}}],"adjust_pure_negative":true,"boost":1}}],"adjust_pure_negative":true,"boost":1}}';
40+
41+
const searchBody = getElasticsearchMetricQuery(
42+
expressionParams,
43+
timefield,
44+
groupBy,
45+
filterQuery
46+
);
47+
test('includes a range filter', () => {
48+
expect(
49+
searchBody.query.bool.filter.find((filter) => filter.hasOwnProperty('range'))
50+
).toBeTruthy();
51+
});
52+
53+
test('includes a metric field filter', () => {
54+
expect(searchBody.query.bool.filter).toMatchObject(
55+
expect.arrayContaining([{ exists: { field: 'system.is.a.good.puppy.dog' } }])
56+
);
57+
});
58+
});
59+
});

x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/metric_query.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ import { createPercentileAggregation } from './create_percentile_aggregation';
1111

1212
const MINIMUM_BUCKETS = 5;
1313

14-
const getParsedFilterQuery: (
15-
filterQuery: string | undefined
16-
) => Record<string, any> | Array<Record<string, any>> = (filterQuery) => {
17-
if (!filterQuery) return {};
18-
return JSON.parse(filterQuery).bool;
14+
const getParsedFilterQuery: (filterQuery: string | undefined) => Record<string, any> | null = (
15+
filterQuery
16+
) => {
17+
if (!filterQuery) return null;
18+
return JSON.parse(filterQuery);
1919
};
2020

2121
export const getElasticsearchMetricQuery = (
@@ -129,9 +129,8 @@ export const getElasticsearchMetricQuery = (
129129
filter: [
130130
...rangeFilters,
131131
...metricFieldFilters,
132-
...(Array.isArray(parsedFilterQuery) ? parsedFilterQuery : []),
132+
...(parsedFilterQuery ? [parsedFilterQuery] : []),
133133
],
134-
...(!Array.isArray(parsedFilterQuery) ? parsedFilterQuery : {}),
135134
},
136135
},
137136
size: 0,

0 commit comments

Comments
 (0)