diff --git a/x-pack/plugins/infra/public/components/alerting/metrics/alert_dropdown.tsx b/x-pack/plugins/infra/public/components/alerting/metrics/alert_dropdown.tsx index 0a464d91fbe06..bb664f4067662 100644 --- a/x-pack/plugins/infra/public/components/alerting/metrics/alert_dropdown.tsx +++ b/x-pack/plugins/infra/public/components/alerting/metrics/alert_dropdown.tsx @@ -38,7 +38,7 @@ export const AlertDropdown = () => { 'kibana#/management/kibana/triggersActions/alerts' )} > - + , ]; }, [kibana.services]); diff --git a/x-pack/plugins/infra/public/components/alerting/metrics/metric_threshold_alert_type.ts b/x-pack/plugins/infra/public/components/alerting/metrics/metric_threshold_alert_type.ts index d3b5aaa7c8796..60c4e013d79ac 100644 --- a/x-pack/plugins/infra/public/components/alerting/metrics/metric_threshold_alert_type.ts +++ b/x-pack/plugins/infra/public/components/alerting/metrics/metric_threshold_alert_type.ts @@ -15,10 +15,20 @@ export function getAlertType(): AlertTypeModel { return { id: METRIC_THRESHOLD_ALERT_TYPE_ID, name: i18n.translate('xpack.infra.metrics.alertFlyout.alertName', { - defaultMessage: 'Alert Trigger', + defaultMessage: 'Metric Threshold', }), iconClass: 'bell', alertParamsExpression: Expressions, validate: validateMetricThreshold, + defaultActionMessage: i18n.translate( + 'xpack.infra.metrics.alerting.threshold.defaultActionMessage', + { + defaultMessage: `\\{\\{alertName\\}\\} - \\{\\{context.group\\}\\} + +\\{\\{context.metricOf.condition0\\}\\} has crossed a threshold of \\{\\{context.thresholdOf.condition0\\}\\} +Current value is \\{\\{context.valueOf.condition0\\}\\} +`, + } + ), }; } diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts index feaa404ae960a..09f1702349542 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.test.ts @@ -126,6 +126,14 @@ describe('The metric threshold alert type', () => { expect(alertInstances.get(instanceID).mostRecentAction).toBe(undefined); expect(alertInstances.get(instanceID).state.alertState).toBe(AlertStates.OK); }); + test('reports expected values to the action context', async () => { + await execute(Comparator.GT, [0.75]); + const mostRecentAction = alertInstances.get(instanceID).mostRecentAction; + expect(mostRecentAction.action.group).toBe('*'); + expect(mostRecentAction.action.valueOf.condition0).toBe(1); + expect(mostRecentAction.action.thresholdOf.condition0).toStrictEqual([0.75]); + expect(mostRecentAction.action.metricOf.condition0).toBe('test.metric.1'); + }); }); describe('querying with a groupBy parameter', () => { @@ -166,6 +174,11 @@ describe('The metric threshold alert type', () => { expect(alertInstances.get(instanceIdB).mostRecentAction).toBe(undefined); expect(alertInstances.get(instanceIdB).state.alertState).toBe(AlertStates.OK); }); + test('reports group values to the action context', async () => { + await execute(Comparator.GT, [0.75]); + expect(alertInstances.get(instanceIdA).mostRecentAction.action.group).toBe('a'); + expect(alertInstances.get(instanceIdB).mostRecentAction.action.group).toBe('b'); + }); }); describe('querying with multiple criteria', () => { @@ -215,6 +228,17 @@ describe('The metric threshold alert type', () => { expect(alertInstances.get(instanceIdB).mostRecentAction).toBe(undefined); expect(alertInstances.get(instanceIdB).state.alertState).toBe(AlertStates.OK); }); + test('sends all criteria to the action context', async () => { + const instanceID = 'test-*'; + await execute(Comparator.GT_OR_EQ, [1.0], [3.0]); + const mostRecentAction = alertInstances.get(instanceID).mostRecentAction; + expect(mostRecentAction.action.valueOf.condition0).toBe(1); + expect(mostRecentAction.action.valueOf.condition1).toBe(3.5); + expect(mostRecentAction.action.thresholdOf.condition0).toStrictEqual([1.0]); + expect(mostRecentAction.action.thresholdOf.condition1).toStrictEqual([3.0]); + expect(mostRecentAction.action.metricOf.condition0).toBe('test.metric.1'); + expect(mostRecentAction.action.metricOf.condition1).toBe('test.metric.2'); + }); }); describe('querying with the count aggregator', () => { const instanceID = 'test-*'; diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.ts index bfe04b82b95fc..60bba61b75ef1 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/metric_threshold_executor.ts @@ -223,6 +223,17 @@ const comparatorMap = { [Comparator.LT_OR_EQ]: (a: number, [b]: number[]) => a <= b, }; +const mapToConditionsLookup = ( + list: any[], + mapFn: (value: any, index: number, array: any[]) => unknown +) => + list + .map(mapFn) + .reduce( + (result: Record, value, i) => ({ ...result, [`condition${i}`]: value }), + {} + ); + export const createMetricThresholdExecutor = (alertUUID: string) => async function({ services, params }: AlertExecutorOptions) { const { criteria, groupBy, filterQuery } = params as { @@ -261,7 +272,9 @@ export const createMetricThresholdExecutor = (alertUUID: string) => if (shouldAlertFire) { alertInstance.scheduleActions(FIRED_ACTIONS.id, { group, - value: alertResults.map(result => result[group].currentValue), + valueOf: mapToConditionsLookup(alertResults, result => result[group].currentValue), + thresholdOf: mapToConditionsLookup(criteria, criterion => criterion.threshold), + metricOf: mapToConditionsLookup(criteria, criterion => criterion.metric), }); } // Future use: ability to fetch display current alert state diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_alert_type.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_alert_type.ts index ed3a9b2f4fe36..57f9124db923c 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_alert_type.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/register_metric_threshold_alert_type.ts @@ -3,6 +3,7 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ +import { i18n } from '@kbn/i18n'; import uuid from 'uuid'; import { schema } from '@kbn/config-schema'; import { PluginSetupContract } from '../../../../../alerting/server'; @@ -49,6 +50,37 @@ export async function registerMetricThresholdAlertType(alertingPlugin: PluginSet metric: schema.never(), }); + const groupActionVariableDescription = i18n.translate( + 'xpack.infra.metrics.alerting.threshold.alerting.groupActionVariableDescription', + { + defaultMessage: 'Name of the group reporting data', + } + ); + + const valueOfActionVariableDescription = i18n.translate( + 'xpack.infra.metrics.alerting.threshold.alerting.valueOfActionVariableDescription', + { + defaultMessage: + 'Record of the current value of the watched metric; grouped by condition, i.e valueOf.condition0, valueOf.condition1, etc.', + } + ); + + const thresholdOfActionVariableDescription = i18n.translate( + 'xpack.infra.metrics.alerting.threshold.alerting.thresholdOfActionVariableDescription', + { + defaultMessage: + 'Record of the alerting threshold; grouped by condition, i.e thresholdOf.condition0, thresholdOf.condition1, etc.', + } + ); + + const metricOfActionVariableDescription = i18n.translate( + 'xpack.infra.metrics.alerting.threshold.alerting.metricOfActionVariableDescription', + { + defaultMessage: + 'Record of the watched metric; grouped by condition, i.e metricOf.condition0, metricOf.condition1, etc.', + } + ); + alertingPlugin.registerType({ id: METRIC_THRESHOLD_ALERT_TYPE_ID, name: 'Metric Alert - Threshold', @@ -62,5 +94,13 @@ export async function registerMetricThresholdAlertType(alertingPlugin: PluginSet defaultActionGroupId: FIRED_ACTIONS.id, actionGroups: [FIRED_ACTIONS], executor: createMetricThresholdExecutor(alertUUID), + actionVariables: { + context: [ + { name: 'group', description: groupActionVariableDescription }, + { name: 'valueOf', description: valueOfActionVariableDescription }, + { name: 'thresholdOf', description: thresholdOfActionVariableDescription }, + { name: 'metricOf', description: metricOfActionVariableDescription }, + ], + }, }); }