@oneuptime/common 7.0.3526 → 7.0.3546

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/Models/DatabaseModels/AlertFeed.ts +12 -4
  2. package/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.ts +2 -0
  3. package/Models/DatabaseModels/OnCallDutyPolicyExecutionLogTimeline.ts +59 -2
  4. package/Models/DatabaseModels/UserNotificationRule.ts +50 -0
  5. package/Models/DatabaseModels/UserOnCallLog.ts +48 -1
  6. package/Models/DatabaseModels/UserOnCallLogTimeline.ts +49 -2
  7. package/Server/API/UserOnCallLogTimelineAPI.ts +32 -8
  8. package/Server/Infrastructure/Postgres/SchemaMigrations/1737141420441-MigrationName.ts +131 -0
  9. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
  10. package/Server/Services/AlertInternalNoteService.ts +73 -0
  11. package/Server/Services/AlertOwnerTeamService.ts +112 -0
  12. package/Server/Services/AlertOwnerUserService.ts +114 -0
  13. package/Server/Services/AlertService.ts +121 -0
  14. package/Server/Services/AlertStateTimelineService.ts +52 -0
  15. package/Server/Services/OnCallDutyPolicyEscalationRuleService.ts +32 -14
  16. package/Server/Services/OnCallDutyPolicyExecutionLogService.ts +86 -27
  17. package/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.ts +30 -12
  18. package/Server/Services/UserNotificationRuleService.ts +450 -67
  19. package/Server/Services/UserOnCallLogService.ts +61 -18
  20. package/Server/Services/UserOnCallLogTimelineService.ts +25 -11
  21. package/Server/Services/WorkflowLogService.ts +1 -1
  22. package/Types/Email/EmailTemplateType.ts +1 -0
  23. package/Types/NotificationRule/NotificationRuleType.ts +1 -1
  24. package/build/dist/Models/DatabaseModels/AlertFeed.js +12 -4
  25. package/build/dist/Models/DatabaseModels/AlertFeed.js.map +1 -1
  26. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js +2 -0
  27. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js.map +1 -1
  28. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLogTimeline.js +60 -2
  29. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLogTimeline.js.map +1 -1
  30. package/build/dist/Models/DatabaseModels/UserNotificationRule.js +49 -0
  31. package/build/dist/Models/DatabaseModels/UserNotificationRule.js.map +1 -1
  32. package/build/dist/Models/DatabaseModels/UserOnCallLog.js +48 -1
  33. package/build/dist/Models/DatabaseModels/UserOnCallLog.js.map +1 -1
  34. package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js +50 -2
  35. package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js.map +1 -1
  36. package/build/dist/Server/API/UserOnCallLogTimelineAPI.js +10 -2
  37. package/build/dist/Server/API/UserOnCallLogTimelineAPI.js.map +1 -1
  38. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1737141420441-MigrationName.js +50 -0
  39. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1737141420441-MigrationName.js.map +1 -0
  40. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
  41. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  42. package/build/dist/Server/Services/AlertInternalNoteService.js +56 -0
  43. package/build/dist/Server/Services/AlertInternalNoteService.js.map +1 -1
  44. package/build/dist/Server/Services/AlertOwnerTeamService.js +86 -0
  45. package/build/dist/Server/Services/AlertOwnerTeamService.js.map +1 -1
  46. package/build/dist/Server/Services/AlertOwnerUserService.js +89 -0
  47. package/build/dist/Server/Services/AlertOwnerUserService.js.map +1 -1
  48. package/build/dist/Server/Services/AlertService.js +107 -3
  49. package/build/dist/Server/Services/AlertService.js.map +1 -1
  50. package/build/dist/Server/Services/AlertStateTimelineService.js +44 -1
  51. package/build/dist/Server/Services/AlertStateTimelineService.js.map +1 -1
  52. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js +18 -8
  53. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js.map +1 -1
  54. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js +70 -24
  55. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js.map +1 -1
  56. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js +26 -11
  57. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js.map +1 -1
  58. package/build/dist/Server/Services/UserNotificationRuleService.js +334 -67
  59. package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
  60. package/build/dist/Server/Services/UserOnCallLogService.js +66 -27
  61. package/build/dist/Server/Services/UserOnCallLogService.js.map +1 -1
  62. package/build/dist/Server/Services/UserOnCallLogTimelineService.js +16 -5
  63. package/build/dist/Server/Services/UserOnCallLogTimelineService.js.map +1 -1
  64. package/build/dist/Server/Services/WorkflowLogService.js +1 -1
  65. package/build/dist/Server/Services/WorkflowLogService.js.map +1 -1
  66. package/build/dist/Types/Email/EmailTemplateType.js +1 -0
  67. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  68. package/build/dist/Types/NotificationRule/NotificationRuleType.js +1 -1
  69. package/build/dist/Types/NotificationRule/NotificationRuleType.js.map +1 -1
  70. package/package.json +2 -2
