Skip to content

Commit

Permalink
[Alerting] extend Alert Type with names/descriptions of action variables
Browse files Browse the repository at this point in the history
resolves elastic#58529

This PR extends alertType with an `actionVariables` property, which
should be an object with optionial properties `context` and `state`.
These properties should be typed as optional `Record<string, string>`
values.  The keys are the names of the relevant action variables,
and the values are the localized descriptions of the variables.
  • Loading branch information
pmuellr committed Mar 10, 2020
1 parent 3f365a8 commit cb6cc19
Show file tree
Hide file tree
Showing 7 changed files with 143 additions and 1 deletion.
4 changes: 4 additions & 0 deletions x-pack/plugins/alerting/server/alert_type_registry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,10 @@ describe('list()', () => {
"name": "Test Action Group",
},
],
"actionVariables": Object {
"context": Object {},
"state": Object {},
},
"defaultActionGroupId": "testActionGroup",
"id": "test",
"name": "Test",
Expand Down
8 changes: 8 additions & 0 deletions x-pack/plugins/alerting/server/alert_type_registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ export class AlertTypeRegistry {
name: alertType.name,
actionGroups: alertType.actionGroups,
defaultActionGroupId: alertType.defaultActionGroupId,
actionVariables: normalizedActionVariables(alertType.actionVariables),
}));
}
}

function normalizedActionVariables(actionVariables: any) {
return {
context: actionVariables?.context ?? {},
state: actionVariables?.state ?? {},
};
}
4 changes: 4 additions & 0 deletions x-pack/plugins/alerting/server/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ export interface AlertType {
actionGroups: ActionGroup[];
defaultActionGroupId: ActionGroup['id'];
executor: ({ services, params, state }: AlertExecutorOptions) => Promise<State | void>;
actionVariables?: {
context?: Record<string, string>;
state?: Record<string, string>;
};
}

