Skip to content

Commit

Permalink
Only loading maintenance windows if there are new alerts to persist
Browse files Browse the repository at this point in the history
  • Loading branch information
ymao1 committed Sep 12, 2024
1 parent 850cdf0 commit a544490
Show file tree
Hide file tree
Showing 29 changed files with 808 additions and 564 deletions.
2 changes: 0 additions & 2 deletions x-pack/plugins/alerting/server/alert/create_alert_factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,6 @@ export function createAlertFactory<
autoRecoverAlerts,
// flappingSettings.enabled is false, as we only want to use this function to get the recovered alerts
flappingSettings: DISABLE_FLAPPING_SETTINGS,
// no maintenance window IDs are passed as we only want to use this function to get recovered alerts
maintenanceWindowIds: [],
});
return Object.keys(currentRecoveredAlerts ?? {}).map(
(alertId: string) => currentRecoveredAlerts[alertId]
Expand Down
148 changes: 115 additions & 33 deletions x-pack/plugins/alerting/server/alerts_client/alerts_client.test.ts

Large diffs are not rendered by default.

75 changes: 37 additions & 38 deletions x-pack/plugins/alerting/server/alerts_client/alerts_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ import type { AlertRule, LogAlertsOpts, ProcessAlertsOpts, SearchResult } from '
import {
IAlertsClient,
InitializeExecutionOpts,
ProcessAndLogAlertsOpts,
TrackedAlerts,
ReportedAlert,
ReportedAlertData,
Expand All @@ -62,11 +61,10 @@ import {
} from './lib';
import { isValidAlertIndexName } from '../alerts_service';
import { resolveAlertConflicts } from './lib/alert_conflict_resolver';
import { MaintenanceWindow } from '../application/maintenance_window/types';
import {
filterMaintenanceWindows,
filterMaintenanceWindowsIds,
} from '../task_runner/get_maintenance_windows';
} from '../task_runner/maintenance_windows';

// Term queries can take up to 10,000 terms
const CHUNK_SIZE = 10000;
Expand All @@ -77,6 +75,10 @@ export interface AlertsClientParams extends CreateAlertsClientParams {
dataStreamAdapter: DataStreamAdapter;
}

interface AlertsAffectedByMaintenanceWindows {
alertIds: string[];
maintenanceWindowIds: string[];
}
export class AlertsClient<
AlertData extends RuleAlertData,
LegacyState extends AlertInstanceState,
Expand Down Expand Up @@ -121,7 +123,11 @@ export class AlertsClient<
LegacyContext,
ActionGroupIds,
RecoveryActionGroupId
>({ logger: this.options.logger, ruleType: this.options.ruleType });
>({
logger: this.options.logger,
maintenanceWindowsService: this.options.maintenanceWindowsService,
ruleType: this.options.ruleType,
});
this.indexTemplateAndPattern = getIndexTemplateAndPattern({
context: this.options.ruleType.alerts?.context!,
namespace: this.options.ruleType.alerts?.isSpaceAware
Expand Down Expand Up @@ -301,45 +307,25 @@ export class AlertsClient<
return this.legacyAlertsClient.checkLimitUsage();
}

public processAlerts(opts: ProcessAlertsOpts) {
this.legacyAlertsClient.processAlerts(opts);
public async processAlerts(opts: ProcessAlertsOpts) {
await this.legacyAlertsClient.processAlerts(opts);
}

public logAlerts(opts: LogAlertsOpts) {
this.legacyAlertsClient.logAlerts(opts);
}

public processAndLogAlerts(opts: ProcessAndLogAlertsOpts) {
this.legacyAlertsClient.processAndLogAlerts(opts);
}

public getProcessedAlerts(
type: 'new' | 'active' | 'activeCurrent' | 'recovered' | 'recoveredCurrent'
) {
return this.legacyAlertsClient.getProcessedAlerts(type);
}

public async persistAlerts(maintenanceWindows?: MaintenanceWindow[]): Promise<{
alertIds: string[];
maintenanceWindowIds: string[];
} | null> {
public async persistAlerts(): Promise<AlertsAffectedByMaintenanceWindows> {
// Persist alerts first
await this.persistAlertsHelper();
const didWriteAlerts = await this.persistAlertsHelper();

// Try to update the persisted alerts with maintenance windows with a scoped query
let updateAlertsMaintenanceWindowResult = null;
try {
updateAlertsMaintenanceWindowResult = await this.updateAlertsMaintenanceWindowIdByScopedQuery(
maintenanceWindows ?? []
);
} catch (e) {
this.options.logger.debug(
`Failed to update alert matched by maintenance window scoped query ${this.ruleInfoMessage}`,
this.logTags
);
}

return updateAlertsMaintenanceWindowResult;
return await this.updatePersistedAlertsWithMaintenanceWindowIds(didWriteAlerts);
}

public getAlertsToSerialize() {
Expand Down Expand Up @@ -418,7 +404,7 @@ export class AlertsClient<
`Resources registered and installed for ${this.ruleType.alerts?.context} context but "shouldWrite" is set to false ${this.ruleInfoMessage}.`,
this.logTags
);
return;
return false;
}
const currentTime = this.startedAtString ?? new Date().toISOString();
const esClient = await this.options.elasticsearchClientPromise;
Expand Down Expand Up @@ -623,6 +609,8 @@ export class AlertsClient<
},
};
}

return alertsToIndex.length > 0;
}

private async getMaintenanceWindowScopedQueryAlerts({
Expand Down Expand Up @@ -692,18 +680,31 @@ export class AlertsClient<
}
}

private async updateAlertsMaintenanceWindowIdByScopedQuery(
maintenanceWindows: MaintenanceWindow[]
) {
private async updatePersistedAlertsWithMaintenanceWindowIds(
didWriteAlerts: boolean
): Promise<AlertsAffectedByMaintenanceWindows> {
// check if there are any new alerts
const newAlerts = Object.values(this.legacyAlertsClient.getProcessedAlerts('new'));

// return if there are no new alerts written because we only check new alerts against maintenance window filters
if (!didWriteAlerts || newAlerts.length === 0 || !this.options.maintenanceWindowsService) {
return {
alertIds: [],
maintenanceWindowIds: [],
};
}

const { maintenanceWindows } =
await this.options.maintenanceWindowsService.loadMaintenanceWindows();

const maintenanceWindowsWithScopedQuery = filterMaintenanceWindows({
maintenanceWindows,
maintenanceWindows: maintenanceWindows ?? [],
withScopedQuery: true,
});
const maintenanceWindowsWithoutScopedQueryIds = filterMaintenanceWindowsIds({
maintenanceWindows,
maintenanceWindows: maintenanceWindows ?? [],
withScopedQuery: false,
});

if (maintenanceWindowsWithScopedQuery.length === 0) {
return {
alertIds: [],
Expand All @@ -723,8 +724,6 @@ export class AlertsClient<
const alertsAffectedByScopedQuery: string[] = [];
const appliedMaintenanceWindowIds: string[] = [];

const newAlerts = Object.values(this.getProcessedAlerts('new'));

for (const [scopedQueryMaintenanceWindowId, alertIds] of Object.entries(aggsResult)) {
// Go through matched alerts, find the in memory object
alertIds.forEach((alertId) => {
Expand Down
Loading

0 comments on commit a544490

Please sign in to comment.