Skip to content

Commit

Permalink
[Alerting] write event log entries for alert execution and it's actio…
Browse files Browse the repository at this point in the history
…ns (#61706)

resolves #55636

Writes eventLog events for alert executions, and the actions executed from
that alert execution.
  • Loading branch information
pmuellr authored Apr 6, 2020
1 parent 5003179 commit 113181b
Show file tree
Hide file tree
Showing 12 changed files with 382 additions and 28 deletions.
2 changes: 1 addition & 1 deletion x-pack/plugins/alerting/kibana.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
"version": "8.0.0",
"kibanaVersion": "kibana",
"configPath": ["xpack", "alerting"],
"requiredPlugins": ["licensing", "taskManager", "encryptedSavedObjects", "actions"],
"requiredPlugins": ["licensing", "taskManager", "encryptedSavedObjects", "actions", "eventLog"],
"optionalPlugins": ["usageCollection", "spaces", "security"]
}
4 changes: 4 additions & 0 deletions x-pack/plugins/alerting/server/plugin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { coreMock } from '../../../../src/core/server/mocks';
import { licensingMock } from '../../../plugins/licensing/server/mocks';
import { encryptedSavedObjectsMock } from '../../../plugins/encrypted_saved_objects/server/mocks';
import { taskManagerMock } from '../../task_manager/server/mocks';
import { eventLogServiceMock } from '../../event_log/server/event_log_service.mock';