@@ -1,10 +1,122 @@
1
+ import Team from "../../Models/DatabaseModels/Team";
2
+ import ObjectID from "../../Types/ObjectID";
3
+ import DeleteBy from "../Types/Database/DeleteBy";
4
+ import { OnCreate, OnDelete } from "../Types/Database/Hooks";
1
5
  import DatabaseService from "./DatabaseService";
2
6
  import Model from "Common/Models/DatabaseModels/AlertOwnerTeam";
7
+ import TeamService from "./TeamService";
8
+ import AlertFeedService from "./AlertFeedService";
9
+ import { AlertFeedEventType } from "../../Models/DatabaseModels/AlertFeed";
10
+ import { Gray500, Red500 } from "../../Types/BrandColors";
3
11
 
4
12
  export class Service extends DatabaseService<Model> {
5
13
  public constructor() {
6
14
  super(Model);
7
15
  }
16
+
17
+ protected override async onBeforeDelete(
18
+ deleteBy: DeleteBy<Model>,
19
+ ): Promise<OnDelete<Model>> {
20
+ const itemsToDelete: Model[] = await this.findBy({
21
+ query: deleteBy.query,
22
+ limit: deleteBy.limit,
23
+ skip: deleteBy.skip,
24
+ props: {
25
+ isRoot: true,
26
+ },
27
+ select: {
28
+ alertId: true,
29
+ projectId: true,
30
+ teamId: true,
31
+ },
32
+ });
33
+
34
+ return {
35
+ carryForward: {
36
+ itemsToDelete: itemsToDelete,
37
+ },
38
+ deleteBy: deleteBy,
39
+ };
40
+ }
41
+
42
+ protected override async onDeleteSuccess(
43
+ onDelete: OnDelete<Model>,
44
+ _itemIdsBeforeDelete: Array<ObjectID>,
45
+ ): Promise<OnDelete<Model>> {
46
+ const deleteByUserId: ObjectID | undefined =
47
+ onDelete.deleteBy.deletedByUser?.id || onDelete.deleteBy.props.userId;
48
+
49
+ const itemsToDelete: Model[] = onDelete.carryForward.itemsToDelete;
50
+
51
+ for (const item of itemsToDelete) {
52
+ const alertId: ObjectID | undefined = item.alertId;
53
+ const projectId: ObjectID | undefined = item.projectId;
54
+ const teamId: ObjectID | undefined = item.teamId;
55
+
56
+ if (alertId && teamId && projectId) {
57
+ const team: Team | null = await TeamService.findOneById({
58
+ id: teamId,
59
+ select: {
60
+ name: true,
61
+ },
62
+ props: {
63
+ isRoot: true,
64
+ },
65
+ });
66
+
67
+ if (team && team.name) {
68
+ await AlertFeedService.createAlertFeed({
69
+ alertId: alertId,
70
+ projectId: projectId,
71
+ alertFeedEventType: AlertFeedEventType.OwnerTeamRemoved,
72
+ displayColor: Red500,
73
+ feedInfoInMarkdown: `**Team ${team.name}** was removed from the alert as the owner.`,
74
+ userId: deleteByUserId || undefined,
75
+ });
76
+ }
77
+ }
78
+ }
79
+
80
+ return onDelete;
81
+ }
82
+
83
+ public override async onCreateSuccess(
84
+ onCreate: OnCreate<Model>,
85
+ createdItem: Model,
86
+ ): Promise<Model> {
87
+ // add alert feed.
88
+
89
+ const alertId: ObjectID | undefined = createdItem.alertId;
90
+ const projectId: ObjectID | undefined = createdItem.projectId;
91
+ const teamId: ObjectID | undefined = createdItem.teamId;
92
+ const createdByUserId: ObjectID | undefined =
93
+ createdItem.createdByUserId || onCreate.createBy.props.userId;
94
+
95
+ if (alertId && teamId && projectId) {
96
+ const team: Team | null = await TeamService.findOneById({
97
+ id: teamId,
98
+ select: {
99
+ name: true,
100
+ },
101
+ props: {
102
+ isRoot: true,
103
+ },
104
+ });
105
+
106
+ if (team && team.name) {
107
+ await AlertFeedService.createAlertFeed({
108
+ alertId: alertId,
109
+ projectId: projectId,
110
+ alertFeedEventType: AlertFeedEventType.OwnerTeamAdded,
111
+ displayColor: Gray500,
112
+ feedInfoInMarkdown: `**Team ${team.name}** was added to the alert as the owner.`,
113
+ userId: createdByUserId || undefined,
114
+ });
115
+ }
116
+ }
117
+
118
+ return createdItem;
119
+ }
8
120
  }