export interface RawAlertAction extends SavedObjectAttributes {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,21 @@ describe('alertType', () => {
expect(alertType.id).toBe('.index-threshold');
expect(alertType.name).toBe('Index Threshold');
expect(alertType.actionGroups).toEqual([{ id: 'threshold met', name: 'Threshold Met' }]);

const actionVariables = {
context: alertType.actionVariables?.context,
state: alertType.actionVariables?.state,
};
expect(actionVariables).toMatchInlineSnapshot(`
Object {
"context": Object {
"date": "The date the alert exceeded the threshold.",
"group": "The group that exceeded the threshold.",
"value": "The value that exceeded the threshold.",
},
"state": undefined,
}
`);
});

it('validator succeeds with valid params', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,27 @@ export function getAlertType(service: Service): AlertType {
}
);

const actionVariableContextGroupLabel = i18n.translate(
'xpack.alertingBuiltins.indexThreshold.actionVariableContextGroupLabel',
{
defaultMessage: 'The group that exceeded the threshold.',
}
);

const actionVariableContextDateLabel = i18n.translate(
'xpack.alertingBuiltins.indexThreshold.actionVariableContextDateLabel',
{
defaultMessage: 'The date the alert exceeded the threshold.',
}
);

const actionVariableContextValueLabel = i18n.translate(
'xpack.alertingBuiltins.indexThreshold.actionVariableContextValueLabel',
{
defaultMessage: 'The value that exceeded the threshold.',
}
);

return {
id: ID,
name: alertTypeName,
Expand All @@ -40,6 +61,13 @@ export function getAlertType(service: Service): AlertType {
validate: {
params: ParamsSchema,
},
actionVariables: {
context: {
group: actionVariableContextGroupLabel,
date: actionVariableContextDateLabel,
value: actionVariableContextValueLabel,
},
},
executor,
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,14 @@ export default function(kibana: any) {
{ id: 'other', name: 'Other' },
],
defaultActionGroupId: 'default',
actionVariables: {
state: {
instanceStateValue: 'the instance state value',
},
context: {
instanceContextValue: 'the instance context value',
},
},
async executor(alertExecutorOptions: AlertExecutorOptions) {
const {
services,
Expand Down Expand Up @@ -419,13 +427,35 @@ export default function(kibana: any) {
defaultActionGroupId: 'default',
async executor({ services, params, state }: AlertExecutorOptions) {},
};
const onlyContextVariablesAlertType: AlertType = {
id: 'test.onlyContextVariables',
name: 'Test: Only Context Variables',
actionGroups: [{ id: 'default', name: 'Default' }],
defaultActionGroupId: 'default',
actionVariables: {
context: { aContextVariable: 'this is a context variable' },
},
async executor(opts: AlertExecutorOptions) {},
};
const onlyStateVariablesAlertType: AlertType = {
id: 'test.onlyStateVariables',
name: 'Test: Only State Variables',
actionGroups: [{ id: 'default', name: 'Default' }],
defaultActionGroupId: 'default',
actionVariables: {
state: { aStateVariable: 'this is a state variable' },
},
async executor(opts: AlertExecutorOptions) {},
};
server.newPlatform.setup.plugins.alerting.registerType(alwaysFiringAlertType);
server.newPlatform.setup.plugins.alerting.registerType(cumulativeFiringAlertType);
server.newPlatform.setup.plugins.alerting.registerType(neverFiringAlertType);
server.newPlatform.setup.plugins.alerting.registerType(failingAlertType);
server.newPlatform.setup.plugins.alerting.registerType(validationAlertType);
server.newPlatform.setup.plugins.alerting.registerType(authorizationAlertType);
server.newPlatform.setup.plugins.alerting.registerType(noopAlertType);
server.newPlatform.setup.plugins.alerting.registerType(onlyContextVariablesAlertType);
server.newPlatform.setup.plugins.alerting.registerType(onlyStateVariablesAlertType);
},
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,67 @@ export default function listAlertTypes({ getService }: FtrProviderContext) {
describe('list_alert_types', () => {
it('should return 200 with list of alert types', async () => {
const response = await supertest.get(`${getUrlPrefix(Spaces.space1.id)}/api/alert/types`);

expect(response.statusCode).to.eql(200);
const fixtureAlertType = response.body.find((alertType: any) => alertType.id === 'test.noop');
expect(fixtureAlertType).to.eql({
actionGroups: [{ id: 'default', name: 'Default' }],
defaultActionGroupId: 'default',
id: 'test.noop',
name: 'Test: Noop',
actionVariables: {
state: {},
context: {},
},
});
});

it('should return actionVariables with both context and state', async () => {
const response = await supertest.get(`${getUrlPrefix(Spaces.space1.id)}/api/alert/types`);
expect(response.statusCode).to.eql(200);

const fixtureAlertType = response.body.find(
(alertType: any) => alertType.id === 'test.always-firing'
);

expect(fixtureAlertType.actionVariables).to.eql({
state: {
instanceStateValue: 'the instance state value',
},
context: {
instanceContextValue: 'the instance context value',
},
});
});

it('should return actionVariables with just context', async () => {
const response = await supertest.get(`${getUrlPrefix(Spaces.space1.id)}/api/alert/types`);
expect(response.statusCode).to.eql(200);

const fixtureAlertType = response.body.find(
(alertType: any) => alertType.id === 'test.onlyContextVariables'
);

expect(fixtureAlertType.actionVariables).to.eql({
state: {},
context: {
aContextVariable: 'this is a context variable',
},
});
});

it('should return actionVariables with just state', async () => {
const response = await supertest.get(`${getUrlPrefix(Spaces.space1.id)}/api/alert/types`);
expect(response.statusCode).to.eql(200);

const fixtureAlertType = response.body.find(
(alertType: any) => alertType.id === 'test.onlyStateVariables'
);

expect(fixtureAlertType.actionVariables).to.eql({
state: {
aStateVariable: 'this is a state variable',
},
context: {},
});
});
});
Expand Down

0 comments on commit cb6cc19

Please sign in to comment.