diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/metric_query.test.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/metric_query.test.ts new file mode 100644 index 000000000000..3ad1031f574e --- /dev/null +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/metric_query.test.ts @@ -0,0 +1,59 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { MetricExpressionParams } from '../types'; +import { getElasticsearchMetricQuery } from './metric_query'; + +describe("The Metric Threshold Alert's getElasticsearchMetricQuery", () => { + const expressionParams = { + metric: 'system.is.a.good.puppy.dog', + aggType: 'avg', + timeUnit: 'm', + timeSize: 1, + } as MetricExpressionParams; + + const timefield = '@timestamp'; + const groupBy = 'host.doggoname'; + + describe('when passed no filterQuery', () => { + const searchBody = getElasticsearchMetricQuery(expressionParams, timefield, groupBy); + test('includes a range filter', () => { + expect( + searchBody.query.bool.filter.find((filter) => filter.hasOwnProperty('range')) + ).toBeTruthy(); + }); + + test('includes a metric field filter', () => { + expect(searchBody.query.bool.filter).toMatchObject( + expect.arrayContaining([{ exists: { field: 'system.is.a.good.puppy.dog' } }]) + ); + }); + }); + + describe('when passed a filterQuery', () => { + const filterQuery = + // This is adapted from a real-world query that previously broke alerts + // We want to make sure it doesn't override any existing filters + '{"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}}'; + + const searchBody = getElasticsearchMetricQuery( + expressionParams, + timefield, + groupBy, + filterQuery + ); + test('includes a range filter', () => { + expect( + searchBody.query.bool.filter.find((filter) => filter.hasOwnProperty('range')) + ).toBeTruthy(); + }); + + test('includes a metric field filter', () => { + expect(searchBody.query.bool.filter).toMatchObject( + expect.arrayContaining([{ exists: { field: 'system.is.a.good.puppy.dog' } }]) + ); + }); + }); +}); diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/metric_query.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/metric_query.ts index 5680035d9d60..15506a30529c 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/metric_query.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/metric_query.ts @@ -11,11 +11,11 @@ import { createPercentileAggregation } from './create_percentile_aggregation'; const MINIMUM_BUCKETS = 5; -const getParsedFilterQuery: ( - filterQuery: string | undefined -) => Record | Array> = (filterQuery) => { - if (!filterQuery) return {}; - return JSON.parse(filterQuery).bool; +const getParsedFilterQuery: (filterQuery: string | undefined) => Record | null = ( + filterQuery +) => { + if (!filterQuery) return null; + return JSON.parse(filterQuery); }; export const getElasticsearchMetricQuery = ( @@ -129,9 +129,8 @@ export const getElasticsearchMetricQuery = ( filter: [ ...rangeFilters, ...metricFieldFilters, - ...(Array.isArray(parsedFilterQuery) ? parsedFilterQuery : []), + ...(parsedFilterQuery ? [parsedFilterQuery] : []), ], - ...(!Array.isArray(parsedFilterQuery) ? parsedFilterQuery : {}), }, }, size: 0,