[Uptime] Fix filters in query for fetching monitor attached rules (#115921)

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Shahzad 2021-10-29 19:50:47 +02:00 committed by GitHub
parent d4d470d938
commit 45476dcbe6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 369 additions and 30 deletions

View file

@ -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-*",
},
]
`;

View file

@ -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: [],
},
],
};

View file

@ -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<GetMonitorDetailsParams,
],
};
const { body: result } = await uptimeEsClient.search({ body: params });
const { body: result } = await uptimeEsClient.search({ body: params }, 'getMonitorDetails');
const data = result.hits.hits[0]?._source as Ping & { '@timestamp': string };

View file

@ -91,8 +91,7 @@ export function mockSearchResult(
): UptimeESClient {
const { esClient: mockEsClient, uptimeEsClient } = getUptimeESMockClient();
// @ts-expect-error incomplete search response
mockEsClient.search.mockResolvedValue({
mockEsClient.search = jest.fn().mockResolvedValue({
body: {
took: 18,
timed_out: false,
@ -113,5 +112,6 @@ export function mockSearchResult(
aggregations,
},
});
return uptimeEsClient;
}