mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 18:51:07 -04:00
[ResponseOps][Alerting] Add summary alerts to alerting serverless tests (#164349)
Resolves https://github.com/elastic/kibana/issues/163947 ## Summary Adds AAD summary tests to the alerting serverless tests
This commit is contained in:
parent
5e5e4cfc0a
commit
aeb26bd19d
6 changed files with 587 additions and 46 deletions
|
@ -48,7 +48,6 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
},
|
||||
});
|
||||
ruleId = createdRule.id;
|
||||
expect(ruleId).not.to.be(undefined);
|
||||
objectRemover.add('default', ruleId, 'rule', 'alerting');
|
||||
|
||||
// get the first alert document written
|
||||
|
@ -176,7 +175,6 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
},
|
||||
});
|
||||
ruleId = createdRule.id;
|
||||
expect(ruleId).not.to.be(undefined);
|
||||
objectRemover.add('default', ruleId, 'rule', 'alerting');
|
||||
|
||||
// get the first alert document written
|
||||
|
|
|
@ -46,8 +46,9 @@ export async function createIndexConnector({
|
|||
refresh: true,
|
||||
},
|
||||
connector_type_id: '.index',
|
||||
});
|
||||
return body.id as string;
|
||||
})
|
||||
.expect(200);
|
||||
return body;
|
||||
}
|
||||
|
||||
export async function createSlackConnector({
|
||||
|
@ -68,8 +69,9 @@ export async function createSlackConnector({
|
|||
webhookUrl: 'http://test',
|
||||
},
|
||||
connector_type_id: '.slack',
|
||||
});
|
||||
return body.id as string;
|
||||
})
|
||||
.expect(200);
|
||||
return body;
|
||||
}
|
||||
|
||||
export async function createEsQueryRule({
|
||||
|
@ -111,7 +113,8 @@ export async function createEsQueryRule({
|
|||
rule_type_id: ruleTypeId,
|
||||
actions,
|
||||
...(notifyWhen ? { notify_when: notifyWhen, throttle: '5m' } : {}),
|
||||
});
|
||||
})
|
||||
.expect(200);
|
||||
return body;
|
||||
}
|
||||
|
||||
|
@ -125,7 +128,8 @@ export async function disableRule({
|
|||
const { body } = await supertest
|
||||
.post(`/api/alerting/rule/${ruleId}/_disable`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.set('x-elastic-internal-origin', 'foo');
|
||||
.set('x-elastic-internal-origin', 'foo')
|
||||
.expect(204);
|
||||
return body;
|
||||
}
|
||||
|
||||
|
@ -141,7 +145,8 @@ export async function updateEsQueryRule({
|
|||
const { body: r } = await supertest
|
||||
.get(`/api/alerting/rule/${ruleId}`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.set('x-elastic-internal-origin', 'foo');
|
||||
.set('x-elastic-internal-origin', 'foo')
|
||||
.expect(200);
|
||||
const body = await supertest
|
||||
.put(`/api/alerting/rule/${ruleId}`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
|
@ -162,7 +167,8 @@ export async function updateEsQueryRule({
|
|||
})),
|
||||
},
|
||||
...updates,
|
||||
});
|
||||
})
|
||||
.expect(200);
|
||||
return body;
|
||||
}
|
||||
|
||||
|
@ -176,7 +182,8 @@ export async function runRule({
|
|||
const response = await supertest
|
||||
.post(`/internal/alerting/rule/${ruleId}/_run_soon`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.set('x-elastic-internal-origin', 'foo');
|
||||
.set('x-elastic-internal-origin', 'foo')
|
||||
.expect(204);
|
||||
return response;
|
||||
}
|
||||
|
||||
|
@ -190,7 +197,8 @@ export async function muteRule({
|
|||
const { body } = await supertest
|
||||
.post(`/api/alerting/rule/${ruleId}/_mute_all`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.set('x-elastic-internal-origin', 'foo');
|
||||
.set('x-elastic-internal-origin', 'foo')
|
||||
.expect(204);
|
||||
return body;
|
||||
}
|
||||
|
||||
|
@ -204,7 +212,8 @@ export async function enableRule({
|
|||
const { body } = await supertest
|
||||
.post(`/api/alerting/rule/${ruleId}/_enable`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.set('x-elastic-internal-origin', 'foo');
|
||||
.set('x-elastic-internal-origin', 'foo')
|
||||
.expect(204);
|
||||
return body;
|
||||
}
|
||||
|
||||
|
@ -220,7 +229,8 @@ export async function muteAlert({
|
|||
const { body } = await supertest
|
||||
.post(`/api/alerting/rule/${ruleId}/alert/${alertId}/_mute`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.set('x-elastic-internal-origin', 'foo');
|
||||
.set('x-elastic-internal-origin', 'foo')
|
||||
.expect(204);
|
||||
return body;
|
||||
}
|
||||
|
||||
|
@ -234,6 +244,7 @@ export async function unmuteRule({
|
|||
const { body } = await supertest
|
||||
.post(`/api/alerting/rule/${ruleId}/_unmute_all`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.set('x-elastic-internal-origin', 'foo');
|
||||
.set('x-elastic-internal-origin', 'foo')
|
||||
.expect(204);
|
||||
return body;
|
||||
}
|
||||
|
|
|
@ -344,10 +344,7 @@ export async function waitForNumRuleRuns({
|
|||
for (let i = 0; i < numOfRuns; i++) {
|
||||
await pRetry(
|
||||
async () => {
|
||||
const resp = await runRule({ supertest, ruleId });
|
||||
if (resp.status !== 204) {
|
||||
throw new Error(`Expected ${resp.status} to equal 204`);
|
||||
}
|
||||
await runRule({ supertest, ruleId });
|
||||
await waitForExecutionEventLog({
|
||||
esClient,
|
||||
filter: testStart,
|
||||
|
|
|
@ -11,5 +11,6 @@ export default function ({ loadTestFile }: FtrProviderContext) {
|
|||
describe('Alerting APIs', function () {
|
||||
loadTestFile(require.resolve('./rules'));
|
||||
loadTestFile(require.resolve('./alert_documents'));
|
||||
loadTestFile(require.resolve('./summary_actions'));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -61,12 +61,12 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
it('should schedule task, run rule and schedule actions when appropriate', async () => {
|
||||
const testStart = new Date();
|
||||
|
||||
actionId = await createIndexConnector({
|
||||
const createdAction = await createIndexConnector({
|
||||
supertest,
|
||||
name: 'Index Connector: Alerting API test',
|
||||
indexName: ALERT_ACTION_INDEX,
|
||||
});
|
||||
expect(actionId).not.to.be(undefined);
|
||||
actionId = createdAction.id;
|
||||
|
||||
const createdRule = await createEsQueryRule({
|
||||
supertest,
|
||||
|
@ -111,7 +111,6 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
],
|
||||
});
|
||||
ruleId = createdRule.id;
|
||||
expect(ruleId).not.to.be(undefined);
|
||||
|
||||
// Wait for the action to index a document before disabling the alert and waiting for tasks to finish
|
||||
const resp = await waitForDocumentInIndex({
|
||||
|
@ -170,12 +169,12 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
it('should pass updated rule params to executor', async () => {
|
||||
const testStart = new Date();
|
||||
|
||||
actionId = await createIndexConnector({
|
||||
const createdAction = await createIndexConnector({
|
||||
supertest,
|
||||
name: 'Index Connector: Alerting API test',
|
||||
indexName: ALERT_ACTION_INDEX,
|
||||
});
|
||||
expect(actionId).not.to.be(undefined);
|
||||
actionId = createdAction.id;
|
||||
|
||||
const createdRule = await createEsQueryRule({
|
||||
supertest,
|
||||
|
@ -220,7 +219,6 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
],
|
||||
});
|
||||
ruleId = createdRule.id;
|
||||
expect(ruleId).not.to.be(undefined);
|
||||
|
||||
// Wait for the action to index a document before disabling the alert and waiting for tasks to finish
|
||||
const resp = await waitForDocumentInIndex({
|
||||
|
@ -289,11 +287,11 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
const testStart = new Date();
|
||||
|
||||
// Should fail
|
||||
actionId = await createSlackConnector({
|
||||
const createdAction = await createSlackConnector({
|
||||
supertest,
|
||||
name: 'Slack Connector: Alerting API test',
|
||||
});
|
||||
expect(actionId).not.to.be(undefined);
|
||||
actionId = createdAction.id;
|
||||
|
||||
const createdRule = await createEsQueryRule({
|
||||
supertest,
|
||||
|
@ -326,7 +324,6 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
],
|
||||
});
|
||||
ruleId = createdRule.id;
|
||||
expect(ruleId).not.to.be(undefined);
|
||||
|
||||
// Should retry when the the action fails
|
||||
const resp = await waitForAllTasks({
|
||||
|
@ -341,12 +338,12 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
it('should throttle alerts when appropriate', async () => {
|
||||
const testStart = new Date();
|
||||
|
||||
actionId = await createIndexConnector({
|
||||
const createdAction = await createIndexConnector({
|
||||
supertest,
|
||||
name: 'Index Connector: Alerting API test',
|
||||
indexName: ALERT_ACTION_INDEX,
|
||||
});
|
||||
expect(actionId).not.to.be(undefined);
|
||||
actionId = createdAction.id;
|
||||
|
||||
const createdRule = await createEsQueryRule({
|
||||
supertest,
|
||||
|
@ -388,7 +385,6 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
],
|
||||
});
|
||||
ruleId = createdRule.id;
|
||||
expect(ruleId).not.to.be(undefined);
|
||||
|
||||
// Wait until alerts ran at least 3 times before disabling the alert and waiting for tasks to finish
|
||||
await waitForNumRuleRuns({ supertest, numOfRuns: 3, ruleId, esClient, testStart });
|
||||
|
@ -415,12 +411,12 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
it('should throttle alerts with throttled action when appropriate', async () => {
|
||||
const testStart = new Date();
|
||||
|
||||
actionId = await createIndexConnector({
|
||||
const createdAction = await createIndexConnector({
|
||||
supertest,
|
||||
name: 'Index Connector: Alerting API test',
|
||||
indexName: ALERT_ACTION_INDEX,
|
||||
});
|
||||
expect(actionId).not.to.be(undefined);
|
||||
actionId = createdAction.id;
|
||||
|
||||
const createdRule = await createEsQueryRule({
|
||||
supertest,
|
||||
|
@ -466,7 +462,6 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
],
|
||||
});
|
||||
ruleId = createdRule.id;
|
||||
expect(ruleId).not.to.be(undefined);
|
||||
|
||||
// Wait until alerts ran at least 3 times before disabling the alert and waiting for tasks to finish
|
||||
await waitForNumRuleRuns({ supertest, numOfRuns: 3, ruleId, esClient, testStart });
|
||||
|
@ -493,12 +488,12 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
it('should reset throttle window when not firing and should not throttle when changing groups', async () => {
|
||||
const testStart = new Date();
|
||||
|
||||
actionId = await createIndexConnector({
|
||||
const createdAction = await createIndexConnector({
|
||||
supertest,
|
||||
name: 'Index Connector: Alerting API test',
|
||||
indexName: ALERT_ACTION_INDEX,
|
||||
});
|
||||
expect(actionId).not.to.be(undefined);
|
||||
actionId = createdAction.id;
|
||||
|
||||
const createdRule = await createEsQueryRule({
|
||||
supertest,
|
||||
|
@ -568,7 +563,6 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
],
|
||||
});
|
||||
ruleId = createdRule.id;
|
||||
expect(ruleId).not.to.be(undefined);
|
||||
|
||||
// Wait for the action to index a document
|
||||
const resp = await waitForDocumentInIndex({
|
||||
|
@ -638,12 +632,12 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
const testStart = new Date();
|
||||
await createIndex({ esClient, indexName: ALERT_ACTION_INDEX });
|
||||
|
||||
actionId = await createIndexConnector({
|
||||
const createdAction = await createIndexConnector({
|
||||
supertest,
|
||||
name: 'Index Connector: Alerting API test',
|
||||
indexName: ALERT_ACTION_INDEX,
|
||||
});
|
||||
expect(actionId).not.to.be(undefined);
|
||||
actionId = createdAction.id;
|
||||
|
||||
const createdRule = await createEsQueryRule({
|
||||
supertest,
|
||||
|
@ -689,7 +683,6 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
],
|
||||
});
|
||||
ruleId = createdRule.id;
|
||||
expect(ruleId).not.to.be(undefined);
|
||||
|
||||
await muteRule({
|
||||
supertest,
|
||||
|
@ -728,12 +721,12 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
const testStart = new Date();
|
||||
await createIndex({ esClient, indexName: ALERT_ACTION_INDEX });
|
||||
|
||||
actionId = await createIndexConnector({
|
||||
const createdAction = await createIndexConnector({
|
||||
supertest,
|
||||
name: 'Index Connector: Alerting API test',
|
||||
indexName: ALERT_ACTION_INDEX,
|
||||
});
|
||||
expect(actionId).not.to.be(undefined);
|
||||
actionId = createdAction.id;
|
||||
|
||||
const createdRule = await createEsQueryRule({
|
||||
supertest,
|
||||
|
@ -779,7 +772,6 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
],
|
||||
});
|
||||
ruleId = createdRule.id;
|
||||
expect(ruleId).not.to.be(undefined);
|
||||
|
||||
await muteAlert({
|
||||
supertest,
|
||||
|
@ -816,12 +808,12 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
});
|
||||
|
||||
it(`should unmute all instances when unmuting an alert`, async () => {
|
||||
actionId = await createIndexConnector({
|
||||
const createdAction = await createIndexConnector({
|
||||
supertest,
|
||||
name: 'Index Connector: Alerting API test',
|
||||
indexName: ALERT_ACTION_INDEX,
|
||||
});
|
||||
expect(actionId).not.to.be(undefined);
|
||||
actionId = createdAction.id;
|
||||
|
||||
const createdRule = await createEsQueryRule({
|
||||
supertest,
|
||||
|
@ -867,7 +859,6 @@ export default function ({ getService }: FtrProviderContext) {
|
|||
],
|
||||
});
|
||||
ruleId = createdRule.id;
|
||||
expect(ruleId).not.to.be(undefined);
|
||||
|
||||
await muteAlert({
|
||||
supertest,
|
||||
|
|
|
@ -0,0 +1,543 @@
|
|||
/*
|
||||
* 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 expect from '@kbn/expect';
|
||||
import { omit, padStart } from 'lodash';
|
||||
import { FtrProviderContext } from '../../../ftr_provider_context';
|
||||
import { createIndexConnector, createEsQueryRule } from './helpers/alerting_api_helper';
|
||||
import {
|
||||
createIndex,
|
||||
getDocumentsInIndex,
|
||||
waitForAlertInIndex,
|
||||
waitForDocumentInIndex,
|
||||
} from './helpers/alerting_wait_for_helpers';
|
||||
|
||||
export default function ({ getService }: FtrProviderContext) {
|
||||
const supertest = getService('supertest');
|
||||
const esClient = getService('es');
|
||||
const esDeleteAllIndices = getService('esDeleteAllIndices');
|
||||
|
||||
describe('Summary actions', () => {
|
||||
const RULE_TYPE_ID = '.es-query';
|
||||
const ALERT_ACTION_INDEX = 'alert-action-es-query';
|
||||
const ALERT_INDEX = '.alerts-stack.alerts-default';
|
||||
let actionId: string;
|
||||
let ruleId: string;
|
||||
const fields = [
|
||||
'@timestamp',
|
||||
'event.action',
|
||||
'kibana.alert.duration.us',
|
||||
'kibana.alert.flapping_history',
|
||||
'kibana.alert.maintenance_window_ids',
|
||||
'kibana.alert.reason',
|
||||
'kibana.alert.rule.execution.uuid',
|
||||
'kibana.alert.rule.duration',
|
||||
'kibana.alert.start',
|
||||
'kibana.alert.time_range',
|
||||
'kibana.alert.uuid',
|
||||
'kibana.alert.url',
|
||||
'kibana.version',
|
||||
];
|
||||
|
||||
afterEach(async () => {
|
||||
await supertest
|
||||
.delete(`/api/actions/connector/${actionId}`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.set('x-elastic-internal-origin', 'foo')
|
||||
.expect(204);
|
||||
await supertest
|
||||
.delete(`/api/alerting/rule/${ruleId}`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.set('x-elastic-internal-origin', 'foo')
|
||||
.expect(204);
|
||||
await esDeleteAllIndices([ALERT_ACTION_INDEX]);
|
||||
});
|
||||
|
||||
it('should schedule actions for summary of alerts per rule run', async () => {
|
||||
const testStart = new Date();
|
||||
const createdAction = await createIndexConnector({
|
||||
supertest,
|
||||
name: 'Index Connector: Alerting API test',
|
||||
indexName: ALERT_ACTION_INDEX,
|
||||
});
|
||||
actionId = createdAction.id;
|
||||
|
||||
const createdRule = await createEsQueryRule({
|
||||
supertest,
|
||||
consumer: 'alerts',
|
||||
name: 'always fire',
|
||||
ruleTypeId: RULE_TYPE_ID,
|
||||
params: {
|
||||
size: 100,
|
||||
thresholdComparator: '>',
|
||||
threshold: [-1],
|
||||
index: ['alert-test-data'],
|
||||
timeField: 'date',
|
||||
esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n}`,
|
||||
timeWindowSize: 20,
|
||||
timeWindowUnit: 's',
|
||||
},
|
||||
actions: [
|
||||
{
|
||||
group: 'query matched',
|
||||
id: actionId,
|
||||
params: {
|
||||
documents: [
|
||||
{
|
||||
all: '{{alerts.all.count}}',
|
||||
new: '{{alerts.new.count}}',
|
||||
newIds: '[{{#alerts.new.data}}{{kibana.alert.instance.id}},{{/alerts.new.data}}]',
|
||||
ongoing: '{{alerts.ongoing.count}}',
|
||||
ongoingIds:
|
||||
'[{{#alerts.ongoing.data}}{{kibana.alert.instance.id}},{{/alerts.ongoing.data}}]',
|
||||
recovered: '{{alerts.recovered.count}}',
|
||||
recoveredIds:
|
||||
'[{{#alerts.recovered.data}}{{kibana.alert.instance.id}},{{/alerts.recovered.data}}]',
|
||||
},
|
||||
],
|
||||
},
|
||||
frequency: {
|
||||
notify_when: 'onActiveAlert',
|
||||
throttle: null,
|
||||
summary: true,
|
||||
},
|
||||
alerts_filter: {
|
||||
query: { kql: 'kibana.alert.rule.name:always fire', filters: [] },
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
ruleId = createdRule.id;
|
||||
|
||||
const resp = await waitForDocumentInIndex({
|
||||
esClient,
|
||||
indexName: ALERT_ACTION_INDEX,
|
||||
});
|
||||
expect(resp.hits.hits.length).to.be(1);
|
||||
|
||||
const resp2 = await waitForAlertInIndex({
|
||||
esClient,
|
||||
filter: testStart,
|
||||
indexName: ALERT_INDEX,
|
||||
ruleId,
|
||||
num: 1,
|
||||
});
|
||||
expect(resp2.hits.hits.length).to.be(1);
|
||||
|
||||
const document = resp.hits.hits[0];
|
||||
expect(document._source).to.eql({
|
||||
all: '1',
|
||||
new: '1',
|
||||
newIds: '[query matched,]',
|
||||
ongoing: '0',
|
||||
ongoingIds: '[]',
|
||||
recovered: '0',
|
||||
recoveredIds: '[]',
|
||||
});
|
||||
|
||||
const alertDocument = resp2.hits.hits[0]._source as Record<string, any>;
|
||||
expect(omit(alertDocument, fields)).to.eql({
|
||||
event: {
|
||||
kind: 'signal',
|
||||
},
|
||||
tags: [],
|
||||
kibana: {
|
||||
space_ids: ['default'],
|
||||
alert: {
|
||||
title: "rule 'always fire' matched query",
|
||||
evaluation: {
|
||||
conditions: 'Number of matching documents is greater than -1',
|
||||
value: 0,
|
||||
},
|
||||
action_group: 'query matched',
|
||||
flapping: false,
|
||||
duration: {},
|
||||
instance: { id: 'query matched' },
|
||||
status: 'active',
|
||||
workflow_status: 'open',
|
||||
rule: {
|
||||
category: 'Elasticsearch query',
|
||||
consumer: 'alerts',
|
||||
name: 'always fire',
|
||||
execution: {},
|
||||
parameters: {
|
||||
size: 100,
|
||||
thresholdComparator: '>',
|
||||
threshold: [-1],
|
||||
index: ['alert-test-data'],
|
||||
timeField: 'date',
|
||||
esQuery: '{\n "query":{\n "match_all" : {}\n }\n}',
|
||||
timeWindowSize: 20,
|
||||
timeWindowUnit: 's',
|
||||
excludeHitsFromPreviousRun: true,
|
||||
aggType: 'count',
|
||||
groupBy: 'all',
|
||||
searchType: 'esQuery',
|
||||
},
|
||||
producer: 'stackAlerts',
|
||||
revision: 0,
|
||||
rule_type_id: '.es-query',
|
||||
tags: [],
|
||||
uuid: ruleId,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should filter alerts by kql', async () => {
|
||||
const testStart = new Date();
|
||||
const createdAction = await createIndexConnector({
|
||||
supertest,
|
||||
name: 'Index Connector: Alerting API test',
|
||||
indexName: ALERT_ACTION_INDEX,
|
||||
});
|
||||
actionId = createdAction.id;
|
||||
|
||||
const createdRule = await createEsQueryRule({
|
||||
supertest,
|
||||
consumer: 'alerts',
|
||||
name: 'always fire',
|
||||
ruleTypeId: RULE_TYPE_ID,
|
||||
params: {
|
||||
size: 100,
|
||||
thresholdComparator: '>',
|
||||
threshold: [-1],
|
||||
index: ['alert-test-data'],
|
||||
timeField: 'date',
|
||||
esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n}`,
|
||||
timeWindowSize: 20,
|
||||
timeWindowUnit: 's',
|
||||
},
|
||||
actions: [
|
||||
{
|
||||
group: 'query matched',
|
||||
id: actionId,
|
||||
params: {
|
||||
documents: [
|
||||
{
|
||||
all: '{{alerts.all.count}}',
|
||||
new: '{{alerts.new.count}}',
|
||||
newIds: '[{{#alerts.new.data}}{{kibana.alert.instance.id}},{{/alerts.new.data}}]',
|
||||
ongoing: '{{alerts.ongoing.count}}',
|
||||
ongoingIds:
|
||||
'[{{#alerts.ongoing.data}}{{kibana.alert.instance.id}},{{/alerts.ongoing.data}}]',
|
||||
recovered: '{{alerts.recovered.count}}',
|
||||
recoveredIds:
|
||||
'[{{#alerts.recovered.data}}{{kibana.alert.instance.id}},{{/alerts.recovered.data}}]',
|
||||
},
|
||||
],
|
||||
},
|
||||
frequency: {
|
||||
notify_when: 'onActiveAlert',
|
||||
throttle: null,
|
||||
summary: true,
|
||||
},
|
||||
alerts_filter: {
|
||||
query: { kql: 'kibana.alert.instance.id:query matched', filters: [] },
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
ruleId = createdRule.id;
|
||||
|
||||
const resp = await waitForDocumentInIndex({
|
||||
esClient,
|
||||
indexName: ALERT_ACTION_INDEX,
|
||||
});
|
||||
expect(resp.hits.hits.length).to.be(1);
|
||||
|
||||
const resp2 = await waitForAlertInIndex({
|
||||
esClient,
|
||||
filter: testStart,
|
||||
indexName: ALERT_INDEX,
|
||||
ruleId,
|
||||
num: 1,
|
||||
});
|
||||
expect(resp2.hits.hits.length).to.be(1);
|
||||
|
||||
const document = resp.hits.hits[0];
|
||||
expect(document._source).to.eql({
|
||||
all: '1',
|
||||
new: '1',
|
||||
newIds: '[query matched,]',
|
||||
ongoing: '0',
|
||||
ongoingIds: '[]',
|
||||
recovered: '0',
|
||||
recoveredIds: '[]',
|
||||
});
|
||||
|
||||
const alertDocument = resp2.hits.hits[0]._source as Record<string, any>;
|
||||
expect(omit(alertDocument, fields)).to.eql({
|
||||
event: {
|
||||
kind: 'signal',
|
||||
},
|
||||
tags: [],
|
||||
kibana: {
|
||||
space_ids: ['default'],
|
||||
alert: {
|
||||
title: "rule 'always fire' matched query",
|
||||
evaluation: {
|
||||
conditions: 'Number of matching documents is greater than -1',
|
||||
value: 0,
|
||||
},
|
||||
action_group: 'query matched',
|
||||
flapping: false,
|
||||
duration: {},
|
||||
instance: { id: 'query matched' },
|
||||
status: 'active',
|
||||
workflow_status: 'open',
|
||||
rule: {
|
||||
category: 'Elasticsearch query',
|
||||
consumer: 'alerts',
|
||||
name: 'always fire',
|
||||
execution: {},
|
||||
parameters: {
|
||||
size: 100,
|
||||
thresholdComparator: '>',
|
||||
threshold: [-1],
|
||||
index: ['alert-test-data'],
|
||||
timeField: 'date',
|
||||
esQuery: '{\n "query":{\n "match_all" : {}\n }\n}',
|
||||
timeWindowSize: 20,
|
||||
timeWindowUnit: 's',
|
||||
excludeHitsFromPreviousRun: true,
|
||||
aggType: 'count',
|
||||
groupBy: 'all',
|
||||
searchType: 'esQuery',
|
||||
},
|
||||
producer: 'stackAlerts',
|
||||
revision: 0,
|
||||
rule_type_id: '.es-query',
|
||||
tags: [],
|
||||
uuid: ruleId,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should filter alerts by hours', async () => {
|
||||
const now = new Date();
|
||||
now.setHours(now.getHours() + 1);
|
||||
const hour = padStart(now.getUTCHours().toString(), 2, '0');
|
||||
const minutes = padStart(now.getUTCMinutes().toString(), 2, '0');
|
||||
|
||||
const start = `${hour}:${minutes}`;
|
||||
const end = `${hour}:${minutes}`;
|
||||
|
||||
await createIndex({ esClient, indexName: ALERT_ACTION_INDEX });
|
||||
|
||||
const createdAction = await createIndexConnector({
|
||||
supertest,
|
||||
name: 'Index Connector: Alerting API test',
|
||||
indexName: ALERT_ACTION_INDEX,
|
||||
});
|
||||
actionId = createdAction.id;
|
||||
|
||||
const createdRule = await createEsQueryRule({
|
||||
supertest,
|
||||
consumer: 'alerts',
|
||||
name: 'always fire',
|
||||
ruleTypeId: RULE_TYPE_ID,
|
||||
schedule: { interval: '1m' },
|
||||
params: {
|
||||
size: 100,
|
||||
thresholdComparator: '>',
|
||||
threshold: [-1],
|
||||
index: ['alert-test-data'],
|
||||
timeField: 'date',
|
||||
esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n}`,
|
||||
timeWindowSize: 20,
|
||||
timeWindowUnit: 's',
|
||||
},
|
||||
actions: [
|
||||
{
|
||||
group: 'query matched',
|
||||
id: actionId,
|
||||
params: {
|
||||
documents: [
|
||||
{
|
||||
all: '{{alerts.all.count}}',
|
||||
new: '{{alerts.new.count}}',
|
||||
newIds: '[{{#alerts.new.data}}{{kibana.alert.instance.id}},{{/alerts.new.data}}]',
|
||||
ongoing: '{{alerts.ongoing.count}}',
|
||||
ongoingIds:
|
||||
'[{{#alerts.ongoing.data}}{{kibana.alert.instance.id}},{{/alerts.ongoing.data}}]',
|
||||
recovered: '{{alerts.recovered.count}}',
|
||||
recoveredIds:
|
||||
'[{{#alerts.recovered.data}}{{kibana.alert.instance.id}},{{/alerts.recovered.data}}]',
|
||||
},
|
||||
],
|
||||
},
|
||||
frequency: {
|
||||
notify_when: 'onActiveAlert',
|
||||
throttle: null,
|
||||
summary: true,
|
||||
},
|
||||
alerts_filter: {
|
||||
timeframe: {
|
||||
days: [1, 2, 3, 4, 5, 6, 7],
|
||||
timezone: 'UTC',
|
||||
hours: { start, end },
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
ruleId = createdRule.id;
|
||||
|
||||
// Should not have executed any action
|
||||
const resp = await getDocumentsInIndex({
|
||||
esClient,
|
||||
indexName: ALERT_ACTION_INDEX,
|
||||
});
|
||||
expect(resp.hits.hits.length).to.be(0);
|
||||
});
|
||||
|
||||
it('should schedule actions for summary of alerts on a custom interval', async () => {
|
||||
const testStart = new Date();
|
||||
const createdAction = await createIndexConnector({
|
||||
supertest,
|
||||
name: 'Index Connector: Alerting API test',
|
||||
indexName: ALERT_ACTION_INDEX,
|
||||
});
|
||||
actionId = createdAction.id;
|
||||
|
||||
const createdRule = await createEsQueryRule({
|
||||
supertest,
|
||||
consumer: 'alerts',
|
||||
name: 'always fire',
|
||||
ruleTypeId: RULE_TYPE_ID,
|
||||
schedule: { interval: '1m' },
|
||||
params: {
|
||||
size: 100,
|
||||
thresholdComparator: '>',
|
||||
threshold: [-1],
|
||||
index: ['alert-test-data'],
|
||||
timeField: 'date',
|
||||
esQuery: `{\n \"query\":{\n \"match_all\" : {}\n }\n}`,
|
||||
timeWindowSize: 20,
|
||||
timeWindowUnit: 's',
|
||||
},
|
||||
actions: [
|
||||
{
|
||||
group: 'query matched',
|
||||
id: actionId,
|
||||
params: {
|
||||
documents: [
|
||||
{
|
||||
all: '{{alerts.all.count}}',
|
||||
new: '{{alerts.new.count}}',
|
||||
newIds: '[{{#alerts.new.data}}{{kibana.alert.instance.id}},{{/alerts.new.data}}]',
|
||||
ongoing: '{{alerts.ongoing.count}}',
|
||||
ongoingIds:
|
||||
'[{{#alerts.ongoing.data}}{{kibana.alert.instance.id}},{{/alerts.ongoing.data}}]',
|
||||
recovered: '{{alerts.recovered.count}}',
|
||||
recoveredIds:
|
||||
'[{{#alerts.recovered.data}}{{kibana.alert.instance.id}},{{/alerts.recovered.data}}]',
|
||||
},
|
||||
],
|
||||
},
|
||||
frequency: {
|
||||
notify_when: 'onThrottleInterval',
|
||||
throttle: '1m',
|
||||
summary: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
ruleId = createdRule.id;
|
||||
|
||||
const resp = await waitForDocumentInIndex({
|
||||
esClient,
|
||||
indexName: ALERT_ACTION_INDEX,
|
||||
num: 2,
|
||||
});
|
||||
|
||||
const resp2 = await waitForAlertInIndex({
|
||||
esClient,
|
||||
filter: testStart,
|
||||
indexName: ALERT_INDEX,
|
||||
ruleId,
|
||||
num: 1,
|
||||
});
|
||||
expect(resp2.hits.hits.length).to.be(1);
|
||||
|
||||
const document = resp.hits.hits[0];
|
||||
expect(document._source).to.eql({
|
||||
all: '1',
|
||||
new: '1',
|
||||
newIds: '[query matched,]',
|
||||
ongoing: '0',
|
||||
ongoingIds: '[]',
|
||||
recovered: '0',
|
||||
recoveredIds: '[]',
|
||||
});
|
||||
|
||||
const document1 = resp.hits.hits[1];
|
||||
expect(document1._source).to.eql({
|
||||
all: '1',
|
||||
new: '0',
|
||||
newIds: '[]',
|
||||
ongoing: '1',
|
||||
ongoingIds: '[query matched,]',
|
||||
recovered: '0',
|
||||
recoveredIds: '[]',
|
||||
});
|
||||
|
||||
const alertDocument = resp2.hits.hits[0]._source as Record<string, any>;
|
||||
expect(omit(alertDocument, fields)).to.eql({
|
||||
event: {
|
||||
kind: 'signal',
|
||||
},
|
||||
tags: [],
|
||||
kibana: {
|
||||
space_ids: ['default'],
|
||||
alert: {
|
||||
title: "rule 'always fire' matched query",
|
||||
evaluation: {
|
||||
conditions: 'Number of matching documents is greater than -1',
|
||||
value: 0,
|
||||
},
|
||||
action_group: 'query matched',
|
||||
flapping: false,
|
||||
duration: {},
|
||||
instance: { id: 'query matched' },
|
||||
status: 'active',
|
||||
workflow_status: 'open',
|
||||
rule: {
|
||||
category: 'Elasticsearch query',
|
||||
consumer: 'alerts',
|
||||
name: 'always fire',
|
||||
execution: {},
|
||||
parameters: {
|
||||
size: 100,
|
||||
thresholdComparator: '>',
|
||||
threshold: [-1],
|
||||
index: ['alert-test-data'],
|
||||
timeField: 'date',
|
||||
esQuery: '{\n "query":{\n "match_all" : {}\n }\n}',
|
||||
timeWindowSize: 20,
|
||||
timeWindowUnit: 's',
|
||||
excludeHitsFromPreviousRun: true,
|
||||
aggType: 'count',
|
||||
groupBy: 'all',
|
||||
searchType: 'esQuery',
|
||||
},
|
||||
producer: 'stackAlerts',
|
||||
revision: 0,
|
||||
rule_type_id: '.es-query',
|
||||
tags: [],
|
||||
uuid: ruleId,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue