Skip to content

Commit 226a00d

Browse files
authored
feat: add state field to AlertHistory collection (#157)
1 parent 63fb258 commit 226a00d

4 files changed

Lines changed: 73 additions & 29 deletions

File tree

.changeset/great-bags-smoke.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@hyperdx/api': minor
3+
---
4+
5+
feat: add state field to AlertHistory collection

packages/api/src/models/alertHistory.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import mongoose, { Schema } from 'mongoose';
22
import ms from 'ms';
33

4+
import { AlertState } from '@/models/alert';
5+
46
import type { ObjectId } from '.';
57

68
export interface IAlertHistory {
79
alert: ObjectId;
810
counts: number;
911
createdAt: Date;
12+
state: AlertState;
1013
}
1114

1215
const AlertHistorySchema = new Schema<IAlertHistory>({
@@ -19,6 +22,11 @@ const AlertHistorySchema = new Schema<IAlertHistory>({
1922
required: true,
2023
},
2124
alert: { type: mongoose.Schema.Types.ObjectId, ref: 'Alert' },
25+
state: {
26+
type: String,
27+
enum: Object.values(AlertState),
28+
required: true,
29+
},
2230
});
2331

2432
AlertHistorySchema.index(

packages/api/src/tasks/__tests__/checkAlerts.test.ts

Lines changed: 54 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -184,15 +184,6 @@ describe('checkAlerts', () => {
184184

185185
// shoud fetch 5m of logs
186186
await processAlert(now, alert);
187-
// check alert history
188-
const alertHistories = await AlertHistory.find({
189-
alertId: alert._id,
190-
});
191-
expect(alertHistories.length).toBe(1);
192-
expect(alertHistories[0].counts).toBe(1);
193-
expect(alertHistories[0].createdAt).toEqual(
194-
new Date('2023-11-16T22:10:00.000Z'),
195-
);
196187
expect(alert.state).toBe('ALERT');
197188

198189
// skip since time diff is less than 1 window size
@@ -206,6 +197,24 @@ describe('checkAlerts', () => {
206197
// alert should be in ok state
207198
expect(alert.state).toBe('OK');
208199

200+
// check alert history
201+
const alertHistories = await AlertHistory.find({
202+
alertId: alert._id,
203+
}).sort({
204+
createdAt: 1,
205+
});
206+
expect(alertHistories.length).toBe(2);
207+
expect(alertHistories[0].state).toBe('ALERT');
208+
expect(alertHistories[0].counts).toBe(1);
209+
expect(alertHistories[0].createdAt).toEqual(
210+
new Date('2023-11-16T22:10:00.000Z'),
211+
);
212+
expect(alertHistories[1].state).toBe('OK');
213+
expect(alertHistories[1].counts).toBe(0);
214+
expect(alertHistories[1].createdAt).toEqual(
215+
new Date('2023-11-16T22:15:00.000Z'),
216+
);
217+
209218
// check if checkAlert query + webhook were triggered
210219
expect(clickhouse.checkAlert).toHaveBeenNthCalledWith(1, {
211220
endTime: new Date('2023-11-16T22:10:00.000Z'),
@@ -331,15 +340,6 @@ describe('checkAlerts', () => {
331340

332341
// shoud fetch 5m of logs
333342
await processAlert(now, alert);
334-
// check alert history
335-
const alertHistories = await AlertHistory.find({
336-
alertId: alert._id,
337-
});
338-
expect(alertHistories.length).toBe(1);
339-
expect(alertHistories[0].counts).toBe(1);
340-
expect(alertHistories[0].createdAt).toEqual(
341-
new Date('2023-11-16T22:10:00.000Z'),
342-
);
343343
expect(alert.state).toBe('ALERT');
344344

345345
// skip since time diff is less than 1 window size
@@ -353,6 +353,24 @@ describe('checkAlerts', () => {
353353
// alert should be in ok state
354354
expect(alert.state).toBe('OK');
355355

356+
// check alert history
357+
const alertHistories = await AlertHistory.find({
358+
alertId: alert._id,
359+
}).sort({
360+
createdAt: 1,
361+
});
362+
expect(alertHistories.length).toBe(2);
363+
expect(alertHistories[0].state).toBe('ALERT');
364+
expect(alertHistories[0].counts).toBe(1);
365+
expect(alertHistories[0].createdAt).toEqual(
366+
new Date('2023-11-16T22:10:00.000Z'),
367+
);
368+
expect(alertHistories[1].state).toBe('OK');
369+
expect(alertHistories[1].counts).toBe(0);
370+
expect(alertHistories[1].createdAt).toEqual(
371+
new Date('2023-11-16T22:15:00.000Z'),
372+
);
373+
356374
// check if getLogsChart query + webhook were triggered
357375
expect(clickhouse.getLogsChart).toHaveBeenNthCalledWith(1, {
358376
aggFn: 'max',
@@ -477,15 +495,6 @@ describe('checkAlerts', () => {
477495

478496
// shoud fetch 5m of logs
479497
await processAlert(now, alert);
480-
// check alert history
481-
const alertHistories = await AlertHistory.find({
482-
alertId: alert._id,
483-
});
484-
expect(alertHistories.length).toBe(1);
485-
expect(alertHistories[0].counts).toBe(1);
486-
expect(alertHistories[0].createdAt).toEqual(
487-
new Date('2023-11-16T22:10:00.000Z'),
488-
);
489498
expect(alert.state).toBe('ALERT');
490499

491500
// skip since time diff is less than 1 window size
@@ -499,6 +508,24 @@ describe('checkAlerts', () => {
499508
// alert should be in ok state
500509
expect(alert.state).toBe('OK');
501510

511+
// check alert history
512+
const alertHistories = await AlertHistory.find({
513+
alertId: alert._id,
514+
}).sort({
515+
createdAt: 1,
516+
});
517+
expect(alertHistories.length).toBe(2);
518+
expect(alertHistories[0].state).toBe('ALERT');
519+
expect(alertHistories[0].counts).toBe(1);
520+
expect(alertHistories[0].createdAt).toEqual(
521+
new Date('2023-11-16T22:10:00.000Z'),
522+
);
523+
expect(alertHistories[1].state).toBe('OK');
524+
expect(alertHistories[1].counts).toBe(0);
525+
expect(alertHistories[1].createdAt).toEqual(
526+
new Date('2023-11-16T22:15:00.000Z'),
527+
);
528+
502529
// check if getLogsChart query + webhook were triggered
503530
expect(clickhouse.getMetricsChart).toHaveBeenNthCalledWith(1, {
504531
aggFn: 'max',

packages/api/src/tasks/checkAlerts.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -464,12 +464,13 @@ export const processAlert = async (now: Date, alert: AlertDocument) => {
464464
return;
465465
}
466466

467+
// TODO: support INSUFFICIENT_DATA state
468+
let alertState = AlertState.OK;
467469
const history = await new AlertHistory({
468470
alert: alert._id,
469471
createdAt: nowInMinsRoundDown,
472+
state: alertState,
470473
}).save();
471-
// TODO: support INSUFFICIENT_DATA state
472-
let alertState = AlertState.OK;
473474
if (checksData?.rows && checksData?.rows > 0) {
474475
for (const checkData of checksData.data) {
475476
const totalCount = isString(checkData.data)
@@ -498,8 +499,11 @@ export const processAlert = async (now: Date, alert: AlertDocument) => {
498499
history.counts += 1;
499500
}
500501
}
502+
503+
history.state = alertState;
501504
await history.save();
502505
}
506+
503507
alert.state = alertState;
504508
await alert.save();
505509
} catch (e) {

0 commit comments

Comments
 (0)