feat: rename notification rule type for clarity and update related migration

This commit is contained in:
Simon Larsen
2025-01-20 13:55:56 +00:00
parent 984cb41efc
commit bc244bfde1
14 changed files with 143 additions and 91 deletions

View File

@@ -271,7 +271,7 @@ export default class OnCallDutyPolicyExecutionLog extends BaseModel {
@TableColumn({
type: TableColumnType.ObjectID,
title: "Triggered By Alert ID",
required: false,
required: false,
description:
"ID of the incident which triggered this on-call escalation policy.",
})

View File

@@ -369,7 +369,7 @@ export default class UserOnCallLog extends BaseModel {
@TableColumn({
type: TableColumnType.ObjectID,
title: "Triggered By Incident ID",
required: false,
required: false,
description:
"ID of the incident which triggered this on-call escalation policy.",
})
@@ -414,7 +414,7 @@ export default class UserOnCallLog extends BaseModel {
@TableColumn({
type: TableColumnType.ObjectID,
title: "Triggered By Alert ID",
required: false,
required: false,
description:
"ID of the Alert which triggered this on-call escalation policy.",
})

View File

@@ -188,7 +188,9 @@ export class Service extends DatabaseService<Model> {
teamId: ObjectID | null,
scheduleId: ObjectID | null,
): Promise<void> => {
logger.debug(`Starting notification rule execution for userId: ${userId.toString()}`);
logger.debug(
`Starting notification rule execution for userId: ${userId.toString()}`,
);
let log: OnCallDutyPolicyExecutionLogTimeline = getNewLog();
log.statusMessage = "Sending notification to user.";
log.status = OnCallDutyExecutionLogTimelineStatus.Executing;

View File

@@ -113,18 +113,17 @@ export class Service extends DatabaseService<Model> {
},
});
let userNotificationEventType: UserNotificationEventType | null = null;
if(createdItem.triggeredByIncidentId) {
if (createdItem.triggeredByIncidentId) {
userNotificationEventType = UserNotificationEventType.IncidentCreated;
}
if(createdItem.triggeredByAlertId) {
if (createdItem.triggeredByAlertId) {
userNotificationEventType = UserNotificationEventType.AlertCreated;
}
if(!userNotificationEventType) {
if (!userNotificationEventType) {
throw new BadDataException("Invalid userNotificationEventType");
}

View File

@@ -185,7 +185,7 @@ export class Service extends DatabaseService<Model> {
if (
options.userNotificationEventType ===
UserNotificationEventType.IncidentCreated &&
UserNotificationEventType.IncidentCreated &&
options.triggeredByIncidentId
) {
incident = await IncidentService.findOneById({
@@ -214,7 +214,7 @@ export class Service extends DatabaseService<Model> {
if (
options.userNotificationEventType ===
UserNotificationEventType.AlertCreated &&
UserNotificationEventType.AlertCreated &&
options.triggeredByAlertId
) {
alert = await AlertService.findOneById({
@@ -252,7 +252,7 @@ export class Service extends DatabaseService<Model> {
if (
options.userNotificationEventType ===
UserNotificationEventType.AlertCreated &&
UserNotificationEventType.AlertCreated &&
alert
) {
// create an error log.
@@ -297,7 +297,7 @@ export class Service extends DatabaseService<Model> {
// send email for incident
if (
options.userNotificationEventType ===
UserNotificationEventType.IncidentCreated &&
UserNotificationEventType.IncidentCreated &&
incident
) {
// create an error log.
@@ -365,7 +365,7 @@ export class Service extends DatabaseService<Model> {
//send sms for alert
if (
options.userNotificationEventType ===
UserNotificationEventType.AlertCreated &&
UserNotificationEventType.AlertCreated &&
alert
) {
// create an error log.
@@ -409,7 +409,7 @@ export class Service extends DatabaseService<Model> {
// send sms for incident
if (
options.userNotificationEventType ===
UserNotificationEventType.IncidentCreated &&
UserNotificationEventType.IncidentCreated &&
incident
) {
// create an error log.
@@ -476,7 +476,7 @@ export class Service extends DatabaseService<Model> {
// send call for alert
if (
options.userNotificationEventType ===
UserNotificationEventType.AlertCreated &&
UserNotificationEventType.AlertCreated &&
alert
) {
// create an error log.
@@ -520,7 +520,7 @@ export class Service extends DatabaseService<Model> {
if (
options.userNotificationEventType ===
UserNotificationEventType.IncidentCreated &&
UserNotificationEventType.IncidentCreated &&
incident
) {
// send call for incident
@@ -701,8 +701,9 @@ export class Service extends DatabaseService<Model> {
const sms: SMS = {
to,
message: `This is a message from OneUptime. A new alert has been created. ${alert.title
}. To acknowledge this alert, please click on the following link ${url.toString()}`,
message: `This is a message from OneUptime. A new alert has been created. ${
alert.title
}. To acknowledge this alert, please click on the following link ${url.toString()}`,
};
return sms;
@@ -729,8 +730,9 @@ export class Service extends DatabaseService<Model> {
const sms: SMS = {
to,
message: `This is a message from OneUptime. A new incident has been created. ${incident.title
}. To acknowledge this incident, please click on the following link ${url.toString()}`,
message: `This is a message from OneUptime. A new incident has been created. ${
incident.title
}. To acknowledge this incident, please click on the following link ${url.toString()}`,
};
return sms;
@@ -909,12 +911,10 @@ export class Service extends DatabaseService<Model> {
}
public async addDefaultIncidentNotificationRuleForUser(data: {
projectId: ObjectID,
userId: ObjectID,
userEmail: UserEmail,
}
): Promise<void> {
projectId: ObjectID;
userId: ObjectID;
userEmail: UserEmail;
}): Promise<void> {
const { projectId, userId, userEmail } = data;
const incidentSeverities: Array<IncidentSeverity> =
@@ -932,7 +932,6 @@ export class Service extends DatabaseService<Model> {
},
});
// create for incident severities.
for (const incidentSeverity of incidentSeverities) {
//check if this rule already exists.
@@ -971,14 +970,11 @@ export class Service extends DatabaseService<Model> {
}
}
public async addDefaultAlertNotificationRulesForUser(data: {
projectId: ObjectID,
userId: ObjectID,
userEmail: UserEmail,
}
): Promise<void> {
projectId: ObjectID;
userId: ObjectID;
userEmail: UserEmail;
}): Promise<void> {
const { projectId, userId, userEmail } = data;
const alertSeverities: Array<AlertSeverity> =
@@ -1034,13 +1030,11 @@ export class Service extends DatabaseService<Model> {
}
}
public async addDefaultNotificationRuleForUser(
projectId: ObjectID,
userId: ObjectID,
email: Email,
): Promise<void> {
let userEmail: UserEmail | null = await UserEmailService.findOneBy({
query: {
projectId,
@@ -1052,7 +1046,6 @@ export class Service extends DatabaseService<Model> {
},
});
if (!userEmail) {
userEmail = new UserEmail();
userEmail.projectId = projectId;
@@ -1069,11 +1062,19 @@ export class Service extends DatabaseService<Model> {
}
// add default incident rules for user
await this.addDefaultIncidentNotificationRuleForUser({projectId, userId, userEmail});
await this.addDefaultIncidentNotificationRuleForUser({
projectId,
userId,
userEmail,
});
// add default alert rules for user, just like the incident
await this.addDefaultAlertNotificationRulesForUser({projectId, userId, userEmail});
await this.addDefaultAlertNotificationRulesForUser({
projectId,
userId,
userEmail,
});
//check if this rule already exists.
const existingRuleOnCall: Model | null = await this.findOneBy({

View File

@@ -283,7 +283,8 @@ export class Service extends DatabaseService<Model> {
NotificationRuleType.ON_CALL_EXECUTED;
if (
userNotificationEventType === UserNotificationEventType.IncidentCreated || userNotificationEventType === UserNotificationEventType.AlertCreated
userNotificationEventType === UserNotificationEventType.IncidentCreated ||
userNotificationEventType === UserNotificationEventType.AlertCreated
) {
notificationRuleType = NotificationRuleType.ON_CALL_EXECUTED;
} else {

View File

@@ -1,5 +1,5 @@
enum NotificationRuleType {
ON_CALL_EXECUTED = "When incident is created during on call",
ON_CALL_EXECUTED = "When on-call policy is executed",
WHEN_USER_GOES_ON_CALL = "When user goes on call",
WHEN_USER_GOES_OFF_CALL = "When user goes off call",
}

View File

@@ -122,18 +122,20 @@ const ExecutionLogsTable: FunctionComponent<ComponentProps> = (
return (
<div>
<p>Incident:</p>
<IncidentView incident={item["triggeredByIncident"] as Incident} />
<IncidentView
incident={item["triggeredByIncident"] as Incident}
/>
</div>
);
}
if(item.triggeredByAlert){
if (item.triggeredByAlert) {
return (
<div>
<p>Alert:</p>
<AlertView alert={item["triggeredByAlert"] as Alert} />
</div>
)
<AlertView alert={item["triggeredByAlert"] as Alert} />
</div>
);
}
return <p>-</p>;

View File

@@ -17,7 +17,6 @@ BasicCron({
runOnStartup: false,
},
runFunction: async () => {
logger.debug("Checking if probe is alive...");
const probeId: string | undefined = LocalCache.getString(
@@ -40,12 +39,10 @@ BasicCron({
ProbeAPIRequest.getDefaultRequestBody(),
);
if(result.isSuccess()){
if (result.isSuccess()) {
logger.debug("Probe update sent to server successfully.");
}else{
} else {
logger.error("Failed to send probe update to server.");
}
},
});

View File

@@ -29,33 +29,28 @@ import OneUptimeDate from "Common/Types/Date";
const router: ExpressRouter = Express.getRouter();
router.post(
"/alive",
ProbeAuthorization.isAuthorizedServiceMiddleware,
async (
req: ExpressRequest,
res: ExpressResponse,
): Promise<void> => {
async (req: ExpressRequest, res: ExpressResponse): Promise<void> => {
// Update last alive in probe and return success response.
// Update last alive in probe and return success response.
const data: JSONObject = req.body;
const data: JSONObject = req.body;
const probeId: ObjectID = new ObjectID(data["probeId"] as string);
const probeId: ObjectID = new ObjectID(data["probeId"] as string);
await ProbeService.updateOneById({
id: probeId,
data: {
lastAlive: OneUptimeDate.getCurrentDate(),
},
props: {
isRoot: true,
},
});
await ProbeService.updateOneById({
id: probeId,
data: {
lastAlive: OneUptimeDate.getCurrentDate(),
},
props: {
isRoot: true,
},
});
return Response.sendEmptySuccessResponse(req, res);
}
return Response.sendEmptySuccessResponse(req, res);
},
);
router.post(

View File

@@ -40,6 +40,7 @@ import RefreshDefaultUserNotificationSetting from "./RefreshUserNotificationSett
import AddServiceTypeColumnToMetricsTable from "./AddServiceTypeColumnToMetricTable";
import AddIsSubscriptionConfirmedToSubscribers from "./AddIsSubscriptionConfirmedToSubscribers";
import AddIncidentNumber from "./AddIncidentNumber";
import RenameRuleTypeInUserNotificationRule from "./RenameRuleTypeInUserNotificationRule";
// This is the order in which the migrations will be run. Add new migrations to the end of the array.
@@ -85,6 +86,7 @@ const DataMigrations: Array<DataMigrationBase> = [
new AddServiceTypeColumnToMetricsTable(),
new AddIsSubscriptionConfirmedToSubscribers(),
new AddIncidentNumber(),
new RenameRuleTypeInUserNotificationRule(),
];
export default DataMigrations;

View File

@@ -0,0 +1,65 @@
import Project from "Common/Models/DatabaseModels/Project";
import DataMigrationBase from "./DataMigrationBase";
import LIMIT_MAX from "Common/Types/Database/LimitMax";
import UserNotificationRule from "Common/Models/DatabaseModels/UserNotificationRule";
import UserNotificationRuleService from "Common/Server/Services/UserNotificationRuleService";
import ProjectService from "Common/Server/Services/ProjectService";
export default class RenameRuleTypeInUserNotificationRule extends DataMigrationBase {
public constructor() {
super("RenameRuleTypeInUserNotificationRule");
}
public override async migrate(): Promise<void> {
// get all projects.
// for each project get all UserNotifiacationRules with ruleType ""When incident is created during on call"
// update ruleType to "When on-call policy is executed"
// update UserNotificationRule
const projects: Array<Project> = await ProjectService.findBy({
query: {},
select: {
_id: true,
},
skip: 0,
limit: LIMIT_MAX,
props: {
isRoot: true,
},
});
for (const project of projects) {
const userNotificationRules: Array<UserNotificationRule> =
await UserNotificationRuleService.findBy({
query: {
projectId: project._id,
ruleType: "When incident is created during on call" as any,
},
select: {
_id: true,
},
skip: 0,
limit: LIMIT_MAX,
props: {
isRoot: true,
},
});
for (const userNotificationRule of userNotificationRules) {
await UserNotificationRuleService.updateOneById({
id: userNotificationRule.id!,
data: {
ruleType: "When on-call policy is executed" as any,
},
props: {
isRoot: true,
},
});
}
}
}
public override async rollback(): Promise<void> {
return;
}
}

View File

@@ -70,7 +70,7 @@ RunCron(
select: {
_id: true,
title: true,
projectId: true,
projectId: true,
description: true,
monitor: {
name: true,

View File

@@ -67,27 +67,18 @@ const executeOnCallPolicy: ExecuteOnCallPolicyFunction = async (
executionLog: OnCallDutyPolicyExecutionLog,
): Promise<void> => {
try {
logger.debug(
`Executing on-call policy execution log: ${executionLog.id}`,
)
logger.debug(`Executing on-call policy execution log: ${executionLog.id}`);
// get trigger by alert
if (executionLog.triggeredByAlertId) {
logger.debug(
`Triggered by alert: ${executionLog.triggeredByAlertId}`,
)
logger.debug(`Triggered by alert: ${executionLog.triggeredByAlertId}`);
// check if this alert is ack.
const isAcknowledged: boolean = await AlertService.isAlertAcknowledged({
alertId: executionLog.triggeredByAlertId,
});
logger.debug(
`Alert is acknowledged: ${isAcknowledged}`,
)
logger.debug(`Alert is acknowledged: ${isAcknowledged}`);
if (isAcknowledged) {
// then mark this policy as executed.
@@ -107,10 +98,9 @@ const executeOnCallPolicy: ExecuteOnCallPolicyFunction = async (
// get trigger by incident
if (executionLog.triggeredByIncidentId) {
logger.debug(
`Triggered by incident: ${executionLog.triggeredByIncidentId}`,
)
);
// check if this incident is ack.
const isAcknowledged: boolean =
@@ -118,9 +108,7 @@ const executeOnCallPolicy: ExecuteOnCallPolicyFunction = async (
incidentId: executionLog.triggeredByIncidentId,
});
logger.debug(
`Incident is acknowledged: ${isAcknowledged}`,
)
logger.debug(`Incident is acknowledged: ${isAcknowledged}`);
if (isAcknowledged) {
// then mark this policy as executed.
@@ -189,8 +177,8 @@ const executeOnCallPolicy: ExecuteOnCallPolicyFunction = async (
if (
executionLog.onCallPolicyExecutionRepeatCount &&
executionLog.onCallPolicyExecutionRepeatCount <
executionLog.onCallDutyPolicy!
.repeatPolicyIfNoOneAcknowledgesNoOfTimes!
executionLog.onCallDutyPolicy!
.repeatPolicyIfNoOneAcknowledgesNoOfTimes!
) {
// repeating execution