9
121
 
10
122
  export default new Service();
@@ -1,10 +1,124 @@
1
+ import User from "../../Models/DatabaseModels/User";
2
+ import ObjectID from "../../Types/ObjectID";
3
+ import DeleteBy from "../Types/Database/DeleteBy";
4
+ import { OnCreate, OnDelete } from "../Types/Database/Hooks";
1
5
  import DatabaseService from "./DatabaseService";
2
6
  import Model from "Common/Models/DatabaseModels/AlertOwnerUser";
7
+ import UserService from "./UserService";
8
+ import AlertFeedService from "./AlertFeedService";
9
+ import { AlertFeedEventType } from "../../Models/DatabaseModels/AlertFeed";
10
+ import { Gray500, Red500 } from "../../Types/BrandColors";
3
11
 
4
12
  export class Service extends DatabaseService<Model> {
5
13
  public constructor() {
6
14
  super(Model);
7
15
  }
16
+
17
+ protected override async onBeforeDelete(
18
+ deleteBy: DeleteBy<Model>,
19
+ ): Promise<OnDelete<Model>> {
20
+ const itemsToDelete: Model[] = await this.findBy({
21
+ query: deleteBy.query,
22
+ limit: deleteBy.limit,
23
+ skip: deleteBy.skip,
24
+ props: {
25
+ isRoot: true,
26
+ },
27
+ select: {
28
+ alertId: true,
29
+ projectId: true,
30
+ userId: true,
31
+ },
32
+ });
33
+
34
+ return {
35
+ carryForward: {
36
+ itemsToDelete: itemsToDelete,
37
+ },
38
+ deleteBy: deleteBy,
39
+ };
40
+ }
41
+
42
+ protected override async onDeleteSuccess(
43
+ onDelete: OnDelete<Model>,
44
+ _itemIdsBeforeDelete: Array<ObjectID>,
45
+ ): Promise<OnDelete<Model>> {
46
+ const deleteByUserId: ObjectID | undefined =
47
+ onDelete.deleteBy.deletedByUser?.id || onDelete.deleteBy.props.userId;
48
+
49
+ const itemsToDelete: Model[] = onDelete.carryForward.itemsToDelete;
50
+
51
+ for (const item of itemsToDelete) {
52
+ const alertId: ObjectID | undefined = item.alertId;
53
+ const projectId: ObjectID | undefined = item.projectId;
54
+ const userId: ObjectID | undefined = item.userId;
55
+
56
+ if (alertId && userId && projectId) {
57
+ const user: User | null = await UserService.findOneById({
58
+ id: userId,
59
+ select: {
60
+ name: true,
61
+ email: true,
62
+ },
63
+ props: {
64
+ isRoot: true,
65
+ },
66
+ });
67
+
68
+ if (user && user.name) {
69
+ await AlertFeedService.createAlertFeed({
70
+ alertId: alertId,
71
+ projectId: projectId,
72
+ alertFeedEventType: AlertFeedEventType.OwnerUserRemoved,
73
+ displayColor: Red500,
74
+ feedInfoInMarkdown: `**${user.name.toString()}** (${user.email?.toString()}) was removed from the alert as the owner.`,
75
+ userId: deleteByUserId || undefined,
76
+ });
77
+ }
78
+ }
79
+ }
80
+
81
+ return onDelete;
82
+ }
83
+
84
+ public override async onCreateSuccess(
85
+ onCreate: OnCreate<Model>,
86
+ createdItem: Model,
87
+ ): Promise<Model> {
88
+ // add alert feed.
89
+
90
+ const alertId: ObjectID | undefined = createdItem.alertId;
91
+ const projectId: ObjectID | undefined = createdItem.projectId;
92
+ const userId: ObjectID | undefined = createdItem.userId;
93
+ const createdByUserId: ObjectID | undefined =
94
+ createdItem.createdByUserId || onCreate.createBy.props.userId;
95
+
96
+ if (alertId && userId && projectId) {
97
+ const user: User | null = await UserService.findOneById({
98
+ id: userId,
99
+ select: {
100
+ name: true,
101
+ email: true,
102
+ },
103
+ props: {
104
+ isRoot: true,
105
+ },
106
+ });
107
+
108
+ if (user && user.name) {
109
+ await AlertFeedService.createAlertFeed({
110
+ alertId: alertId,
111
+ projectId: projectId,
112
+ alertFeedEventType: AlertFeedEventType.OwnerUserAdded,
113
+ displayColor: Gray500,
114
+ feedInfoInMarkdown: `**${user.name.toString()}** (${user.email?.toString()}) was added to the alert as the owner.`,
115
+ userId: createdByUserId || undefined,
116
+ });
117
+ }
118
+ }
119
+
120
+ return createdItem;
121
+ }
8
122
  }
9
123
 
10
124
  export default new Service();
@@ -38,6 +38,9 @@ import Metric, {
38
38
  ServiceType,
39
39
  } from "../../Models/AnalyticsModels/Metric";
40
40
  import AlertMetricType from "../../Types/Alerts/AlertMetricType";
41
+ import AlertFeedService from "./AlertFeedService";
42
+ import { AlertFeedEventType } from "../../Models/DatabaseModels/AlertFeed";
43
+ import { Gray500, Red500 } from "../../Types/BrandColors";
41
44
 
42
45
  export class Service extends DatabaseService<Model> {
43
46
  public constructor() {
@@ -224,6 +227,48 @@ export class Service extends DatabaseService<Model> {
224
227
  throw new BadDataException("currentAlertStateId is required");
225
228
  }
226
229
 
230
+ const createdByUserId: ObjectID | undefined | null =
231
+ createdItem.createdByUserId || createdItem.createdByUser?.id;
232
+
233
+ await AlertFeedService.createAlertFeed({
234
+ alertId: createdItem.id!,
235
+ projectId: createdItem.projectId!,
236
+ alertFeedEventType: AlertFeedEventType.AlertCreated,
237
+ displayColor: Red500,
238
+ feedInfoInMarkdown: `**Alert Created**:
239
+
240
+ **Alert Title**:
241
+
242
+ ${createdItem.title || "No title provided."}
243
+
244
+ **Description**:
245
+
246
+ ${createdItem.description || "No description provided."}
247
+
248
+ `,
249
+ userId: createdByUserId || undefined,
250
+ });
251
+
252
+ await AlertFeedService.createAlertFeed({
253
+ alertId: createdItem.id!,
254
+ projectId: createdItem.projectId!,
255
+ alertFeedEventType: AlertFeedEventType.RootCause,
256
+ displayColor: Red500,
257
+ feedInfoInMarkdown: `**Root Cause**
258
+
259
+ ${createdItem.rootCause || "No root cause provided."}`,
260
+ });
261
+
262
+ await AlertFeedService.createAlertFeed({
263
+ alertId: createdItem.id!,
264
+ projectId: createdItem.projectId!,
265
+ alertFeedEventType: AlertFeedEventType.RemediationNotes,
266
+ displayColor: Red500,
267
+ feedInfoInMarkdown: `**Remediation Notes**
268
+
269
+ ${createdItem.remediationNotes || "No remediation notes provided."}`,
270
+ });
271
+
227
272
  await this.changeAlertState({
228
273
  projectId: createdItem.projectId,
229
274
  alertId: createdItem.id,
@@ -445,6 +490,82 @@ export class Service extends DatabaseService<Model> {
445
490
  }
446
491
  }
447
492
 
493
+ if (updatedItemIds.length > 0) {
494
+ for (const alertId of updatedItemIds) {
495
+ if (onUpdate.updateBy.data.title) {
496
+ // add alert feed.
497
+ const createdByUserId: ObjectID | undefined | null =
498
+ onUpdate.updateBy.props.userId;
499
+
500
+ await AlertFeedService.createAlertFeed({
501
+ alertId: alertId,
502
+ projectId: onUpdate.updateBy.props.tenantId as ObjectID,
503
+ alertFeedEventType: AlertFeedEventType.AlertUpdated,
504
+ displayColor: Gray500,
505
+ feedInfoInMarkdown: `**Alert title was updated.** Here's the new title.
506
+
507
+ ${onUpdate.updateBy.data.title || "No title provided."}
508
+ `,
509
+ userId: createdByUserId || undefined,
510
+ });
511
+ }
512
+
513
+ if (onUpdate.updateBy.data.rootCause) {
514
+ // add alert feed.
515
+ const createdByUserId: ObjectID | undefined | null =
516
+ onUpdate.updateBy.props.userId;
517
+
518
+ await AlertFeedService.createAlertFeed({
519
+ alertId: alertId,
520
+ projectId: onUpdate.updateBy.props.tenantId as ObjectID,
521
+ alertFeedEventType: AlertFeedEventType.AlertUpdated,
522
+ displayColor: Gray500,
523
+ feedInfoInMarkdown: `**Alert root cause was updated.** Here's the new root cause.
524
+
525
+ ${onUpdate.updateBy.data.rootCause || "No root cause provided."}
526
+ `,
527
+ userId: createdByUserId || undefined,
528
+ });
529
+ }
530
+
531
+ if (onUpdate.updateBy.data.description) {
532
+ // add alert feed.
533
+ const createdByUserId: ObjectID | undefined | null =
534
+ onUpdate.updateBy.props.userId;
535
+
536
+ await AlertFeedService.createAlertFeed({
537
+ alertId: alertId,
538
+ projectId: onUpdate.updateBy.props.tenantId as ObjectID,
539
+ alertFeedEventType: AlertFeedEventType.AlertUpdated,
540
+ displayColor: Gray500,
541
+ feedInfoInMarkdown: `**Alert description was updated.** Here's the new description.
542
+
543
+ ${onUpdate.updateBy.data.description || "No description provided."}
544
+ `,
545
+ userId: createdByUserId || undefined,
546
+ });
547
+ }
548
+
549
+ if (onUpdate.updateBy.data.remediationNotes) {
550
+ // add alert feed.
551
+ const createdByUserId: ObjectID | undefined | null =
552
+ onUpdate.updateBy.props.userId;
553
+
554
+ await AlertFeedService.createAlertFeed({
555
+ alertId: alertId,
556
+ projectId: onUpdate.updateBy.props.tenantId as ObjectID,
557
+ alertFeedEventType: AlertFeedEventType.AlertUpdated,
558
+ displayColor: Gray500,
559
+ feedInfoInMarkdown: `**Remediation notes were updated.** Here are the new notes.
560
+
561
+ ${onUpdate.updateBy.data.remediationNotes || "No remediation notes provided."}
562
+ `,
563
+ userId: createdByUserId || undefined,
564
+ });
565
+ }
566
+ }
567
+ }
568
+
448
569
  return onUpdate;
449
570
  }
450
571
 
@@ -19,6 +19,8 @@ import { JSONObject } from "../../Types/JSON";
19
19
  import AlertInternalNote from "../../Models/DatabaseModels/AlertInternalNote";
20
20
  import AlertInternalNoteService from "./AlertInternalNoteService";
21
21
  import logger from "../Utils/Logger";
22
+ import AlertFeedService from "./AlertFeedService";
23
+ import { AlertFeedEventType } from "../../Models/DatabaseModels/AlertFeed";
22
24
 
23
25
  export class Service extends DatabaseService<AlertStateTimeline> {
24
26
  public constructor() {
@@ -130,10 +132,15 @@ export class Service extends DatabaseService<AlertStateTimeline> {
130
132
  });
131
133
  }
132
134
 
135
+ const privateNote: string | undefined = (
136
+ createBy.miscDataProps as JSONObject | undefined
137
+ )?.["privateNote"] as string | undefined;
138
+
133
139
  return {
134
140
  createBy,
135
141
  carryForward: {
136
142
  lastAlertStateTimelineId: lastAlertStateTimeline?.id || null,
143
+ privateNote: privateNote,
137
144
  },
138
145
  };
139
146
  }
@@ -164,6 +171,36 @@ export class Service extends DatabaseService<AlertStateTimeline> {
164
171
  });
