diff --git a/x-pack/packages/kbn-infra-forge/src/data_sources/fake_hosts/index.ts b/x-pack/packages/kbn-infra-forge/src/data_sources/fake_hosts/index.ts index fe969726499b4..e134cc21a0796 100644 --- a/x-pack/packages/kbn-infra-forge/src/data_sources/fake_hosts/index.ts +++ b/x-pack/packages/kbn-infra-forge/src/data_sources/fake_hosts/index.ts @@ -51,10 +51,10 @@ export const generateEvent = (index: number, timestamp: Moment, interval: number }, }, user: { - pct: randomBetween(1, 4), + pct: 2.5, }, system: { - pct: randomBetween(1, 4), + pct: 3, }, }, }, diff --git a/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/avg_pct_fired.ts b/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/avg_pct_fired.ts index b36a0bcd86010..91b767ca8087a 100644 --- a/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/avg_pct_fired.ts +++ b/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/avg_pct_fired.ts @@ -5,6 +5,7 @@ * 2.0. */ +import moment from 'moment'; import { cleanup, generate } from '@kbn/infra-forge'; import { Aggregators, @@ -15,8 +16,13 @@ import expect from '@kbn/expect'; import { OBSERVABILITY_THRESHOLD_RULE_TYPE_ID } from '@kbn/rule-data-utils'; import { createIndexConnector, createRule } from '../helpers/alerting_api_helper'; import { createDataView, deleteDataView } from '../helpers/data_view'; -import { waitForAlertInIndex, waitForRuleStatus } from '../helpers/alerting_wait_for_helpers'; +import { + waitForAlertInIndex, + waitForDocumentInIndex, + waitForRuleStatus, +} from '../helpers/alerting_wait_for_helpers'; import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { ActionDocument } from './typings'; // eslint-disable-next-line import/no-default-export export default function ({ getService }: FtrProviderContext) { @@ -35,6 +41,8 @@ export default function ({ getService }: FtrProviderContext) { let infraDataIndex: string; let actionId: string; let ruleId: string; + let alertId: string; + let startedAt: string; before(async () => { infraDataIndex = await generate({ esClient, lookback: 'now-15m', logger }); @@ -110,6 +118,10 @@ export default function ({ getService }: FtrProviderContext) { documents: [ { ruleType: '{{rule.type}}', + alertDetailsUrl: '{{context.alertDetailsUrl}}', + reason: '{{context.reason}}', + value: '{{context.value}}', + host: '{{context.host}}', }, ], }, @@ -140,6 +152,8 @@ export default function ({ getService }: FtrProviderContext) { indexName: CUSTOM_THRESHOLD_RULE_ALERT_INDEX, ruleId, }); + alertId = (resp.hits.hits[0]._source as any)['kibana.alert.uuid']; + startedAt = (resp.hits.hits[0]._source as any)['kibana.alert.start']; expect(resp.hits.hits[0]._source).property( 'kibana.alert.rule.category', @@ -186,6 +200,23 @@ export default function ({ getService }: FtrProviderContext) { searchConfiguration: { index: 'data-view-id', query: { query: '', language: 'kuery' } }, }); }); + + it('should set correct action variables', async () => { + const rangeFrom = moment(startedAt).subtract('5', 'minute').toISOString(); + const resp = await waitForDocumentInIndex({ + esClient, + indexName: ALERT_ACTION_INDEX, + }); + + expect(resp.hits.hits[0]._source?.ruleType).eql('observability.rules.custom_threshold'); + expect(resp.hits.hits[0]._source?.alertDetailsUrl).eql( + `https://localhost:5601/app/observability/alerts?_a=(kuery:%27kibana.alert.uuid:%20%22${alertId}%22%27%2CrangeFrom:%27${rangeFrom}%27%2CrangeTo:now%2Cstatus:all)` + ); + expect(resp.hits.hits[0]._source?.reason).eql( + 'Custom equation is 2.5 in the last 5 mins. Alert when > 0.5.' + ); + expect(resp.hits.hits[0]._source?.value).eql('2.5'); + }); }); }); } diff --git a/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/avg_pct_no_data.ts b/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/avg_pct_no_data.ts index 9eba55d60743a..949a74480382b 100644 --- a/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/avg_pct_no_data.ts +++ b/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/avg_pct_no_data.ts @@ -5,23 +5,30 @@ * 2.0. */ +import moment from 'moment'; import { Aggregators, Comparator, } from '@kbn/observability-plugin/common/custom_threshold_rule/types'; -import { FIRED_ACTIONS_ID } from '@kbn/observability-plugin/server/lib/rules/custom_threshold/custom_threshold_executor'; +import { NO_DATA_ACTIONS_ID } from '@kbn/observability-plugin/server/lib/rules/custom_threshold/custom_threshold_executor'; import expect from '@kbn/expect'; import { OBSERVABILITY_THRESHOLD_RULE_TYPE_ID } from '@kbn/rule-data-utils'; import { createIndexConnector, createRule } from '../helpers/alerting_api_helper'; import { createDataView, deleteDataView } from '../helpers/data_view'; -import { waitForAlertInIndex, waitForRuleStatus } from '../helpers/alerting_wait_for_helpers'; +import { + waitForAlertInIndex, + waitForDocumentInIndex, + waitForRuleStatus, +} from '../helpers/alerting_wait_for_helpers'; import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { ActionDocument } from './typings'; // eslint-disable-next-line import/no-default-export export default function ({ getService }: FtrProviderContext) { const esClient = getService('es'); const supertest = getService('supertest'); + const esDeleteAllIndices = getService('esDeleteAllIndices'); describe('Custom Threshold rule - AVG - PCT - NoData', () => { const CUSTOM_THRESHOLD_RULE_ALERT_INDEX = '.alerts-observability.threshold.alerts-default'; @@ -29,6 +36,8 @@ export default function ({ getService }: FtrProviderContext) { const DATA_VIEW_ID = 'data-view-id-no-data'; let actionId: string; let ruleId: string; + let alertId: string; + let startedAt: string; before(async () => { await createDataView({ @@ -54,6 +63,7 @@ export default function ({ getService }: FtrProviderContext) { supertest, id: DATA_VIEW_ID, }); + await esDeleteAllIndices([ALERT_ACTION_INDEX]); }); describe('Rule creation', () => { @@ -95,12 +105,15 @@ export default function ({ getService }: FtrProviderContext) { }, actions: [ { - group: FIRED_ACTIONS_ID, + group: NO_DATA_ACTIONS_ID, id: actionId, params: { documents: [ { ruleType: '{{rule.type}}', + alertDetailsUrl: '{{context.alertDetailsUrl}}', + reason: '{{context.reason}}', + value: '{{context.value}}', }, ], }, @@ -131,6 +144,8 @@ export default function ({ getService }: FtrProviderContext) { indexName: CUSTOM_THRESHOLD_RULE_ALERT_INDEX, ruleId, }); + alertId = (resp.hits.hits[0]._source as any)['kibana.alert.uuid']; + startedAt = (resp.hits.hits[0]._source as any)['kibana.alert.start']; expect(resp.hits.hits[0]._source).property( 'kibana.alert.rule.category', @@ -180,6 +195,23 @@ export default function ({ getService }: FtrProviderContext) { }, }); }); + + it('should set correct action variables', async () => { + const rangeFrom = moment(startedAt).subtract('5', 'minute').toISOString(); + const resp = await waitForDocumentInIndex({ + esClient, + indexName: ALERT_ACTION_INDEX, + }); + + expect(resp.hits.hits[0]._source?.ruleType).eql('observability.rules.custom_threshold'); + expect(resp.hits.hits[0]._source?.alertDetailsUrl).eql( + `https://localhost:5601/app/observability/alerts?_a=(kuery:%27kibana.alert.uuid:%20%22${alertId}%22%27%2CrangeFrom:%27${rangeFrom}%27%2CrangeTo:now%2Cstatus:all)` + ); + expect(resp.hits.hits[0]._source?.reason).eql( + 'Custom equation reported no data in the last 5m' + ); + expect(resp.hits.hits[0]._source?.value).eql('[NO DATA]'); + }); }); }); } diff --git a/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/avg_us_fired.ts b/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/avg_us_fired.ts index d7f21a1453823..46b109d48a0df 100644 --- a/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/avg_us_fired.ts +++ b/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/avg_us_fired.ts @@ -24,6 +24,7 @@ import { waitForDocumentInIndex, waitForRuleStatus, } from '../helpers/alerting_wait_for_helpers'; +import { ActionDocument } from './typings'; // eslint-disable-next-line import/no-default-export export default function ({ getService }: FtrProviderContext) { @@ -206,12 +207,7 @@ export default function ({ getService }: FtrProviderContext) { it('should set correct action parameter: ruleType', async () => { const rangeFrom = moment(startedAt).subtract('5', 'minute').toISOString(); - const resp = await waitForDocumentInIndex<{ - ruleType: string; - alertDetailsUrl: string; - reason: string; - value: string; - }>({ + const resp = await waitForDocumentInIndex({ esClient, indexName: ALERT_ACTION_INDEX, }); diff --git a/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/custom_eq_avg_bytes_fired.ts b/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/custom_eq_avg_bytes_fired.ts index 50e62935f0edb..3ebb2fa0dbc76 100644 --- a/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/custom_eq_avg_bytes_fired.ts +++ b/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/custom_eq_avg_bytes_fired.ts @@ -11,6 +11,7 @@ * 2.0. */ +import moment from 'moment'; import { cleanup, generate } from '@kbn/infra-forge'; import { Aggregators, @@ -21,8 +22,13 @@ import expect from '@kbn/expect'; import { OBSERVABILITY_THRESHOLD_RULE_TYPE_ID } from '@kbn/rule-data-utils'; import { createIndexConnector, createRule } from '../helpers/alerting_api_helper'; import { createDataView, deleteDataView } from '../helpers/data_view'; -import { waitForAlertInIndex, waitForRuleStatus } from '../helpers/alerting_wait_for_helpers'; +import { + waitForAlertInIndex, + waitForDocumentInIndex, + waitForRuleStatus, +} from '../helpers/alerting_wait_for_helpers'; import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { ActionDocument } from './typings'; // eslint-disable-next-line import/no-default-export export default function ({ getService }: FtrProviderContext) { @@ -41,6 +47,8 @@ export default function ({ getService }: FtrProviderContext) { let infraDataIndex: string; let actionId: string; let ruleId: string; + let alertId: string; + let startedAt: string; before(async () => { infraDataIndex = await generate({ esClient, lookback: 'now-15m', logger }); @@ -118,6 +126,9 @@ export default function ({ getService }: FtrProviderContext) { documents: [ { ruleType: '{{rule.type}}', + alertDetailsUrl: '{{context.alertDetailsUrl}}', + reason: '{{context.reason}}', + value: '{{context.value}}', }, ], }, @@ -148,6 +159,8 @@ export default function ({ getService }: FtrProviderContext) { indexName: CUSTOM_THRESHOLD_RULE_ALERT_INDEX, ruleId, }); + alertId = (resp.hits.hits[0]._source as any)['kibana.alert.uuid']; + startedAt = (resp.hits.hits[0]._source as any)['kibana.alert.start']; expect(resp.hits.hits[0]._source).property( 'kibana.alert.rule.category', @@ -198,6 +211,23 @@ export default function ({ getService }: FtrProviderContext) { searchConfiguration: { index: 'data-view-id', query: { query: '', language: 'kuery' } }, }); }); + + it('should set correct action variables', async () => { + const rangeFrom = moment(startedAt).subtract('5', 'minute').toISOString(); + const resp = await waitForDocumentInIndex({ + esClient, + indexName: ALERT_ACTION_INDEX, + }); + + expect(resp.hits.hits[0]._source?.ruleType).eql('observability.rules.custom_threshold'); + expect(resp.hits.hits[0]._source?.alertDetailsUrl).eql( + `https://localhost:5601/app/observability/alerts?_a=(kuery:%27kibana.alert.uuid:%20%22${alertId}%22%27%2CrangeFrom:%27${rangeFrom}%27%2CrangeTo:now%2Cstatus:all)` + ); + expect(resp.hits.hits[0]._source?.reason).eql( + 'Custom equation is 1 in the last 1 min. Alert when > 0.9.' + ); + expect(resp.hits.hits[0]._source?.value).eql('1'); + }); }); }); } diff --git a/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/documents_count_fired.ts b/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/documents_count_fired.ts index 644cfaa2264e0..07efa46cf175f 100644 --- a/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/documents_count_fired.ts +++ b/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/documents_count_fired.ts @@ -5,6 +5,7 @@ * 2.0. */ +import moment from 'moment'; import { cleanup, generate } from '@kbn/infra-forge'; import { Aggregators, @@ -15,8 +16,13 @@ import expect from '@kbn/expect'; import { OBSERVABILITY_THRESHOLD_RULE_TYPE_ID } from '@kbn/rule-data-utils'; import { createIndexConnector, createRule } from '../helpers/alerting_api_helper'; import { createDataView, deleteDataView } from '../helpers/data_view'; -import { waitForAlertInIndex, waitForRuleStatus } from '../helpers/alerting_wait_for_helpers'; +import { + waitForAlertInIndex, + waitForDocumentInIndex, + waitForRuleStatus, +} from '../helpers/alerting_wait_for_helpers'; import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { ActionDocument } from './typings'; // eslint-disable-next-line import/no-default-export export default function ({ getService }: FtrProviderContext) { @@ -35,6 +41,8 @@ export default function ({ getService }: FtrProviderContext) { let infraDataIndex: string; let actionId: string; let ruleId: string; + let alertId: string; + let startedAt: string; before(async () => { infraDataIndex = await generate({ esClient, lookback: 'now-15m', logger }); @@ -108,6 +116,9 @@ export default function ({ getService }: FtrProviderContext) { documents: [ { ruleType: '{{rule.type}}', + alertDetailsUrl: '{{context.alertDetailsUrl}}', + reason: '{{context.reason}}', + value: '{{context.value}}', }, ], }, @@ -138,6 +149,8 @@ export default function ({ getService }: FtrProviderContext) { indexName: CUSTOM_THRESHOLD_RULE_ALERT_INDEX, ruleId, }); + alertId = (resp.hits.hits[0]._source as any)['kibana.alert.uuid']; + startedAt = (resp.hits.hits[0]._source as any)['kibana.alert.start']; expect(resp.hits.hits[0]._source).property( 'kibana.alert.rule.category', @@ -186,6 +199,23 @@ export default function ({ getService }: FtrProviderContext) { searchConfiguration: { index: 'data-view-id', query: { query: '', language: 'kuery' } }, }); }); + + it('should set correct action variables', async () => { + const rangeFrom = moment(startedAt).subtract('5', 'minute').toISOString(); + const resp = await waitForDocumentInIndex({ + esClient, + indexName: ALERT_ACTION_INDEX, + }); + + expect(resp.hits.hits[0]._source?.ruleType).eql('observability.rules.custom_threshold'); + expect(resp.hits.hits[0]._source?.alertDetailsUrl).eql( + `https://localhost:5601/app/observability/alerts?_a=(kuery:%27kibana.alert.uuid:%20%22${alertId}%22%27%2CrangeFrom:%27${rangeFrom}%27%2CrangeTo:now%2Cstatus:all)` + ); + expect(resp.hits.hits[0]._source?.reason).eql( + 'Custom equation is 3 in the last 1 min. Alert when > 2.' + ); + expect(resp.hits.hits[0]._source?.value).eql('3'); + }); }); }); } diff --git a/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/group_by_fired.ts b/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/group_by_fired.ts index b22fae7fe00f1..1d5ffa15ff97f 100644 --- a/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/group_by_fired.ts +++ b/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/group_by_fired.ts @@ -4,12 +4,6 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -/* - * 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 moment from 'moment'; import { cleanup, generate } from '@kbn/infra-forge'; @@ -28,6 +22,7 @@ import { waitForRuleStatus, } from '../helpers/alerting_wait_for_helpers'; import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { ActionDocument } from './typings'; // eslint-disable-next-line import/no-default-export export default function ({ getService }: FtrProviderContext) { @@ -35,8 +30,6 @@ export default function ({ getService }: FtrProviderContext) { const supertest = getService('supertest'); const esDeleteAllIndices = getService('esDeleteAllIndices'); const logger = getService('log'); - let alertId: string; - let startedAt: string; describe('Custom Threshold rule - GROUP_BY - FIRED', () => { const CUSTOM_THRESHOLD_RULE_ALERT_INDEX = '.alerts-observability.threshold.alerts-default'; @@ -48,6 +41,8 @@ export default function ({ getService }: FtrProviderContext) { let infraDataIndex: string; let actionId: string; let ruleId: string; + let alertId: string; + let startedAt: string; before(async () => { infraDataIndex = await generate({ esClient, lookback: 'now-15m', logger }); @@ -235,14 +230,7 @@ export default function ({ getService }: FtrProviderContext) { it('should set correct action variables', async () => { const rangeFrom = moment(startedAt).subtract('5', 'minute').toISOString(); - const resp = await waitForDocumentInIndex<{ - ruleType: string; - alertDetailsUrl: string; - reason: string; - value: string; - host: string; - group: string; - }>({ + const resp = await waitForDocumentInIndex({ esClient, indexName: ALERT_ACTION_INDEX, }); diff --git a/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/typings.ts b/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/typings.ts new file mode 100644 index 0000000000000..83894e6cf24a2 --- /dev/null +++ b/x-pack/test/alerting_api_integration/observability/custom_threshold_rule/typings.ts @@ -0,0 +1,15 @@ +/* + * 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. + */ + +export interface ActionDocument { + ruleType: string; + alertDetailsUrl: string; + reason: string; + value: string; + host?: string; + group?: string; +}