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] Display Action Group in Alert Details #82645

Merged
merged 12 commits into from
Nov 6, 2020
1 change: 1 addition & 0 deletions x-pack/plugins/alerts/common/alert_instance_summary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@ export interface AlertInstanceSummary {
export interface AlertInstanceStatus {
status: AlertInstanceStatusValues;
muted: boolean;
actionGroupId?: string;
activeStartDate?: string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,12 @@ describe('getAlertInstanceSummary()', () => {
.addExecute()
.addNewInstance('instance-currently-active')
.addNewInstance('instance-previously-active')
.addActiveInstance('instance-currently-active')
.addActiveInstance('instance-previously-active')
.addActiveInstance('instance-currently-active', 'action group A')
.addActiveInstance('instance-previously-active', 'action group B')
.advanceTime(10000)
.addExecute()
.addResolvedInstance('instance-previously-active')
.addActiveInstance('instance-currently-active')
.addActiveInstance('instance-currently-active', 'action group A')
.getEvents();
const eventsResult = {
...AlertInstanceSummaryFindEventsResult,
Expand All @@ -144,16 +144,19 @@ describe('getAlertInstanceSummary()', () => {
"id": "1",
"instances": Object {
"instance-currently-active": Object {
"actionGroupId": "action group A",
"activeStartDate": "2019-02-12T21:01:22.479Z",
"muted": false,
"status": "Active",
},
"instance-muted-no-activity": Object {
"actionGroupId": undefined,
"activeStartDate": undefined,
"muted": true,
"status": "OK",
},
"instance-previously-active": Object {
"actionGroupId": undefined,
"activeStartDate": undefined,
"muted": false,
"status": "OK",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,13 @@ describe('alertInstanceSummaryFromEventLog', () => {
Object {
"instances": Object {
"instance-1": Object {
"actionGroupId": undefined,
"activeStartDate": undefined,
"muted": true,
"status": "OK",
},
"instance-2": Object {
"actionGroupId": undefined,
"activeStartDate": undefined,
"muted": true,
"status": "OK",
Expand Down Expand Up @@ -184,7 +186,7 @@ describe('alertInstanceSummaryFromEventLog', () => {
const events = eventsFactory
.addExecute()
.addNewInstance('instance-1')
.addActiveInstance('instance-1')
.addActiveInstance('instance-1', 'action group A')
.advanceTime(10000)
.addExecute()
.addResolvedInstance('instance-1')
Expand All @@ -202,6 +204,7 @@ describe('alertInstanceSummaryFromEventLog', () => {
Object {
"instances": Object {
"instance-1": Object {
"actionGroupId": undefined,
"activeStartDate": undefined,
"muted": false,
"status": "OK",
Expand All @@ -218,7 +221,7 @@ describe('alertInstanceSummaryFromEventLog', () => {
const eventsFactory = new EventsFactory();
const events = eventsFactory
.addExecute()
.addActiveInstance('instance-1')
.addActiveInstance('instance-1', 'action group A')
.advanceTime(10000)
.addExecute()
.addResolvedInstance('instance-1')
Expand All @@ -236,6 +239,7 @@ describe('alertInstanceSummaryFromEventLog', () => {
Object {
"instances": Object {
"instance-1": Object {
"actionGroupId": undefined,
"activeStartDate": undefined,
"muted": false,
"status": "OK",
Expand All @@ -253,10 +257,10 @@ describe('alertInstanceSummaryFromEventLog', () => {
const events = eventsFactory
.addExecute()
.addNewInstance('instance-1')
.addActiveInstance('instance-1')
.addActiveInstance('instance-1', 'action group A')
.advanceTime(10000)
.addExecute()
.addActiveInstance('instance-1')
.addActiveInstance('instance-1', 'action group A')
.getEvents();

const summary: AlertInstanceSummary = alertInstanceSummaryFromEventLog({
Expand All @@ -271,6 +275,79 @@ describe('alertInstanceSummaryFromEventLog', () => {
Object {
"instances": Object {
"instance-1": Object {
"actionGroupId": "action group A",
"activeStartDate": "2020-06-18T00:00:00.000Z",
"muted": false,
"status": "Active",
},
},
"lastRun": "2020-06-18T00:00:10.000Z",
"status": "Active",
}
`);
});

test('alert with currently active instance with no action group in event log', async () => {
const alert = createAlert({});
const eventsFactory = new EventsFactory();
const events = eventsFactory
.addExecute()
.addNewInstance('instance-1')
.addActiveInstance('instance-1', undefined)
.advanceTime(10000)
.addExecute()
.addActiveInstance('instance-1', undefined)
.getEvents();

const summary: AlertInstanceSummary = alertInstanceSummaryFromEventLog({
alert,
events,
dateStart,
dateEnd,
});

const { lastRun, status, instances } = summary;
expect({ lastRun, status, instances }).toMatchInlineSnapshot(`
Object {
"instances": Object {
"instance-1": Object {
"actionGroupId": undefined,
"activeStartDate": "2020-06-18T00:00:00.000Z",
"muted": false,
"status": "Active",
},
},
"lastRun": "2020-06-18T00:00:10.000Z",
"status": "Active",
}
`);
});

test('alert with currently active instance that switched action groups', async () => {
const alert = createAlert({});
const eventsFactory = new EventsFactory();
const events = eventsFactory
.addExecute()
.addNewInstance('instance-1')
.addActiveInstance('instance-1', 'action group A')
.advanceTime(10000)
.addExecute()
.addActiveInstance('instance-1', 'action group B')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes me wonder what kind of events we should be generating when an instance "switches" action groups. My first thought was it should probably send a resolved-instance with the old action group, and a new-instance with the new instance group, in between these active-instance events. Which implies sending the action groups on new-instance and resolved-instance as well.

But not sure. Perhaps it would be better to leave new-instance and resolved-instance as is, and maybe have a new event active-action-group-changed or such.

I think we'll need to think about this a little bit - create a new issue? ie "what events should be logged when an alert switches action groups".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created this issue: #82792

.getEvents();

const summary: AlertInstanceSummary = alertInstanceSummaryFromEventLog({
alert,
events,
dateStart,
dateEnd,
});

const { lastRun, status, instances } = summary;
expect({ lastRun, status, instances }).toMatchInlineSnapshot(`
Object {
"instances": Object {
"instance-1": Object {
"actionGroupId": "action group B",
"activeStartDate": "2020-06-18T00:00:00.000Z",
"muted": false,
"status": "Active",
Expand All @@ -287,10 +364,10 @@ describe('alertInstanceSummaryFromEventLog', () => {
const eventsFactory = new EventsFactory();
const events = eventsFactory
.addExecute()
.addActiveInstance('instance-1')
.addActiveInstance('instance-1', 'action group A')
.advanceTime(10000)
.addExecute()
.addActiveInstance('instance-1')
.addActiveInstance('instance-1', 'action group A')
.getEvents();

const summary: AlertInstanceSummary = alertInstanceSummaryFromEventLog({
Expand All @@ -305,6 +382,7 @@ describe('alertInstanceSummaryFromEventLog', () => {
Object {
"instances": Object {
"instance-1": Object {
"actionGroupId": "action group A",
"activeStartDate": undefined,
"muted": false,
"status": "Active",
Expand All @@ -322,12 +400,12 @@ describe('alertInstanceSummaryFromEventLog', () => {
const events = eventsFactory
.addExecute()
.addNewInstance('instance-1')
.addActiveInstance('instance-1')
.addActiveInstance('instance-1', 'action group A')
.addNewInstance('instance-2')
.addActiveInstance('instance-2')
.addActiveInstance('instance-2', 'action group B')
.advanceTime(10000)
.addExecute()
.addActiveInstance('instance-1')
.addActiveInstance('instance-1', 'action group A')
.addResolvedInstance('instance-2')
.getEvents();

Expand All @@ -343,11 +421,13 @@ describe('alertInstanceSummaryFromEventLog', () => {
Object {
"instances": Object {
"instance-1": Object {
"actionGroupId": "action group A",
"activeStartDate": "2020-06-18T00:00:00.000Z",
"muted": true,
"status": "Active",
},
"instance-2": Object {
"actionGroupId": undefined,
"activeStartDate": undefined,
"muted": true,
"status": "OK",
Expand All @@ -365,19 +445,19 @@ describe('alertInstanceSummaryFromEventLog', () => {
const events = eventsFactory
.addExecute()
.addNewInstance('instance-1')
.addActiveInstance('instance-1')
.addActiveInstance('instance-1', 'action group A')
.addNewInstance('instance-2')
.addActiveInstance('instance-2')
.addActiveInstance('instance-2', 'action group B')
.advanceTime(10000)
.addExecute()
.addActiveInstance('instance-1')
.addActiveInstance('instance-1', 'action group A')
.addResolvedInstance('instance-2')
.advanceTime(10000)
.addExecute()
.addActiveInstance('instance-1')
.addActiveInstance('instance-1', 'action group B')
.advanceTime(10000)
.addExecute()
.addActiveInstance('instance-1')
.addActiveInstance('instance-1', 'action group B')
.getEvents();

const summary: AlertInstanceSummary = alertInstanceSummaryFromEventLog({
Expand All @@ -392,11 +472,13 @@ describe('alertInstanceSummaryFromEventLog', () => {
Object {
"instances": Object {
"instance-1": Object {
"actionGroupId": "action group B",
"activeStartDate": "2020-06-18T00:00:00.000Z",
"muted": false,
"status": "Active",
},
"instance-2": Object {
"actionGroupId": undefined,
"activeStartDate": undefined,
"muted": false,
"status": "OK",
Expand Down Expand Up @@ -452,14 +534,17 @@ export class EventsFactory {
return this;
}

addActiveInstance(instanceId: string): EventsFactory {
addActiveInstance(instanceId: string, actionGroupId: string | undefined): EventsFactory {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When might an action not have an action group? 🤔
Just wondering if we need the undefined here...

Or is this for when we resolve?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the undefined in order to support the test 'alert with currently active instance with no action group in event log', which ensures we can handle event log entries from prior to this PR which won't have the action_group_id field.

const kibanaAlerting = actionGroupId
? { instance_id: instanceId, action_group_id: actionGroupId }
: { instance_id: instanceId };
this.events.push({
'@timestamp': this.date,
event: {
provider: EVENT_LOG_PROVIDER,
action: EVENT_LOG_ACTIONS.activeInstance,
},
kibana: { alerting: { instance_id: instanceId } },
kibana: { alerting: kibanaAlerting },
});
return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,12 @@ export function alertInstanceSummaryFromEventLog(
// intentionally no break here
case EVENT_LOG_ACTIONS.activeInstance:
status.status = 'Active';
status.actionGroupId = event?.kibana?.alerting?.action_group_id;
break;
case EVENT_LOG_ACTIONS.resolvedInstance:
status.status = 'OK';
status.activeStartDate = undefined;
status.actionGroupId = undefined;
}
}

Expand Down Expand Up @@ -118,6 +120,7 @@ function getAlertInstanceStatus(
const status: AlertInstanceStatus = {
status: 'OK',
muted: false,
actionGroupId: undefined,
activeStartDate: undefined,
};
instances.set(instanceId, status);
Expand Down
11 changes: 8 additions & 3 deletions x-pack/plugins/alerts/server/task_runner/task_runner.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ describe('Task Runner', () => {
kibana: {
alerting: {
instance_id: '1',
action_group_id: 'default',
},
saved_objects: [
{
Expand All @@ -302,7 +303,7 @@ describe('Task Runner', () => {
},
],
},
message: "test:1: 'alert-name' active instance: '1'",
message: "test:1: 'alert-name' active instance: '1' in actionGroup: 'default'",
});
expect(eventLogger.logEvent).toHaveBeenCalledWith({
event: {
Expand Down Expand Up @@ -424,6 +425,7 @@ describe('Task Runner', () => {
},
"kibana": Object {
"alerting": Object {
"action_group_id": undefined,
"instance_id": "1",
},
"saved_objects": Array [
Expand All @@ -445,6 +447,7 @@ describe('Task Runner', () => {
},
"kibana": Object {
"alerting": Object {
"action_group_id": "default",
"instance_id": "1",
},
"saved_objects": Array [
Expand All @@ -456,7 +459,7 @@ describe('Task Runner', () => {
},
],
},
"message": "test:1: 'alert-name' active instance: '1'",
"message": "test:1: 'alert-name' active instance: '1' in actionGroup: 'default'",
},
],
Array [
Expand Down Expand Up @@ -565,6 +568,7 @@ describe('Task Runner', () => {
},
"kibana": Object {
"alerting": Object {
"action_group_id": undefined,
"instance_id": "2",
},
"saved_objects": Array [
Expand All @@ -586,6 +590,7 @@ describe('Task Runner', () => {
},
"kibana": Object {
"alerting": Object {
"action_group_id": "default",
"instance_id": "1",
},
"saved_objects": Array [
Expand All @@ -597,7 +602,7 @@ describe('Task Runner', () => {
},
],
},
"message": "test:1: 'alert-name' active instance: '1'",
"message": "test:1: 'alert-name' active instance: '1' in actionGroup: 'default'",
},
],
]
Expand Down
Loading