165
172
  }
166
173
 
174
+ const alertState: AlertState | null = await AlertStateService.findOneBy({
175
+ query: {
176
+ _id: createdItem.alertStateId.toString()!,
177
+ },
178
+ props: {
179
+ isRoot: true,
180
+ },
181
+ select: {
182
+ _id: true,
183
+ isResolvedState: true,
184
+ isAcknowledgedState: true,
185
+ isCreatedState: true,
186
+ color: true,
187
+ name: true,
188
+ },
189
+ });
190
+
191
+ const stateName: string = alertState?.name || "";
192
+
193
+ await AlertFeedService.createAlertFeed({
194
+ alertId: createdItem.alertId!,
195
+ projectId: createdItem.projectId!,
196
+ alertFeedEventType: AlertFeedEventType.AlertStateChanged,
197
+ displayColor: alertState?.color,
198
+ feedInfoInMarkdown: "**Alert State** changed to **" + stateName + "**",
199
+ moreInformationInMarkdown: `**Cause:**
200
+ ${createdItem.rootCause}`,
201
+ userId: createdItem.createdByUserId || onCreate.createBy.props.userId,
202
+ });
203
+
167
204
  await AlertService.updateOneBy({
168
205
  query: {
169
206
  _id: createdItem.alertId?.toString(),
@@ -174,6 +211,21 @@ export class Service extends DatabaseService<AlertStateTimeline> {
174
211
  props: onCreate.createBy.props,
175
212
  });
176
213
 
214
+ if (onCreate.carryForward.privateNote) {
215
+ const privateNote: string = onCreate.carryForward.privateNote;
216
+
217
+ const alertInternalNote: AlertInternalNote = new AlertInternalNote();
218
+ alertInternalNote.alertId = createdItem.alertId;
219
+ alertInternalNote.note = privateNote;
220
+ alertInternalNote.createdAt = createdItem.startsAt!;
221
+ alertInternalNote.projectId = createdItem.projectId!;
222
+
223
+ await AlertInternalNoteService.create({
224
+ data: alertInternalNote,
225
+ props: onCreate.createBy.props,
226
+ });
227
+ }
228
+
177
229
  AlertService.refreshAlertMetrics({
178
230
  alertId: createdItem.alertId,
179
231
  }).catch((error: Error) => {
@@ -30,6 +30,7 @@ import OnCallDutyPolicyEscalationRuleTeam from "Common/Models/DatabaseModels/OnC
30
30
  import OnCallDutyPolicyEscalationRuleUser from "Common/Models/DatabaseModels/OnCallDutyPolicyEscalationRuleUser";
31
31
  import OnCallDutyPolicyExecutionLogTimeline from "Common/Models/DatabaseModels/OnCallDutyPolicyExecutionLogTimeline";
32
32
  import User from "Common/Models/DatabaseModels/User";
33
+ import logger from "../Utils/Logger";
33
34
 
34
35
  export class Service extends DatabaseService<Model> {
35
36
  public async startRuleExecution(
@@ -37,12 +38,13 @@ export class Service extends DatabaseService<Model> {
37
38
  options: {
38
39
  projectId: ObjectID;
39
40
  triggeredByIncidentId?: ObjectID | undefined;
41
+ triggeredByAlertId?: ObjectID | undefined;
40
42
  userNotificationEventType: UserNotificationEventType;
41
43
  onCallPolicyExecutionLogId: ObjectID;
42
44
  onCallPolicyId: ObjectID;
43
45
  },
44
46
  ): Promise<void> {
45
- // add log timeline.
47
+ logger.debug(`Starting rule execution for ruleId: ${ruleId.toString()}`);
46
48
 
47
49
  const rule: Model | null = await this.findOneById({
48
50
  id: ruleId,
@@ -62,6 +64,8 @@ export class Service extends DatabaseService<Model> {
62
64
  );
63
65
  }
64
66
 
67
+ logger.debug(`Found rule: ${JSON.stringify(rule)}`);
68
+
65
69
  await OnCallDutyPolicyExecutionLogService.updateOneById({
66
70
  id: options.onCallPolicyExecutionLogId,
67
71
  data: {
@@ -75,6 +79,8 @@ export class Service extends DatabaseService<Model> {
75
79
  },
76
80
  });
77
81
 
82
+ logger.debug(`Updated execution log for ruleId: ${ruleId.toString()}`);
83
+
78
84
  type GetNewLogFunction = () => OnCallDutyPolicyExecutionLogTimeline;
79
85
 
80
86
  const getNewLog: GetNewLogFunction =
@@ -92,6 +98,10 @@ export class Service extends DatabaseService<Model> {
92
98
  log.triggeredByIncidentId = options.triggeredByIncidentId;
93
99
  }
94
100
 
101
+ if (options.triggeredByAlertId) {
102
+ log.triggeredByAlertId = options.triggeredByAlertId;
103
+ }
104
+
95
105
  return log;
96
106
  };
97
107
 
@@ -105,6 +115,16 @@ export class Service extends DatabaseService<Model> {
105
115
  );
106
116
  }
107
117
 
118
+ if (
119
+ UserNotificationEventType.AlertCreated ===
120
+ options.userNotificationEventType &&
121
+ !options.triggeredByAlertId
122
+ ) {
123
+ throw new BadDataException(
124
+ "triggeredByAlertId is required when userNotificationEventType is IncidentCreated",
125
+ );
126
+ }
127
+
108
128
  const usersInRule: Array<OnCallDutyPolicyEscalationRuleUser> =
109
129
  await OnCallDutyPolicyEscalationRuleUserService.findBy({
110
130
  query: {
@@ -120,6 +140,8 @@ export class Service extends DatabaseService<Model> {
120
140
  },
121
141
  });
122
142
 
143
+ logger.debug(`Found users in rule: ${JSON.stringify(usersInRule)}`);
144
+
123
145
  const teamsInRule: Array<OnCallDutyPolicyEscalationRuleTeam> =
124
146
  await OnCallDutyPolicyEscalationRuleTeamService.findBy({
125
147
  query: {
@@ -135,6 +157,8 @@ export class Service extends DatabaseService<Model> {
135
157
  },
136
158
  });
137
159
 
160
+ logger.debug(`Found teams in rule: ${JSON.stringify(teamsInRule)}`);
161
+
138
162
  const schedulesInRule: Array<OnCallDutyPolicyEscalationRuleSchedule> =
139
163
  await OnCallDutyPolicyEscalationRuleScheduleService.findBy({
140
164
  query: {
@@ -150,7 +174,7 @@ export class Service extends DatabaseService<Model> {
150
174
  },
151
175
  });
152
176
 
153
- // get unique users and notify all the users.
177
+ logger.debug(`Found schedules in rule: ${JSON.stringify(schedulesInRule)}`);
154
178
 
155
179
  type StartUserNotificationRuleExecutionFunction = (
156
180
  userId: ObjectID,
@@ -164,7 +188,9 @@ export class Service extends DatabaseService<Model> {
164
188
  teamId: ObjectID | null,
165
189
  scheduleId: ObjectID | null,
166
190
  ): Promise<void> => {
167
- // no users in this rule. Skipping.
191
+ logger.debug(
192
+ `Starting notification rule execution for userId: ${userId.toString()}`,
193
+ );
168
194
  let log: OnCallDutyPolicyExecutionLogTimeline = getNewLog();
169
195
  log.statusMessage = "Sending notification to user.";
170
196
  log.status = OnCallDutyExecutionLogTimelineStatus.Executing;
@@ -189,6 +215,7 @@ export class Service extends DatabaseService<Model> {
189
215
  {
190
216
  userNotificationEventType: options.userNotificationEventType!,
191
217
  triggeredByIncidentId: options.triggeredByIncidentId || undefined,
218
+ triggeredByAlertId: options.triggeredByAlertId || undefined,
192
219
  onCallPolicyExecutionLogId: options.onCallPolicyExecutionLogId,
193
220
  onCallPolicyId: options.onCallPolicyId,
194
221
  onCallPolicyEscalationRuleId: ruleId,
@@ -220,7 +247,6 @@ export class Service extends DatabaseService<Model> {
220
247
  null,
221
248
  );
222
249
  } else {
223
- // no users in this rule. Skipping.
224
250
  const log: OnCallDutyPolicyExecutionLogTimeline = getNewLog();
225
251
  log.statusMessage =
226
252
  "Skipped because notification sent to this user already.";
@@ -247,7 +273,6 @@ export class Service extends DatabaseService<Model> {
247
273
  uniqueUserIds.push(userRule.userId!);
248
274
  await startUserNotificationRuleExecution(userRule.userId!, null, null);
249
275
  } else {
250
- // no users in this rule. Skipping.
251
276
  const log: OnCallDutyPolicyExecutionLogTimeline = getNewLog();
252
277
  log.statusMessage =
253
278
  "Skipped because notification sent to this user already.";
@@ -264,23 +289,16 @@ export class Service extends DatabaseService<Model> {
264
289
  }
265
290
 
266
291
  for (const scheduleRule of schedulesInRule) {
267
- // get layers and users in this schedule and find a user to notify.
268
-
269
292
  const userIdInSchedule: ObjectID | null =
270
293
  await OnCallDutyPolicyScheduleService.getCurrentUserIdInSchedule(
271
294
  scheduleRule.onCallDutyPolicyScheduleId!,
272
295
  );
273
296
 
274
297
  if (!userIdInSchedule) {
275
- // no user active in this schedule. Skipping.
276
-
277
298
  const log: OnCallDutyPolicyExecutionLogTimeline = getNewLog();
278
-
279
299
  log.statusMessage =
280
300
  "Skipped because no active users are found in this schedule.";
281
-
282
301
  log.status = OnCallDutyExecutionLogTimelineStatus.Skipped;
283
-
284
302
  log.onCallDutyScheduleId = scheduleRule.onCallDutyPolicyScheduleId!;
285
303
 
286
304
  await OnCallDutyPolicyExecutionLogTimelineService.create({
@@ -305,7 +323,6 @@ export class Service extends DatabaseService<Model> {
305
323
  scheduleRule.onCallDutyPolicyScheduleId!,
306
324
  );
307
325
  } else {
308
- // no users in this rule. Skipping.
309
326
  const log: OnCallDutyPolicyExecutionLogTimeline = getNewLog();
310
327
  log.statusMessage =
311
328
  "Skipped because notification sent to this user already.";
@@ -323,7 +340,6 @@ export class Service extends DatabaseService<Model> {
323
340
  }
324
341
 
325
342
  if (uniqueUserIds.length === 0) {
326
- // no users in this rule. Skipping.
327
343
  const log: OnCallDutyPolicyExecutionLogTimeline = getNewLog();
328
344
  log.statusMessage = "Skipped because no users in this rule.";
329
345
  log.status = OnCallDutyExecutionLogTimelineStatus.Skipped;
@@ -335,6 +351,8 @@ export class Service extends DatabaseService<Model> {
335
351
  },
336
352
  });
337
353
  }
354
+
355
+ logger.debug(`Completed rule execution for ruleId: ${ruleId.toString()}`);
338
356
  }
339
357
 
340
358
  public constructor() {