describe('Alerting Plugin', () => {
describe('setup()', () => {
Expand All @@ -30,6 +31,7 @@ describe('Alerting Plugin', () => {
licensing: licensingMock.createSetup(),
encryptedSavedObjects: encryptedSavedObjectsSetup,
taskManager: taskManagerMock.createSetup(),
eventLog: eventLogServiceMock.create(),
} as any
);

Expand Down Expand Up @@ -67,6 +69,7 @@ describe('Alerting Plugin', () => {
licensing: licensingMock.createSetup(),
encryptedSavedObjects: encryptedSavedObjectsSetup,
taskManager: taskManagerMock.createSetup(),
eventLog: eventLogServiceMock.create(),
} as any
);

Expand Down Expand Up @@ -109,6 +112,7 @@ describe('Alerting Plugin', () => {
licensing: licensingMock.createSetup(),
encryptedSavedObjects: encryptedSavedObjectsSetup,
taskManager: taskManagerMock.createSetup(),
eventLog: eventLogServiceMock.create(),
} as any
);

Expand Down
17 changes: 17 additions & 0 deletions x-pack/plugins/alerting/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,15 @@ import {
import { Services } from './types';
import { registerAlertsUsageCollector } from './usage';
import { initializeAlertingTelemetry, scheduleAlertingTelemetry } from './usage/task';
import { IEventLogger, IEventLogService } from '../../event_log/server';

const EVENT_LOG_PROVIDER = 'alerting';
export const EVENT_LOG_ACTIONS = {
execute: 'execute',
executeAction: 'execute-action',
newInstance: 'new-instance',
resolvedInstance: 'resolved-instance',
};

export interface PluginSetupContract {
registerType: AlertTypeRegistry['register'];
Expand All @@ -73,6 +82,7 @@ export interface AlertingPluginsSetup {
licensing: LicensingPluginSetup;
spaces?: SpacesPluginSetup;
usageCollection?: UsageCollectionSetup;
eventLog: IEventLogService;
}
export interface AlertingPluginsStart {
actions: ActionsPluginStartContract;
Expand All @@ -93,6 +103,7 @@ export class AlertingPlugin {
private readonly alertsClientFactory: AlertsClientFactory;
private readonly telemetryLogger: Logger;
private readonly kibanaIndex: Promise<string>;
private eventLogger?: IEventLogger;

constructor(initializerContext: PluginInitializerContext) {
this.logger = initializerContext.logger.get('plugins', 'alerting');
Expand Down Expand Up @@ -133,6 +144,11 @@ export class AlertingPlugin {
]),
});

plugins.eventLog.registerProviderActions(EVENT_LOG_PROVIDER, Object.values(EVENT_LOG_ACTIONS));
this.eventLogger = plugins.eventLog.getLogger({
event: { provider: EVENT_LOG_PROVIDER },
});

const alertTypeRegistry = new AlertTypeRegistry({
taskManager: plugins.taskManager,
taskRunnerFactory: this.taskRunnerFactory,
Expand Down Expand Up @@ -211,6 +227,7 @@ export class AlertingPlugin {
actionsPlugin: plugins.actions,
encryptedSavedObjectsPlugin: plugins.encryptedSavedObjects,
getBasePath: this.getBasePath,
eventLogger: this.eventLogger!,
});

scheduleAlertingTelemetry(this.telemetryLogger, plugins.taskManager);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { AlertType } from '../types';
import { createExecutionHandler } from './create_execution_handler';
import { loggingServiceMock } from '../../../../../src/core/server/mocks';
import { actionsMock } from '../../../actions/server/mocks';
import { eventLoggerMock } from '../../../event_log/server/event_logger.mock';

const alertType: AlertType = {
id: 'test',
Expand All @@ -31,6 +32,7 @@ const createExecutionHandlerParams = {
getBasePath: jest.fn().mockReturnValue(undefined),
alertType,
logger: loggingServiceMock.create().get(),
eventLogger: eventLoggerMock.create(),
actions: [
{
id: '1',
Expand Down Expand Up @@ -75,6 +77,37 @@ test('calls actionsPlugin.execute per selected action', async () => {
},
]
`);

const eventLogger = createExecutionHandlerParams.eventLogger;
expect(eventLogger.logEvent).toHaveBeenCalledTimes(1);
expect(eventLogger.logEvent.mock.calls).toMatchInlineSnapshot(`
Array [
Array [
Object {
"event": Object {
"action": "execute-action",
},
"kibana": Object {
"alerting": Object {
"instance_id": "2",
},
"namespace": "default",
"saved_objects": Array [
Object {
"id": "1",
"type": "alert",
},
Object {
"id": "1",
"type": "action",
},
],
},
"message": "alert: test:1: 'name-of-alert' instanceId: '2' scheduled actionGroup: 'default' action: test:1",
},
],
]
`);
});

test(`doesn't call actionsPlugin.execute for disabled actionTypes`, async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { AlertAction, State, Context, AlertType } from '../types';
import { Logger } from '../../../../../src/core/server';
import { transformActionParams } from './transform_action_params';
import { PluginStartContract as ActionsPluginStartContract } from '../../../../plugins/actions/server';
import { IEventLogger, IEvent } from '../../../event_log/server';
import { EVENT_LOG_ACTIONS } from '../plugin';

interface CreateExecutionHandlerOptions {
alertId: string;
Expand All @@ -20,6 +22,7 @@ interface CreateExecutionHandlerOptions {
apiKey: string | null;
alertType: AlertType;
logger: Logger;
eventLogger: IEventLogger;
}

interface ExecutionHandlerOptions {
Expand All @@ -39,6 +42,7 @@ export function createExecutionHandler({
spaceId,
apiKey,
alertType,
eventLogger,
}: CreateExecutionHandlerOptions) {
const alertTypeActionGroups = new Set(pluck(alertType.actionGroups, 'id'));
return async ({ actionGroup, context, state, alertInstanceId }: ExecutionHandlerOptions) => {
Expand All @@ -63,19 +67,42 @@ export function createExecutionHandler({
}),
};
});

const alertLabel = `${alertType.id}:${alertId}: '${alertName}'`;

for (const action of actions) {
if (actionsPlugin.isActionTypeEnabled(action.actionTypeId)) {
await actionsPlugin.execute({
id: action.id,
params: action.params,
spaceId,
apiKey,
});
} else {
if (!actionsPlugin.isActionTypeEnabled(action.actionTypeId)) {
logger.warn(
`Alert "${alertId}" skipped scheduling action "${action.id}" because it is disabled`
);
continue;
}

// TODO would be nice to add the action name here, but it's not available
const actionLabel = `${action.actionTypeId}:${action.id}`;
await actionsPlugin.execute({
id: action.id,
params: action.params,
spaceId,
apiKey,
});

const event: IEvent = {
event: { action: EVENT_LOG_ACTIONS.executeAction },
kibana: {
alerting: {
instance_id: alertInstanceId,
},
namespace: spaceId,
saved_objects: [
{ type: 'alert', id: alertId },
{ type: 'action', id: action.id },
],
},
};

event.message = `alert: ${alertLabel} instanceId: '${alertInstanceId}' scheduled actionGroup: '${actionGroup}' action: ${actionLabel}`;
eventLogger.logEvent(event);
}
};
}
Loading

0 comments on commit 113181b

Please sign in to comment.