Skip to content

Commit

Permalink
Added defaultActionMessage to index threshold alert UI type definit…
Browse files Browse the repository at this point in the history
…ion (elastic#80936) (elastic#82950)

* resolves elastic#78148

Adds a `defaultActionMessage` to the index threshold alert, so that the `message` parameter for actions will be pre-filled with a useful message

Co-authored-by: Dhruv Bodani <[email protected]>
  • Loading branch information
pmuellr and dB2510 authored Nov 9, 2020
1 parent 8b05255 commit 694c322
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ describe('ActionContext', () => {
date: '2020-01-01T00:00:00.000Z',
group: '[group]',
value: 42,
function: 'count > 4',
};
const context = addMessages({ name: '[alert-name]' }, base, params);
expect(context.title).toMatchInlineSnapshot(
Expand Down Expand Up @@ -53,6 +54,7 @@ describe('ActionContext', () => {
date: '2020-01-01T00:00:00.000Z',
group: '[group]',
value: 42,
function: 'avg([aggField]) > 4.2',
};
const context = addMessages({ name: '[alert-name]' }, base, params);
expect(context.title).toMatchInlineSnapshot(
Expand Down Expand Up @@ -80,6 +82,7 @@ describe('ActionContext', () => {
date: '2020-01-01T00:00:00.000Z',
group: '[group]',
value: 4,
function: 'count between 4,5',
};
const context = addMessages({ name: '[alert-name]' }, base, params);
expect(context.title).toMatchInlineSnapshot(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ export interface BaseActionContext extends AlertInstanceContext {
date: string;
// the value that met the threshold
value: number;
// the function that is used
function: string;
}

export function addMessages(
Expand All @@ -42,9 +44,6 @@ export function addMessages(
},
});

const agg = params.aggField ? `${params.aggType}(${params.aggField})` : `${params.aggType}`;
const humanFn = `${agg} ${params.thresholdComparator} ${params.threshold.join(',')}`;

const window = `${params.timeWindowSize}${params.timeWindowUnit}`;
const message = i18n.translate(
'xpack.stackAlerts.indexThreshold.alertTypeContextMessageDescription',
Expand All @@ -55,7 +54,7 @@ export function addMessages(
name: alertInfo.name,
group: baseContext.group,
value: baseContext.value,
function: humanFn,
function: baseContext.function,
window,
date: baseContext.date,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ describe('alertType', () => {
"description": "The value that exceeded the threshold.",
"name": "value",
},
Object {
"description": "A string describing the threshold comparator and threshold",
"name": "function",
},
],
"params": Array [
Object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ export function getAlertType(service: Service): AlertType<Params, {}, {}, Action
}
);

const actionVariableContextFunctionLabel = i18n.translate(
'xpack.stackAlerts.indexThreshold.actionVariableContextFunctionLabel',
{
defaultMessage: 'A string describing the threshold comparator and threshold',
}
);

const alertParamsVariables = Object.keys(CoreQueryParamsSchemaProperties).map(
(propKey: string) => {
return {
Expand All @@ -107,6 +114,7 @@ export function getAlertType(service: Service): AlertType<Params, {}, {}, Action
{ name: 'group', description: actionVariableContextGroupLabel },
{ name: 'date', description: actionVariableContextDateLabel },
{ name: 'value', description: actionVariableContextValueLabel },
{ name: 'function', description: actionVariableContextFunctionLabel },
],
params: [
{ name: 'threshold', description: actionVariableContextThresholdLabel },
Expand Down Expand Up @@ -160,10 +168,14 @@ export function getAlertType(service: Service): AlertType<Params, {}, {}, Action

if (!met) continue;

const agg = params.aggField ? `${params.aggType}(${params.aggField})` : `${params.aggType}`;
const humanFn = `${agg} ${params.thresholdComparator} ${params.threshold.join(',')}`;

const baseContext: BaseActionContext = {
date,
group: instanceId,
value,
function: humanFn,
};
const actionContext = addMessages(options, baseContext, params);
const alertInstance = options.services.alertInstanceFactory(instanceId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
*/
import { lazy } from 'react';
import { i18n } from '@kbn/i18n';

import { AlertTypeModel } from '../../../../types';
import { validateExpression } from './validation';
import { IndexThresholdAlertParams } from './types';
Expand All @@ -26,6 +25,12 @@ export function getAlertType(): AlertTypeModel<IndexThresholdAlertParams, Alerts
},
alertParamsExpression: lazy(() => import('./expression')),
validate: validateExpression,
defaultActionMessage: i18n.translate(
'xpack.triggersActionsUI.components.builtinAlertTypes.threshold.alertDefaultActionMessage',
{
defaultMessage: `alert \\{\\{alertName\\}\\} group \\{\\{context.group\\}\\} value \\{\\{context.value\\}\\} exceeded threshold \\{\\{context.function\\}\\} over \\{\\{params.timeWindowSize\\}\\}\\{\\{params.timeWindowUnit\\}\\} on \\{\\{context.date\\}\\}`,
}
),
requiresAppContext: false,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
ObjectRemover,
} from '../../../../../common/lib';
import { createEsDocuments } from './create_test_data';
import { getAlertType } from '../../../../../../../plugins/triggers_actions_ui/public/application/components/builtin_alert_types/threshold/';

const ALERT_TYPE_ID = '.index-threshold';
const ACTION_TYPE_ID = '.index';
Expand All @@ -26,6 +27,8 @@ const ALERT_INTERVALS_TO_WRITE = 5;
const ALERT_INTERVAL_SECONDS = 3;
const ALERT_INTERVAL_MILLIS = ALERT_INTERVAL_SECONDS * 1000;

const DefaultActionMessage = getAlertType().defaultActionMessage;

// eslint-disable-next-line import/no-default-export
export default function alertTests({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
Expand Down Expand Up @@ -62,6 +65,10 @@ export default function alertTests({ getService }: FtrProviderContext) {
await esTestIndexToolOutput.destroy();
});

it('has a default action message', () => {
expect(DefaultActionMessage).to.be.ok();
});

// The tests below create two alerts, one that will fire, one that will
// never fire; the tests ensure the ones that should fire, do fire, and
// those that shouldn't fire, do not fire.
Expand All @@ -85,17 +92,16 @@ export default function alertTests({ getService }: FtrProviderContext) {
const docs = await waitForDocs(2);
for (const doc of docs) {
const { group } = doc._source;
const { name, value, title, message } = doc._source.params;
const { name, title, message } = doc._source.params;

expect(name).to.be('always fire');
expect(group).to.be('all documents');

// we'll check title and message in this test, but not subsequent ones
expect(title).to.be('alert always fire group all documents exceeded threshold');

const expectedPrefix = `alert always fire group all documents value ${value} exceeded threshold count > -1 over`;
const messagePrefix = message.substr(0, expectedPrefix.length);
expect(messagePrefix).to.be(expectedPrefix);
const messagePattern = /alert always fire group all documents value \d+ exceeded threshold count &gt; -1 over 15s on \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/;
expect(message).to.match(messagePattern);
}
});

Expand Down Expand Up @@ -128,10 +134,13 @@ export default function alertTests({ getService }: FtrProviderContext) {

for (const doc of docs) {
const { group } = doc._source;
const { name } = doc._source.params;
const { name, message } = doc._source.params;

expect(name).to.be('always fire');
if (group === 'group-0') inGroup0++;

const messagePattern = /alert always fire group group-\d value \d+ exceeded threshold count .+ over 15s on \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/;
expect(message).to.match(messagePattern);
}

// there should be 2 docs in group-0, rando split between others
Expand Down Expand Up @@ -163,9 +172,12 @@ export default function alertTests({ getService }: FtrProviderContext) {

const docs = await waitForDocs(2);
for (const doc of docs) {
const { name } = doc._source.params;
const { name, message } = doc._source.params;

expect(name).to.be('always fire');

const messagePattern = /alert always fire group all documents value \d+ exceeded threshold sum\(testedValue\) between 0,1000000 over 15s on \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/;
expect(message).to.match(messagePattern);
}
});

Expand Down Expand Up @@ -195,9 +207,12 @@ export default function alertTests({ getService }: FtrProviderContext) {

const docs = await waitForDocs(4);
for (const doc of docs) {
const { name } = doc._source.params;
const { name, message } = doc._source.params;

expect(name).to.be('always fire');

const messagePattern = /alert always fire group all documents value .+ exceeded threshold avg\(testedValue\) .+ 0 over 15s on \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/;
expect(message).to.match(messagePattern);
}
});

Expand Down Expand Up @@ -232,10 +247,13 @@ export default function alertTests({ getService }: FtrProviderContext) {

for (const doc of docs) {
const { group } = doc._source;
const { name } = doc._source.params;
const { name, message } = doc._source.params;

expect(name).to.be('always fire');
if (group === 'group-2') inGroup2++;

const messagePattern = /alert always fire group group-. value \d+ exceeded threshold max\(testedValue\) .* 0 over 15s on \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/;
expect(message).to.match(messagePattern);
}

// there should be 2 docs in group-2, rando split between others
Expand Down Expand Up @@ -274,10 +292,13 @@ export default function alertTests({ getService }: FtrProviderContext) {

for (const doc of docs) {
const { group } = doc._source;
const { name } = doc._source.params;
const { name, message } = doc._source.params;

expect(name).to.be('always fire');
if (group === 'group-0') inGroup0++;

const messagePattern = /alert always fire group group-. value \d+ exceeded threshold min\(testedValue\) .* 0 over 15s on \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/;
expect(message).to.match(messagePattern);
}

// there should be 2 docs in group-0, rando split between others
Expand Down Expand Up @@ -329,7 +350,7 @@ export default function alertTests({ getService }: FtrProviderContext) {
name: '{{{alertName}}}',
value: '{{{context.value}}}',
title: '{{{context.title}}}',
message: '{{{context.message}}}',
message: DefaultActionMessage,
},
date: '{{{context.date}}}',
// TODO: I wanted to write the alert value here, but how?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,13 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
await find.clickByCssSelector('[data-test-subj="saveActionButtonModal"]:not(disabled)');
const createdConnectorToastTitle = await pageObjects.common.closeToast();
expect(createdConnectorToastTitle).to.eql(`Created '${slackConnectorName}'`);
const messageTextArea = await find.byCssSelector('[data-test-subj="messageTextArea"]');
expect(await messageTextArea.getAttribute('value')).to.eql(
'alert {{alertName}} group {{context.group}} value {{context.value}} exceeded threshold {{context.function}} over {{params.timeWindowSize}}{{params.timeWindowUnit}} on {{context.date}}'
);
await testSubjects.setValue('messageTextArea', 'test message ');
await testSubjects.click('messageAddVariableButton');
await testSubjects.click('variableMenuButton-0');
const messageTextArea = await find.byCssSelector('[data-test-subj="messageTextArea"]');
expect(await messageTextArea.getAttribute('value')).to.eql('test message {{alertId}}');
await messageTextArea.type(' some additional text ');

Expand Down

0 comments on commit 694c322

Please sign in to comment.