Skip to content

Commit

Permalink
[Uptime] Look for complete down check in the monitor status alert rule (
Browse files Browse the repository at this point in the history
#118999)

Co-authored-by: Kibana Machine <[email protected]>
  • Loading branch information
shahzad31 and kibanamachine authored Nov 23, 2021
1 parent bab02f9 commit a5d692d
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,11 @@ describe('monitor availability', () => {
"query": Object {
"bool": Object {
"filter": Array [
Object {
"exists": Object {
"field": "summary",
},
},
Object {
"range": Object {
"@timestamp": Object {
Expand Down Expand Up @@ -374,6 +379,11 @@ describe('monitor availability', () => {
"query": Object {
"bool": Object {
"filter": Array [
Object {
"exists": Object {
"field": "summary",
},
},
Object {
"range": Object {
"@timestamp": Object {
Expand Down Expand Up @@ -688,6 +698,11 @@ describe('monitor availability', () => {
"query": Object {
"bool": Object {
"filter": Array [
Object {
"exists": Object {
"field": "summary",
},
},
Object {
"range": Object {
"@timestamp": Object {
Expand Down Expand Up @@ -786,6 +801,11 @@ describe('monitor availability', () => {
"query": Object {
"bool": Object {
"filter": Array [
Object {
"exists": Object {
"field": "summary",
},
},
Object {
"range": Object {
"@timestamp": Object {
Expand Down Expand Up @@ -905,6 +925,11 @@ describe('monitor availability', () => {
"query": Object {
"bool": Object {
"filter": Array [
Object {
"exists": Object {
"field": "summary",
},
},
Object {
"range": Object {
"@timestamp": Object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { UMElasticsearchQueryFn } from '../adapters';
import { GetMonitorAvailabilityParams, Ping } from '../../../common/runtime_types';
import { asMutableArray } from '../../../common/utils/as_mutable_array';
import { AfterKey } from './get_monitor_status';
import { UNNAMED_LOCATION } from '../../../common/constants';

export interface AvailabilityKey {
monitorId: string;
Expand All @@ -28,6 +29,7 @@ export const formatBuckets = async (buckets: any[]): Promise<GetMonitorAvailabil
// eslint-disable-next-line @typescript-eslint/naming-convention
buckets.map(({ key, fields, up_sum, down_sum, ratio }: any) => ({
...key,
location: key.location === null ? UNNAMED_LOCATION : (key.location as string),
monitorInfo: fields?.hits?.hits?.[0]?._source,
up: up_sum.value,
down: down_sum.value,
Expand Down Expand Up @@ -60,6 +62,11 @@ export const getMonitorAvailability: UMElasticsearchQueryFn<
query: {
bool: {
filter: [
{
exists: {
field: 'summary',
},
},
{
range: {
'@timestamp': {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,11 @@ describe('getMonitorStatus', () => {
"fields": Object {
"top_hits": Object {
"size": 1,
"sort": Array [
Object {
"@timestamp": "desc",
},
],
},
},
},
Expand Down Expand Up @@ -141,8 +146,15 @@ describe('getMonitorStatus', () => {
"bool": Object {
"filter": Array [
Object {
"term": Object {
"monitor.status": "down",
"exists": Object {
"field": "summary",
},
},
Object {
"range": Object {
"summary.down": Object {
"gt": "0",
},
},
},
Object {
Expand Down Expand Up @@ -234,6 +246,11 @@ describe('getMonitorStatus', () => {
"fields": Object {
"top_hits": Object {
"size": 1,
"sort": Array [
Object {
"@timestamp": "desc",
},
],
},
},
},
Expand Down Expand Up @@ -270,8 +287,15 @@ describe('getMonitorStatus', () => {
"bool": Object {
"filter": Array [
Object {
"term": Object {
"monitor.status": "down",
"exists": Object {
"field": "summary",
},
},
Object {
"range": Object {
"summary.down": Object {
"gt": "0",
},
},
},
Object {
Expand Down Expand Up @@ -400,6 +424,11 @@ describe('getMonitorStatus', () => {
"fields": Object {
"top_hits": Object {
"size": 1,
"sort": Array [
Object {
"@timestamp": "desc",
},
],
},
},
},
Expand Down Expand Up @@ -436,8 +465,15 @@ describe('getMonitorStatus', () => {
"bool": Object {
"filter": Array [
Object {
"term": Object {
"monitor.status": "down",
"exists": Object {
"field": "summary",
},
},
Object {
"range": Object {
"summary.down": Object {
"gt": "0",
},
},
},
Object {
Expand Down Expand Up @@ -559,6 +595,11 @@ describe('getMonitorStatus', () => {
"fields": Object {
"top_hits": Object {
"size": 1,
"sort": Array [
Object {
"@timestamp": "desc",
},
],
},
},
},
Expand Down Expand Up @@ -595,8 +636,15 @@ describe('getMonitorStatus', () => {
"bool": Object {
"filter": Array [
Object {
"term": Object {
"monitor.status": "down",
"exists": Object {
"field": "summary",
},
},
Object {
"range": Object {
"summary.down": Object {
"gt": "0",
},
},
},
Object {
Expand Down Expand Up @@ -693,6 +741,11 @@ describe('getMonitorStatus', () => {
"fields": Object {
"top_hits": Object {
"size": 1,
"sort": Array [
Object {
"@timestamp": "desc",
},
],
},
},
},
Expand Down Expand Up @@ -729,8 +782,15 @@ describe('getMonitorStatus', () => {
"bool": Object {
"filter": Array [
Object {
"term": Object {
"monitor.status": "down",
"exists": Object {
"field": "summary",
},
},
Object {
"range": Object {
"summary.down": Object {
"gt": "0",
},
},
},
Object {
Expand Down
103 changes: 75 additions & 28 deletions x-pack/plugins/uptime/server/lib/requests/get_monitor_status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,13 @@

import { JsonObject } from '@kbn/utility-types';
import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { PromiseType } from 'utility-types';
import { asMutableArray } from '../../../common/utils/as_mutable_array';
import { UMElasticsearchQueryFn } from '../adapters';
import { Ping } from '../../../common/runtime_types/ping';
import { createEsQuery } from '../../../common/utils/es_search';
import { UptimeESClient } from '../lib';
import { UNNAMED_LOCATION } from '../../../common/constants';

export interface GetMonitorStatusParams {
filters?: JsonObject;
Expand Down Expand Up @@ -41,24 +45,36 @@ const getLocationClause = (locations: string[]) => ({

export type AfterKey = Record<string, string | number | null> | undefined;

export const getMonitorStatus: UMElasticsearchQueryFn<
GetMonitorStatusParams,
GetMonitorStatusResult[]
> = async ({ uptimeEsClient, filters, locations, numTimes, timespanRange, timestampRange }) => {
let afterKey: AfterKey;

const STATUS = 'down';
let monitors: any = [];
do {
// today this value is hardcoded. In the future we may support
// multiple status types for this alert, and this will become a parameter
const esParams = {
const executeQueryParams = async ({
timestampRange,
timespanRange,
filters,
afterKey,
uptimeEsClient,
locations,
}: {
timespanRange: GetMonitorStatusParams['timespanRange'];
timestampRange: GetMonitorStatusParams['timestampRange'];
filters: GetMonitorStatusParams['filters'];
afterKey?: AfterKey;
uptimeEsClient: UptimeESClient;
locations: string[];
}) => {
const queryParams = createEsQuery({
body: {
query: {
bool: {
filter: [
{
term: {
'monitor.status': STATUS,
exists: {
field: 'summary',
},
},
{
range: {
'summary.down': {
gt: '0',
},
},
},
{
Expand Down Expand Up @@ -121,34 +137,65 @@ export const getMonitorStatus: UMElasticsearchQueryFn<
fields: {
top_hits: {
size: 1,
sort: [{ '@timestamp': 'desc' }],
},
},
},
},
},
};
},
});

/**
* Perform a logical `and` against the selected location filters.
*/
if (locations.length) {
queryParams.body.query.bool.filter.push(getLocationClause(locations));
}

/**
* Perform a logical `and` against the selected location filters.
*/
if (locations.length) {
esParams.query.bool.filter.push(getLocationClause(locations));
}
const { body: result } = await uptimeEsClient.search<Ping, typeof queryParams>(queryParams);
const afterKeyRes = result?.aggregations?.monitors?.after_key;

const monitors = result?.aggregations?.monitors?.buckets || [];

return { afterKeyRes, monitors };
};

type QueryResponse = PromiseType<ReturnType<typeof executeQueryParams>>;

export const getMonitorStatus: UMElasticsearchQueryFn<
GetMonitorStatusParams,
GetMonitorStatusResult[]
> = async ({ uptimeEsClient, filters, locations, numTimes, timespanRange, timestampRange }) => {
let afterKey: QueryResponse['afterKeyRes'];

let monitors: QueryResponse['monitors'] = [];

do {
// today this value is hardcoded. In the future we may support
// multiple status types for this alert, and this will become a parameter

const { body: result } = await uptimeEsClient.search({
body: esParams,
const { afterKeyRes, monitors: monitorRes } = await executeQueryParams({
afterKey,
timespanRange,
timestampRange,
filters,
uptimeEsClient,
locations,
});

afterKey = result?.aggregations?.monitors?.after_key as AfterKey;
afterKey = afterKeyRes;

monitors = monitors.concat(result?.aggregations?.monitors?.buckets || []);
monitors = monitors.concat(monitorRes);
} while (afterKey !== undefined);

return monitors
.filter((monitor: any) => monitor?.doc_count >= numTimes)
.map(({ key, doc_count: count, fields }: any) => ({
...key,
.filter((monitor) => monitor?.doc_count >= numTimes)
.map(({ key, doc_count: count, fields }) => ({
count,
monitorId: key.monitorId as string,
status: key.status as string,
location: key.location === null ? UNNAMED_LOCATION : (key.location as string),
monitorInfo: fields?.hits?.hits?.[0]?._source,
}));
};

0 comments on commit a5d692d

Please sign in to comment.