From 45476dcbe60e4e969e9e7d0c1741f8226df97654 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Fri, 29 Oct 2021 19:50:47 +0200 Subject: [PATCH] [Uptime] Fix filters in query for fetching monitor attached rules (#115921) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../get_monitor_details.test.ts.snap | 109 +++++++++ .../lib/requests/get_monitor_details.test.ts | 219 ++++++++++++++++++ .../lib/requests/get_monitor_details.ts | 67 +++--- .../uptime/server/lib/requests/helper.ts | 4 +- 4 files changed, 369 insertions(+), 30 deletions(-) create mode 100644 x-pack/plugins/uptime/server/lib/requests/__snapshots__/get_monitor_details.test.ts.snap create mode 100644 x-pack/plugins/uptime/server/lib/requests/get_monitor_details.test.ts diff --git a/x-pack/plugins/uptime/server/lib/requests/__snapshots__/get_monitor_details.test.ts.snap b/x-pack/plugins/uptime/server/lib/requests/__snapshots__/get_monitor_details.test.ts.snap new file mode 100644 index 000000000000..56b7ed25a74a --- /dev/null +++ b/x-pack/plugins/uptime/server/lib/requests/__snapshots__/get_monitor_details.test.ts.snap @@ -0,0 +1,109 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`getMonitorDetails getMonitorAlerts should use expected filters for the query 1`] = ` +Array [ + Object { + "body": Object { + "aggs": Object { + "monitors": Object { + "terms": Object { + "field": "monitor.id", + "size": 1000, + }, + }, + }, + "query": Object { + "bool": Object { + "filter": Array [ + Object { + "term": Object { + "monitor.id": "fooID", + }, + }, + Object { + "bool": Object { + "filter": Array [ + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match": Object { + "monitor.type": "http", + }, + }, + ], + }, + }, + Object { + "bool": Object { + "minimum_should_match": 1, + "should": Array [ + Object { + "match_phrase": Object { + "url.domain": "www.cnn.com", + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + }, + "size": 0, + }, + "index": "heartbeat-8*,synthetics-*", + }, +] +`; + +exports[`getMonitorDetails getMonitorDetails will provide expected calls 1`] = ` +Array [ + Object { + "body": Object { + "_source": Array [ + "error", + "@timestamp", + ], + "query": Object { + "bool": Object { + "filter": Array [ + Object { + "range": Object { + "@timestamp": Object { + "gte": "now-15m", + "lte": "now", + }, + }, + }, + Object { + "term": Object { + "monitor.id": "fooID", + }, + }, + ], + "must": Array [ + Object { + "exists": Object { + "field": "error", + }, + }, + ], + }, + }, + "size": 1, + "sort": Array [ + Object { + "@timestamp": Object { + "order": "desc", + }, + }, + ], + }, + "index": "heartbeat-8*,synthetics-*", + }, +] +`; diff --git a/x-pack/plugins/uptime/server/lib/requests/get_monitor_details.test.ts b/x-pack/plugins/uptime/server/lib/requests/get_monitor_details.test.ts new file mode 100644 index 000000000000..68560faf4f7f --- /dev/null +++ b/x-pack/plugins/uptime/server/lib/requests/get_monitor_details.test.ts @@ -0,0 +1,219 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { mockSearchResult } from './helper'; +import { getMonitorAlerts, getMonitorDetails } from './get_monitor_details'; +import * as statusCheck from '../alerts/status_check'; + +describe('getMonitorDetails', () => { + it('getMonitorDetails will provide expected calls', async () => { + expect.assertions(2); + + const uptimeEsClient = mockSearchResult([{ _source: { id: 1 } }]); + + await getMonitorDetails({ + uptimeEsClient, + monitorId: 'fooID', + dateStart: 'now-15m', + dateEnd: 'now', + rulesClient: { find: jest.fn().mockReturnValue({ data: [] }) }, + }); + expect(uptimeEsClient.baseESClient.search).toHaveBeenCalledTimes(1); + + expect((uptimeEsClient.baseESClient.search as jest.Mock).mock.calls[0]).toMatchSnapshot(); + }); + + describe('getMonitorAlerts', () => { + it('should use expected filters for the query', async function () { + const uptimeEsClient = mockSearchResult([{ _source: { id: 1 } }]); + + jest.spyOn(statusCheck, 'formatFilterString').mockImplementation(async () => ({ + bool: { + filter: [ + { + bool: { should: [{ match: { 'monitor.type': 'http' } }], minimum_should_match: 1 }, + }, + { + bool: { + should: [{ match_phrase: { 'url.domain': 'www.cnn.com' } }], + minimum_should_match: 1, + }, + }, + ], + }, + })); + + await getMonitorAlerts({ + uptimeEsClient, + monitorId: 'fooID', + rulesClient: { + find: jest.fn().mockReturnValue({ data: dummyAlertRules.data }), + }, + }); + expect(uptimeEsClient.baseESClient.search).toHaveBeenCalledTimes(3); + + const esParams = (uptimeEsClient.baseESClient.search as jest.Mock).mock.calls[0]; + + expect(esParams[0].body.query).toEqual({ + bool: { + filter: [ + { + term: { + 'monitor.id': 'fooID', + }, + }, + { + bool: { + filter: [ + { + bool: { + minimum_should_match: 1, + should: [ + { + match: { + 'monitor.type': 'http', + }, + }, + ], + }, + }, + { + bool: { + minimum_should_match: 1, + should: [ + { + match_phrase: { + 'url.domain': 'www.cnn.com', + }, + }, + ], + }, + }, + ], + }, + }, + ], + }, + }); + + expect(esParams).toMatchSnapshot(); + }); + }); +}); + +const dummyAlertRules = { + page: 1, + total: 3, + per_page: 10, + data: [ + { + id: '9e0cad00-31e7-11ec-b2d2-abfef52bb74d', + consumer: 'uptime', + tags: [], + name: 'browser alerrt', + enabled: true, + throttle: null, + schedule: { interval: '1m' }, + params: { + search: '', + numTimes: 5, + timerangeUnit: 'm', + timerangeCount: 15, + shouldCheckStatus: true, + shouldCheckAvailability: true, + availability: { range: 30, rangeUnit: 'd', threshold: '99' }, + filters: { tags: [], 'url.port': [], 'observer.geo.name': [], 'monitor.type': ['browser'] }, + }, + rule_type_id: 'xpack.uptime.alerts.monitorStatus', + created_by: null, + updated_by: null, + created_at: '2021-10-20T20:52:20.050Z', + updated_at: '2021-10-20T20:52:20.050Z', + api_key_owner: null, + notify_when: 'onActionGroupChange', + mute_all: false, + muted_alert_ids: [], + scheduled_task_id: '9e91bb80-31e7-11ec-b2d2-abfef52bb74d', + execution_status: { + status: 'active', + last_execution_date: '2021-10-21T09:33:22.044Z', + last_duration: 414, + }, + actions: [], + }, + { + id: 'deb541f0-31e7-11ec-b2d2-abfef52bb74d', + consumer: 'alerts', + tags: [], + name: 'http alert', + enabled: true, + throttle: null, + schedule: { interval: '1m' }, + params: { + search: '', + numTimes: 5, + timerangeUnit: 'm', + timerangeCount: 15, + shouldCheckStatus: true, + shouldCheckAvailability: true, + availability: { range: 30, rangeUnit: 'd', threshold: '99' }, + filters: { tags: [], 'url.port': [], 'observer.geo.name': [], 'monitor.type': ['http'] }, + }, + rule_type_id: 'xpack.uptime.alerts.monitorStatus', + created_by: null, + updated_by: null, + created_at: '2021-10-20T20:54:08.529Z', + updated_at: '2021-10-20T20:54:08.529Z', + api_key_owner: null, + notify_when: 'onActionGroupChange', + mute_all: false, + muted_alert_ids: [], + scheduled_task_id: 'df3e2100-31e7-11ec-b2d2-abfef52bb74d', + execution_status: { + status: 'ok', + last_execution_date: '2021-10-21T09:33:22.044Z', + last_duration: 92, + }, + actions: [], + }, + { + id: '5bd4f720-31e8-11ec-b2d2-abfef52bb74d', + consumer: 'uptime', + tags: [], + name: 'http rule', + enabled: true, + throttle: null, + schedule: { interval: '1m' }, + params: { + search: 'url.domain : "www.cnn.com" ', + numTimes: 5, + timerangeUnit: 'm', + timerangeCount: 15, + shouldCheckStatus: true, + shouldCheckAvailability: true, + availability: { range: 30, rangeUnit: 'd', threshold: '99' }, + filters: { tags: [], 'url.port': [], 'observer.geo.name': [], 'monitor.type': ['http'] }, + }, + rule_type_id: 'xpack.uptime.alerts.monitorStatus', + created_by: null, + updated_by: null, + created_at: '2021-10-20T20:57:38.451Z', + updated_at: '2021-10-20T20:57:38.451Z', + api_key_owner: null, + notify_when: 'onActionGroupChange', + mute_all: false, + muted_alert_ids: [], + scheduled_task_id: '5bf417e0-31e8-11ec-b2d2-abfef52bb74d', + execution_status: { + status: 'ok', + last_execution_date: '2021-10-21T09:33:22.043Z', + last_duration: 87, + }, + actions: [], + }, + ], +}; diff --git a/x-pack/plugins/uptime/server/lib/requests/get_monitor_details.ts b/x-pack/plugins/uptime/server/lib/requests/get_monitor_details.ts index b5994d7e5b1c..9f77b0833d8b 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_monitor_details.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_monitor_details.ts @@ -5,10 +5,12 @@ * 2.0. */ +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { UMElasticsearchQueryFn } from '../adapters'; import { MonitorDetails, Ping } from '../../../common/runtime_types'; import { formatFilterString } from '../alerts/status_check'; import { UptimeESClient } from '../lib'; +import { createEsQuery } from '../../../common/utils/es_search'; export interface GetMonitorDetailsParams { monitorId: string; @@ -17,7 +19,7 @@ export interface GetMonitorDetailsParams { rulesClient: any; } -const getMonitorAlerts = async ({ +export const getMonitorAlerts = async ({ uptimeEsClient, rulesClient, monitorId, @@ -43,39 +45,48 @@ const getMonitorAlerts = async ({ monitorAlerts.push(currAlert); continue; } - const esParams = { - query: { - bool: { - filter: [ - { - term: { - 'monitor.id': monitorId, - }, - }, - ], - }, - }, - size: 0, - aggs: { - monitors: { - terms: { - field: 'monitor.id', - size: 1000, - }, - }, - }, - }; - const parsedFilters = await formatFilterString( + const parsedFilters: QueryDslQueryContainer | undefined = await formatFilterString( uptimeEsClient, currAlert.params.filters, currAlert.params.search ); - esParams.query.bool = Object.assign({}, esParams.query.bool, parsedFilters?.bool); - const { body: result } = await uptimeEsClient.search({ body: esParams }); + const esParams = createEsQuery({ + body: { + query: { + bool: { + filter: [ + { + term: { + 'monitor.id': monitorId, + }, + }, + ] as QueryDslQueryContainer[], + }, + }, + size: 0, + aggs: { + monitors: { + terms: { + field: 'monitor.id', + size: 1000, + }, + }, + }, + }, + }); - if (result.hits.total.value > 0) { + if (parsedFilters) { + esParams.body.query.bool.filter.push(parsedFilters); + } + + const { body: result } = await uptimeEsClient.search( + esParams, + `getMonitorsForAlert-${currAlert.name}` + ); + + if (result?.hits.total.value > 0) { monitorAlerts.push(currAlert); } } @@ -124,7 +135,7 @@ export const getMonitorDetails: UMElasticsearchQueryFn