Skip to content

Commit c3f3395

Browse files
committed
fix: fill out missing group-by alert histories
1 parent 2119ef2 commit c3f3395

File tree

1 file changed

+49
-2
lines changed
  • packages/api/src/tasks/checkAlerts

1 file changed

+49
-2
lines changed

packages/api/src/tasks/checkAlerts/index.ts

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,26 @@ const fireChannelEvent = async ({
150150
});
151151
};
152152

153+
/**
154+
* Compute a composite map key for tracking alert history per group.
155+
* For non-grouped alerts, returns just the alert ID.
156+
* For grouped alerts, returns "alertId:groupKey" to track per-group state.
157+
*/
158+
const computeHistoryMapKey = (alertId: string, groupKey: string): string => {
159+
return groupKey ? `${alertId}:${groupKey}` : alertId;
160+
};
161+
162+
/**
163+
* Extract the group key from a composite history map key.
164+
* Handles group names that may contain colons by removing the alertId prefix.
165+
*/
166+
const extractGroupKeyFromMapKey = (mapKey: string, alertId: string): string => {
167+
const alertIdPrefix = `${alertId}:`;
168+
return mapKey.startsWith(alertIdPrefix)
169+
? mapKey.substring(alertIdPrefix.length)
170+
: '';
171+
};
172+
153173
export const processAlert = async (
154174
now: Date,
155175
details: AlertDetails,
@@ -400,7 +420,34 @@ export const processAlert = async (
400420
}
401421

402422
// Handle missing groups: If current check found no data, check if any previously alerting groups need to be resolved
403-
// TODO: Should we 'treat missing data as breaching'?
423+
// For group-by alerts, check if any previously alerting groups are missing from current data
424+
if (hasGroupBy && previousMap && previousMap.size > 0) {
425+
for (const [previousKey, previousHistory] of previousMap.entries()) {
426+
const groupKey = extractGroupKeyFromMapKey(previousKey, alert.id);
427+
428+
// If this group was previously ALERT but is missing from current data, create an OK history
429+
if (
430+
previousHistory.state === AlertState.ALERT &&
431+
!histories.has(groupKey)
432+
) {
433+
logger.info({
434+
message: `Group "${groupKey}" is missing from current data but was previously alerting - creating OK history`,
435+
alertId: alert.id,
436+
group: groupKey,
437+
});
438+
histories.set(groupKey, {
439+
alert: new mongoose.Types.ObjectId(alert.id),
440+
createdAt: nowInMinsRoundDown,
441+
state: AlertState.OK,
442+
counts: 0,
443+
lastValues: [],
444+
group: groupKey || undefined,
445+
});
446+
}
447+
}
448+
}
449+
450+
// If no histories exist at all (no current data and no previous alerting groups), create a default OK history
404451
if (histories.size === 0) {
405452
histories.set('', {
406453
alert: new mongoose.Types.ObjectId(alert.id),
@@ -414,7 +461,7 @@ export const processAlert = async (
414461

415462
// Check for auto-resolve: for each group, check if it transitioned from ALERT to OK
416463
for (const [groupKey, history] of histories.entries()) {
417-
const previousKey = groupKey ? `${alert.id}:${groupKey}` : alert.id;
464+
const previousKey = computeHistoryMapKey(alert.id, groupKey);
418465
const groupPrevious = previousMap?.get(previousKey) || previous; // Use previousMap first, fallback to previous for backwards compatibility
419466

420467
if (

0 commit comments

Comments
 (0)