Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Alerting] add more alert properties to action parameter templating #59718

Merged
merged 3 commits into from
Mar 10, 2020
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions x-pack/plugins/alerting/README.md
Original file line number Diff line number Diff line change
@@ -388,7 +388,15 @@ This factory returns an instance of `AlertInstance`. The alert instance class ha

There needs to be a way to map alert context into action parameters. For this, we started off by adding template support. Any string within the `params` of an alert saved object's `actions` will be processed as a template and can inject context or state values.

When an alert instance executes, the first argument is the `group` of actions to execute and the second is the context the alert exposes to templates. We iterate through each action params attributes recursively and render templates if they are a string. Templates have access to the `context` (provided by second argument of `.scheduleActions(...)` on an alert instance) and the alert instance's `state` (provided by the most recent `replaceState` call on an alert instance) as well as `alertId` and `alertInstanceId`.
When an alert instance executes, the first argument is the `group` of actions to execute and the second is the context the alert exposes to templates. We iterate through each action params attributes recursively and render templates if they are a string. Templates have access to the following "variables":

- `context` - provided by second argument of `.scheduleActions(...)` on an alert instance
- `state` - the alert instance's `state` provided by the most recent `replaceState` call on an alert instance
- `alertId` - the id of the alert
- `alertInstanceId` - the alert instance id
- `alertName` - the name of the alert
- `spaceId` - the id of the space the alert exists in
- `tags` - the tags set in the alert

## Examples

@@ -410,6 +418,7 @@ Below is an example of an alert that takes advantage of templating:
{
...
id: "123",
name: "cpu alert",
actions: [
{
"group": "default",
@@ -418,7 +427,7 @@ Below is an example of an alert that takes advantage of templating:
"from": "example@elastic.co",
"to": ["destination@elastic.co"],
"subject": "A notification about {{context.server}}"
"body": "The server {{context.server}} has a CPU usage of {{state.cpuUsage}}%. This message for {{alertInstanceId}} was created by the alert {{alertId}}."
"body": "The server {{context.server}} has a CPU usage of {{state.cpuUsage}}%. This message for {{alertInstanceId}} was created by the alert {{alertId}} {{alertName}}."
}
}
]
@@ -432,7 +441,7 @@ The templating system will take the alert and alert type as described above and
"from": "example@elastic.co",
"to": ["destination@elastic.co"],
"subject": "A notification about server_1"
"body": "The server server_1 has a CPU usage of 80%. This message for server_1 was created by the alert 123"
"body": "The server server_1 has a CPU usage of 80%. This message for server_1 was created by the alert 123 cpu alert"
}
```

Original file line number Diff line number Diff line change
@@ -23,6 +23,8 @@ const createExecutionHandlerParams = {
executeAction: jest.fn(),
spaceId: 'default',
alertId: '1',
alertName: 'name-of-alert',
tags: ['tag-A', 'tag-B'],
apiKey: 'MTIzOmFiYw==',
spaceIdToNamespace: jest.fn().mockReturnValue(undefined),
getBasePath: jest.fn().mockReturnValue(undefined),
@@ -37,6 +39,7 @@ const createExecutionHandlerParams = {
foo: true,
contextVal: 'My {{context.value}} goes here',
stateVal: 'My {{state.value}} goes here',
alertVal: 'My {{alertId}} {{alertName}} {{spaceId}} {{tags}} {{alertInstanceId}} goes here',
},
},
],
@@ -59,6 +62,7 @@ test('calls executeAction per selected action', async () => {
"apiKey": "MTIzOmFiYw==",
"id": "1",
"params": Object {
"alertVal": "My 1 name-of-alert default tag-A,tag-B 2 goes here",
"contextVal": "My goes here",
"foo": true,
"stateVal": "My goes here",
@@ -95,6 +99,7 @@ test('context attribute gets parameterized', async () => {
"apiKey": "MTIzOmFiYw==",
"id": "1",
"params": Object {
"alertVal": "My 1 name-of-alert default tag-A,tag-B 2 goes here",
"contextVal": "My context-val goes here",
"foo": true,
"stateVal": "My goes here",
@@ -120,6 +125,7 @@ test('state attribute gets parameterized', async () => {
"apiKey": "MTIzOmFiYw==",
"id": "1",
"params": Object {
"alertVal": "My 1 name-of-alert default tag-A,tag-B 2 goes here",
"contextVal": "My goes here",
"foo": true,
"stateVal": "My state-val goes here",
Original file line number Diff line number Diff line change
@@ -12,6 +12,8 @@ import { PluginStartContract as ActionsPluginStartContract } from '../../../../p

interface CreateExecutionHandlerOptions {
alertId: string;
alertName: string;
tags?: string[];
executeAction: ActionsPluginStartContract['execute'];
actions: AlertAction[];
spaceId: string;
@@ -30,6 +32,8 @@ interface ExecutionHandlerOptions {
export function createExecutionHandler({
logger,
alertId,
alertName,
tags,
executeAction,
actions: alertActions,
spaceId,
@@ -49,9 +53,12 @@ export function createExecutionHandler({
...action,
params: transformActionParams({
alertId,
alertName,
spaceId,
tags,
alertInstanceId,
context,
params: action.params,
actionParams: action.params,
state,
}),
};
8 changes: 7 additions & 1 deletion x-pack/plugins/alerting/server/task_runner/task_runner.ts
Original file line number Diff line number Diff line change
@@ -93,8 +93,10 @@ export class TaskRunner {
return this.context.getServices(fakeRequest);
}

getExecutionHandler(
private getExecutionHandler(
alertId: string,
alertName: string,
tags: string[] | undefined,
spaceId: string,
apiKey: string | null,
actions: RawAlert['actions'],
@@ -114,6 +116,8 @@ export class TaskRunner {

return createExecutionHandler({
alertId,
alertName,
tags,
logger: this.logger,
executeAction: this.context.executeAction,
apiKey,
@@ -225,6 +229,8 @@ export class TaskRunner {
const params = validateAlertTypeParams(this.alertType, attributes.params);
const executionHandler = this.getExecutionHandler(
alertId,
attributes.name,
attributes.tags,
spaceId,
apiKey,
attributes.actions,
Loading