Skip to content

Commit

Permalink
[Response Ops][Alerting] Alerting event logger should not throw error…
Browse files Browse the repository at this point in the history
… when ad hoc task runner cannot load saved object (#201637)

## Summary

The ad-hoc task runner loads the `ad_hoc_run` saved object that contains
rule information when it first starts running. If the saved object
cannot be loaded due to saved object not found (likely because the SO
was deleted), the alerting event logger was throwing an error because it
didn't have the rule information to populate the `execute-backfill`
event. This PR fixes it so we're not throwing an error and writes the
`execute-backfill` event with whatever information is available.

## To Verify

1. Modify the ad-hoc task runner to load a random saved object 

```
--- a/x-pack/plugins/alerting/server/task_runner/ad_hoc_task_runner.ts
+++ b/x-pack/plugins/alerting/server/task_runner/ad_hoc_task_runner.ts
@@ -294,7 +294,8 @@ export class AdHocTaskRunner implements CancellableTask {
         const adHocRunSO: SavedObject<AdHocRunSO> =
           await this.context.encryptedSavedObjectsClient.getDecryptedAsInternalUser<AdHocRunSO>(
             AD_HOC_RUN_SAVED_OBJECT_TYPE,
-            adHocRunParamsId,
+            `abcdefgh`,
+            // adHocRunParamsId,
             { namespace }
```

2. Create a detection rule and then schedule backfill run for it. You
should see the execution fail with `Executing ad hoc run with id
\"7401d1f1-73fc-4483-acd5-edf6180028ce\" has resulted in Error: Saved
object [ad_hoc_run_params/abcdefgh] not found` but you should NOT see
any errors from task manager like `Task ad_hoc_run-backfill
"40fd4c52-411f-462c-b285-87e33520bd5b" failed: Error:
AlertingEventLogger not initialized`

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
  • Loading branch information
ymao1 and elasticmachine authored Dec 4, 2024
1 parent 2a7689e commit 6a4fe4f
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1148,6 +1148,68 @@ describe('AlertingEventLogger', () => {
expect(eventLogger.logEvent).toHaveBeenCalledWith(loggedEvent);
});

test('should set fields from backfill even when no rule data is provided', () => {
alertingEventLogger.initialize({
context: backfillContext,
runDate,
type: executionType.BACKFILL,
});

alertingEventLogger.done({
backfill: {
id: 'abc',
start: '2024-03-13T00:00:00.000Z',
interval: '1h',
},
status: {
lastExecutionDate: new Date('2022-05-05T15:59:54.480Z'),
status: 'error',
error: {
reason: RuleExecutionStatusErrorReasons.Execute,
message: 'something went wrong',
},
},
});

const event = initializeExecuteBackfillRecord(backfillContextWithScheduleDelay, [adHocRunSO]);
const loggedEvent = {
...event,
event: {
...event?.event,
outcome: 'failure',
reason: RuleExecutionStatusErrorReasons.Execute,
},
error: {
message: 'something went wrong',
},
message: 'def: execution failed',
kibana: {
...event.kibana,
alert: {
...event.kibana?.alert,
rule: {
...event.kibana?.alert?.rule,
execution: {
...event.kibana?.alert?.rule?.execution,
backfill: {
id: 'abc',
start: '2024-03-13T00:00:00.000Z',
interval: '1h',
},
},
},
},
alerting: {
outcome: 'failure',
status: 'error',
},
},
};

expect(alertingEventLogger.getEvent()).toEqual(loggedEvent);
expect(eventLogger.logEvent).toHaveBeenCalledWith(loggedEvent);
});

test('should set fields from execution metrics if provided', () => {
alertingEventLogger.initialize({ context: ruleContext, runDate, ruleData });
alertingEventLogger.done({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ export class AlertingEventLogger {
}

public done({ status, metrics, timings, backfill }: DoneOpts) {
if (!this.isInitialized || !this.event || !this.context || !this.ruleData) {
if (!this.isInitialized || !this.event || !this.context) {
throw new Error('AlertingEventLogger not initialized');
}

Expand All @@ -360,16 +360,15 @@ export class AlertingEventLogger {
updateEvent(this.event, { status: status.status });

if (status.error) {
const message = this.ruleData
? `${this.ruleData.type?.id}:${this.context.savedObjectId}: execution failed`
: `${this.context.savedObjectId}: execution failed`;
updateEvent(this.event, {
outcome: 'failure',
alertingOutcome: 'failure',
reason: status.error?.reason || 'unknown',
error: this.event?.error?.message || status.error.message,
...(this.event.message && this.event.event?.outcome === 'failure'
? {}
: {
message: `${this.ruleData.type?.id}:${this.context.savedObjectId}: execution failed`,
}),
...(this.event.message && this.event.event?.outcome === 'failure' ? {} : { message }),
});
} else {
if (status.warning) {
Expand Down

0 comments on commit 6a4fe4f

Please sign in to comment.