diff --git a/server/src/index.ts b/server/src/index.ts index 2f9124d0e..8623fc803 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -49,6 +49,9 @@ const createApp = async () => { app.listen(port, "0.0.0.0", () => { indexLogger.info(`Server is running on http://localhost:${port}`); indexLogger.error(new ApiError("Test error logging", 500)); + indexLogger.warn("test", { + testKey: "testValue", + }); }); }; diff --git a/server/src/logger/Logger.ts b/server/src/logger/Logger.ts index 996cbf701..d2a519c4e 100644 --- a/server/src/logger/Logger.ts +++ b/server/src/logger/Logger.ts @@ -11,6 +11,9 @@ const buildLogMsg = (info: winston.Logform.TransformableInfo) => { const message = info.message; const service = info.service; const stack = info.stack || ""; + const { ...meta } = info; + const metaString = + Object.keys(meta).length > 0 ? ` | meta: ${JSON.stringify(meta)}` : ""; return `[${timestamp}]${ service ? ` [${service}]` : "" } ${level}: ${message} ${stack}`; diff --git a/server/src/services/infrastructure/NotificationService.ts b/server/src/services/infrastructure/NotificationService.ts index 21c8088f2..8238f729e 100644 --- a/server/src/services/infrastructure/NotificationService.ts +++ b/server/src/services/infrastructure/NotificationService.ts @@ -69,41 +69,66 @@ class NotificationService implements INotificationService { _id: { $in: notificationIds }, }); - for (const channel of notificationChannels) { - // Implement sending logic based on channel.type and channel.config - let service; - switch (channel.type) { - case "email": - await this.emailService.sendMessage( - this.emailService.buildAlert(monitor, incident), - channel - ); - break; - case "slack": - await this.slackService.sendMessage( - this.slackService.buildAlert(monitor, incident), - channel - ); - break; - case "discord": - await this.discordService.sendMessage( - this.discordService.buildAlert(monitor, incident), - channel - ); - break; - case "webhook": - await this.webhookService.sendMessage( - this.webhookService.buildAlert(monitor, incident), - channel - ); - break; - default: - logger.warn(`Unknown notification channel type: ${channel.type}`); - } + const tasks = notificationChannels.map((channel) => + this.sendForChannel(channel, monitor, incident) + ); + + const results = await Promise.allSettled(tasks); + + const succeeded = results.filter((r) => r.status === "fulfilled").length; + const failed = results.filter((r) => r.status === "rejected"); + + if (failed.length > 0) { + logger.warn( + `Notification send completed with ${succeeded} success, ${failed.length} failure(s)` + ); + failed.forEach((r) => { + logger.debug( + "Notification send failure", + (r as PromiseRejectedResult).reason + ); + }); } + return; }; + private sendForChannel = async ( + channel: INotificationChannel, + monitor: IMonitor, + incident: IIncident + ): Promise => { + switch (channel.type) { + case "email": + await this.emailService.sendMessage( + this.emailService.buildAlert(monitor, incident), + channel + ); + return; + case "slack": + await this.slackService.sendMessage( + this.slackService.buildAlert(monitor, incident), + channel + ); + return; + case "discord": + await this.discordService.sendMessage( + this.discordService.buildAlert(monitor, incident), + channel + ); + return; + case "webhook": + await this.webhookService.sendMessage( + this.webhookService.buildAlert(monitor, incident), + channel + ); + return; + default: + logger.warn(`Unknown notification channel type: ${channel.type}`); + return; + } + }; + private testNotification = async ( channel: INotificationChannel, results: any[]