diff --git a/package-lock.json b/package-lock.json index 92c91a9351..5c63aafbd6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "uptime-kuma", - "version": "1.0.5", + "version": "1.0.6", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/server/model/monitor.js b/server/model/monitor.js index f81f6e00e2..b757ae98fb 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -46,12 +46,11 @@ class Monitor extends BeanModel { start(io) { let previousBeat = null; - const beat = async () => { if (! previousBeat) { previousBeat = await R.findOne("heartbeat", " monitor_id = ? ORDER BY time DESC", [ this.id - ]) + ]); } let bean = R.dispense("heartbeat") @@ -111,9 +110,13 @@ class Monitor extends BeanModel { bean.msg = error.message; } - // Mark as important if status changed - if (! previousBeat || previousBeat.status !== bean.status) { - bean.important = true; + // Do the nottifications if status changed or if two subsequent beats are faulty + if (! previousBeat || previousBeat.status !== bean.status || (previousBeat && previousBeat.status !== 1 && bean.status != 1)) { + // Don't mark as important two subsequent faulty beats + let repeatedFailures = (previousBeat && previousBeat.status !== 1 && bean.status != 1); + let goUpAfterRepeatedFailures = false; + if(repeatedFailures) bean.important = false; + else bean.important = true; // Do not send if first beat is UP if (previousBeat || bean.status !== 1) { @@ -133,7 +136,24 @@ class Monitor extends BeanModel { let msg = `[${this.name}] [${text}] ${bean.msg}`; for(let notification of notificationList) { - promiseList.push(Notification.send(JSON.parse(notification.config), msg, await this.toJSON(), bean.toJSON())); + let notificationConfig = JSON.parse(notification.config); + //Check for how many subsequent failures should happen before sending the notification + notificationConfig.failThreshold = notificationConfig.failThreshold || 1; + if(repeatedFailures && notificationConfig.failThreshold > 1) { + let limit = notificationConfig.failThreshold; + let query = await R.find("heartbeat", " monitor_id = ? ORDER BY time DESC LIMIT " + limit, [ + this.id + ]); + query = query.map(val => val.status); + // All the heartbeats are failed except the oldest one + // Current beat is failed too + goUpAfterRepeatedFailures = query.slice(0,-1).every( val => val === query[0] ); + repeatedFailures = bean.status !== 1 && bean.status === query[0] && query.slice(0,-1).every( val => val === query[0] ) && [...query].reverse()[0] !== [...query].reverse()[1]; + } + if((notificationConfig.failThreshold <= 1 && bean.status === 1) || + (notificationConfig.failThreshold > 1 && bean.status === 1 && goUpAfterRepeatedFailures) || + (notificationConfig.failThreshold <= 1 && !repeatedFailures) || + (notificationConfig.failThreshold > 1 && repeatedFailures)) promiseList.push(Notification.send(notificationConfig, msg, await this.toJSON(), bean.toJSON())); } await Promise.all(promiseList); diff --git a/server/server.js b/server/server.js index 0d0ce51f11..714b86957f 100644 --- a/server/server.js +++ b/server/server.js @@ -398,6 +398,9 @@ let needSetup = false; try { checkLogin(socket) + //Sanitize the threshold + notification.failThreshold = Math.abs(parseInt(notification.failThreshold) || 1); + await Notification.save(notification, notificationID, socket.userID) await sendNotificationList(socket) diff --git a/src/components/NotificationDialog.vue b/src/components/NotificationDialog.vue index 6477ef7663..cabf093c0b 100644 --- a/src/components/NotificationDialog.vue +++ b/src/components/NotificationDialog.vue @@ -30,6 +30,14 @@ +
+ + +
+

Only positive integer numbers allowed. Numbers higher than 1 may cause more heavy queries & more load for the server!

+
+
+