From 071a7fc9cf0e8307c9fd6921b7ac4a8ea3e0dc1d Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Mon, 2 Sep 2024 10:45:07 -0700 Subject: [PATCH 1/3] Add indeterminate state to monitors --- Client/src/Components/Label/index.jsx | 8 ++- Client/src/Pages/Monitors/Home/host.jsx | 3 +- .../src/Pages/Monitors/Home/monitorData.jsx | 14 +++-- Server/controllers/monitorController.js | 1 + Server/models/Monitor.js | 4 +- Server/service/jobQueue.js | 1 - Server/service/networkService.js | 62 ++++++++++++------- 7 files changed, 60 insertions(+), 33 deletions(-) diff --git a/Client/src/Components/Label/index.jsx b/Client/src/Components/Label/index.jsx index 0799a87d7..96468ffd6 100644 --- a/Client/src/Components/Label/index.jsx +++ b/Client/src/Components/Label/index.jsx @@ -126,6 +126,7 @@ ColoredLabel.propTypes = { */ const StatusLabel = ({ status, text, customStyles }) => { + console.log(status); const theme = useTheme(); const colors = { up: { @@ -138,6 +139,11 @@ const StatusLabel = ({ status, text, customStyles }) => { bgColor: theme.palette.error.bg, borderColor: theme.palette.error.light, }, + unknown: { + dotColor: theme.palette.unresolved.main, + bgColor: theme.palette.unresolved.bg, + borderColor: theme.palette.unresolved.light, + }, "cannot resolve": { dotColor: theme.palette.unresolved.main, bgColor: theme.palette.unresolved.bg, @@ -170,7 +176,7 @@ const StatusLabel = ({ status, text, customStyles }) => { }; StatusLabel.propTypes = { - status: PropTypes.oneOf(["up", "down", "cannot resolve"]), + status: PropTypes.oneOf(["up", "down", "unknown", "cannot resolve"]), text: PropTypes.string, customStyles: PropTypes.object, }; diff --git a/Client/src/Pages/Monitors/Home/host.jsx b/Client/src/Pages/Monitors/Home/host.jsx index d450a53f4..9e6a71a05 100644 --- a/Client/src/Pages/Monitors/Home/host.jsx +++ b/Client/src/Pages/Monitors/Home/host.jsx @@ -53,7 +53,8 @@ Host.propTypes = { params: PropTypes.shape({ title: PropTypes.string, percentageColor: PropTypes.string, - percentage: PropTypes.number, + percentage: PropTypes.string, + url: PropTypes.string, }).isRequired, }; diff --git a/Client/src/Pages/Monitors/Home/monitorData.jsx b/Client/src/Pages/Monitors/Home/monitorData.jsx index d3fd66958..28ff08756 100644 --- a/Client/src/Pages/Monitors/Home/monitorData.jsx +++ b/Client/src/Pages/Monitors/Home/monitorData.jsx @@ -35,8 +35,8 @@ export const buildData = (monitors, isAdmin, navigate) => { if (monitor.uptimePercentage !== undefined) { uptimePercentage = monitor.uptimePercentage === 0 - ? "0" - : (monitor.uptimePercentage * 100).toFixed(2); + ? "0" + : (monitor.uptimePercentage * 100).toFixed(2); } const params = { @@ -47,7 +47,12 @@ export const buildData = (monitors, isAdmin, navigate) => { monitor.status === true ? theme.palette.success.main : theme.palette.error.text, - status: monitor.status === true ? "up" : "down", + status: + monitor.status === undefined + ? "unknown" + : monitor.status === true + ? "up" + : "down", }; // Reverse checks so latest check is on the right @@ -86,6 +91,3 @@ export const buildData = (monitors, isAdmin, navigate) => { }); return data; }; - - - diff --git a/Server/controllers/monitorController.js b/Server/controllers/monitorController.js index f33ddcf10..702b28be4 100644 --- a/Server/controllers/monitorController.js +++ b/Server/controllers/monitorController.js @@ -359,6 +359,7 @@ const pauseMonitor = async (req, res, next) => { await req.jobQueue.addJob(monitor._id, monitor); } monitor.isActive = !monitor.isActive; + monitor.status = undefined; monitor.save(); return res.status(200).json({ success: true, diff --git a/Server/models/Monitor.js b/Server/models/Monitor.js index fdc147d1b..d91275e23 100644 --- a/Server/models/Monitor.js +++ b/Server/models/Monitor.js @@ -24,7 +24,7 @@ const MonitorSchema = mongoose.Schema( }, status: { type: Boolean, - default: true, + default: undefined, }, type: { type: String, @@ -46,7 +46,7 @@ const MonitorSchema = mongoose.Schema( }, uptimePercentage: { type: Number, - default: undefined, + default: undefined, }, notifications: [ { diff --git a/Server/service/jobQueue.js b/Server/service/jobQueue.js index ed15e0f94..5248c88fa 100644 --- a/Server/service/jobQueue.js +++ b/Server/service/jobQueue.js @@ -238,7 +238,6 @@ class JobQueue { console.log("Adding job", payload.url); // Execute job immediately await this.queue.add(jobName, payload); - await this.queue.add(jobName, payload, { repeat: { every: payload.interval, diff --git a/Server/service/networkService.js b/Server/service/networkService.js index f5c333a60..e9d44a5b3 100644 --- a/Server/service/networkService.js +++ b/Server/service/networkService.js @@ -15,10 +15,31 @@ class NetworkService { this.NETWORK_ERROR = 5000; } - async handleNotification(job, isAlive) { + async handleNotification(monitor, isAlive) { + let template = + isAlive === true ? "serverIsUpTemplate" : "serverIsDownTemplate"; + let status = isAlive === true ? "up" : "down"; + + const notifications = await this.db.getNotificationsByMonitorId( + monitor._id + ); + for (const notification of notifications) { + if (notification.type === "email") { + await this.emailService.buildAndSendEmail( + template, + { monitorName: monitor.name, monitorUrl: monitor.url }, + notification.address, + `Monitor ${monitor.name} is ${status}` + ); + } + } + } + + async handleStatusUpdate(job, isAlive) { try { const { _id } = job.data; const monitor = await this.db.getMonitorById(_id); + if (monitor === null || monitor === undefined) { logger.error(`Null Monitor: ${_id}`, { method: "handleNotification", @@ -28,25 +49,22 @@ class NetworkService { return; } - // If monitor status changes, update monitor status and send notification - if (monitor.status !== isAlive) { - monitor.status = !monitor.status; + // Two general cases: + // 1. Monitor status is undefined + // 2. Monitor status is defined + + // If the monitor status is undefined, set it's status to isAlive. if isAlive is false, send notification + if (monitor.status === undefined) { + monitor.status = isAlive; await monitor.save(); - - let template = - isAlive === true ? "serverIsUpTemplate" : "serverIsDownTemplate"; - let status = isAlive === true ? "up" : "down"; - - const notifications = await this.db.getNotificationsByMonitorId(_id); - for (const notification of notifications) { - if (notification.type === "email") { - await this.emailService.buildAndSendEmail( - template, - { monitorName: monitor.name, monitorUrl: monitor.url }, - notification.address, - `Monitor ${monitor.name} is ${status}` - ); - } + if (isAlive === false) { + this.handleNotification(monitor, isAlive); + } + } else { + if (monitor.status !== isAlive) { + monitor.status = !monitor.status; + await monitor.save(); + this.handleNotification(monitor, isAlive); } } } catch (error) { @@ -113,7 +131,7 @@ class NetworkService { }; return await this.logAndStoreCheck(checkData, this.db.createCheck); } finally { - this.handleNotification(job, isAlive); + this.handleStatusUpdate(job, isAlive); } } @@ -161,7 +179,7 @@ class NetworkService { return await this.logAndStoreCheck(checkData, this.db.createCheck); } finally { - this.handleNotification(job, isAlive); + this.handleStatusUpdate(job, isAlive); } } @@ -241,7 +259,7 @@ class NetworkService { }; this.logAndStoreCheck(checkData, this.db.createPageSpeedCheck); } finally { - this.handleNotification(job, isAlive); + this.handleStatusUpdate(job, isAlive); } } From 4d61ecfe35bfd6187e73e7ee229220fa51442d03 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Mon, 2 Sep 2024 10:52:11 -0700 Subject: [PATCH 2/3] Add error handling to notifications --- Server/service/networkService.js | 40 +++++++++++++++++++------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/Server/service/networkService.js b/Server/service/networkService.js index e9d44a5b3..23b115c97 100644 --- a/Server/service/networkService.js +++ b/Server/service/networkService.js @@ -16,22 +16,30 @@ class NetworkService { } async handleNotification(monitor, isAlive) { - let template = - isAlive === true ? "serverIsUpTemplate" : "serverIsDownTemplate"; - let status = isAlive === true ? "up" : "down"; + try { + let template = + isAlive === true ? "serverIsUpTemplate" : "serverIsDownTemplate"; + let status = isAlive === true ? "up" : "down"; - const notifications = await this.db.getNotificationsByMonitorId( - monitor._id - ); - for (const notification of notifications) { - if (notification.type === "email") { - await this.emailService.buildAndSendEmail( - template, - { monitorName: monitor.name, monitorUrl: monitor.url }, - notification.address, - `Monitor ${monitor.name} is ${status}` - ); + const notifications = await this.db.getNotificationsByMonitorId( + monitor._id + ); + for (const notification of notifications) { + if (notification.type === "email") { + await this.emailService.buildAndSendEmail( + template, + { monitorName: monitor.name, monitorUrl: monitor.url }, + notification.address, + `Monitor ${monitor.name} is ${status}` + ); + } } + } catch (error) { + logger.error(error.message, { + method: "handleNotification", + service: this.SERVICE_NAME, + monitorId: monitor._id, + }); } } @@ -42,7 +50,7 @@ class NetworkService { if (monitor === null || monitor === undefined) { logger.error(`Null Monitor: ${_id}`, { - method: "handleNotification", + method: "handleStatusUpdate", service: this.SERVICE_NAME, jobId: job.id, }); @@ -69,7 +77,7 @@ class NetworkService { } } catch (error) { logger.error(error.message, { - method: "handleNotification", + method: "handleStatusUpdate", service: this.SERVICE_NAME, jobId: job.id, }); From d2528a694e23151a9890d778e7e045a1a626b32a Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Mon, 2 Sep 2024 11:00:59 -0700 Subject: [PATCH 3/3] simplified conditionals for updating status and sending notifications --- Server/service/networkService.js | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/Server/service/networkService.js b/Server/service/networkService.js index 23b115c97..863349dbf 100644 --- a/Server/service/networkService.js +++ b/Server/service/networkService.js @@ -56,22 +56,12 @@ class NetworkService { }); return; } - - // Two general cases: - // 1. Monitor status is undefined - // 2. Monitor status is defined - - // If the monitor status is undefined, set it's status to isAlive. if isAlive is false, send notification - if (monitor.status === undefined) { + if (monitor.status === undefined || monitor.status !== isAlive) { + const oldStatus = monitor.status; monitor.status = isAlive; await monitor.save(); - if (isAlive === false) { - this.handleNotification(monitor, isAlive); - } - } else { - if (monitor.status !== isAlive) { - monitor.status = !monitor.status; - await monitor.save(); + + if (oldStatus !== undefined && oldStatus !== isAlive) { this.handleNotification(monitor, isAlive); } }