diff --git a/db/patch-monitor-add-resend-interval.sql b/db/patch-monitor-add-resend-interval.sql new file mode 100644 index 000000000..8e28bf693 --- /dev/null +++ b/db/patch-monitor-add-resend-interval.sql @@ -0,0 +1,10 @@ +-- You should not modify if this have pushed to Github, unless it does serious wrong with the db. +BEGIN TRANSACTION; + +ALTER TABLE monitor + ADD resend_interval INTEGER default 0 not null; + +ALTER TABLE heartbeat + ADD down_count INTEGER default 0 not null; + +COMMIT; diff --git a/server/database.js b/server/database.js index 607ecedec..b1a23a475 100644 --- a/server/database.js +++ b/server/database.js @@ -63,6 +63,7 @@ class Database { "patch-add-sqlserver-monitor.sql": true, "patch-add-other-auth.sql": { parents: [ "patch-monitor-basic-auth.sql" ] }, "patch-add-radius-monitor.sql": true, + "patch-monitor-add-resend-interval.sql": true, }; /** diff --git a/server/model/monitor.js b/server/model/monitor.js index dd752143b..f96b4df06 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -79,6 +79,7 @@ class Monitor extends BeanModel { type: this.type, interval: this.interval, retryInterval: this.retryInterval, + resendInterval: this.resendInterval, keyword: this.keyword, expiryNotification: this.isEnabledExpiryNotification(), ignoreTls: this.getIgnoreTls(), @@ -214,6 +215,7 @@ class Monitor extends BeanModel { bean.monitor_id = this.id; bean.time = R.isoDateTimeMillis(dayjs.utc()); bean.status = DOWN; + bean.downCount = previousBeat?.downCount || 0; if (this.isUpsideDown()) { bean.status = flipStatus(bean.status); @@ -594,12 +596,27 @@ class Monitor extends BeanModel { log.debug("monitor", `[${this.name}] sendNotification`); await Monitor.sendNotification(isFirstBeat, this, bean); + // Reset down count + bean.downCount = 0; + // Clear Status Page Cache log.debug("monitor", `[${this.name}] apicache clear`); apicache.clear(); } else { bean.important = false; + + if (bean.status === DOWN && this.resendInterval > 0) { + ++bean.downCount; + if (bean.downCount >= this.resendInterval) { + // Send notification again, because we are still DOWN + log.debug("monitor", `[${this.name}] sendNotification again: Down Count: ${bean.downCount} | Resend Interval: ${this.resendInterval}`); + await Monitor.sendNotification(isFirstBeat, this, bean); + + // Reset down count + bean.downCount = 0; + } + } } if (bean.status === UP) { @@ -610,7 +627,7 @@ class Monitor extends BeanModel { } log.warn("monitor", `Monitor #${this.id} '${this.name}': Pending: ${bean.msg} | Max retries: ${this.maxretries} | Retry: ${retries} | Retry Interval: ${beatInterval} seconds | Type: ${this.type}`); } else { - log.warn("monitor", `Monitor #${this.id} '${this.name}': Failing: ${bean.msg} | Interval: ${beatInterval} seconds | Type: ${this.type}`); + log.warn("monitor", `Monitor #${this.id} '${this.name}': Failing: ${bean.msg} | Interval: ${beatInterval} seconds | Type: ${this.type} | Down Count: ${bean.downCount} | Resend Interval: ${this.resendInterval}`); } log.debug("monitor", `[${this.name}] Send to socket`); diff --git a/server/server.js b/server/server.js index 859c2313b..818bd7d12 100644 --- a/server/server.js +++ b/server/server.js @@ -669,6 +669,7 @@ let needSetup = false; bean.basic_auth_pass = monitor.basic_auth_pass; bean.interval = monitor.interval; bean.retryInterval = monitor.retryInterval; + bean.resendInterval = monitor.resendInterval; bean.hostname = monitor.hostname; bean.maxretries = monitor.maxretries; bean.port = parseInt(monitor.port); @@ -1278,6 +1279,7 @@ let needSetup = false; authDomain: monitorListData[i].authDomain, interval: monitorListData[i].interval, retryInterval: retryInterval, + resendInterval: monitorListData[i].resendInterval || 0, hostname: monitorListData[i].hostname, maxretries: monitorListData[i].maxretries, port: monitorListData[i].port, diff --git a/src/languages/de-DE.js b/src/languages/de-DE.js index 3df13b945..ef47909c7 100644 --- a/src/languages/de-DE.js +++ b/src/languages/de-DE.js @@ -165,7 +165,10 @@ export default { Pink: "Pink", "Search...": "Suchen...", "Heartbeat Retry Interval": "Überprüfungsintervall", + "Resend Notification if Down X times consequently": "Benachrichtigung erneut senden, wenn Inaktiv X mal hintereinander", retryCheckEverySecond: "Alle {0} Sekunden neu versuchen", + resendEveryXTimes: "Erneut versenden alle {0} mal", + resendDisabled: "Erneut versenden deaktiviert", "Import Backup": "Backup importieren", "Export Backup": "Backup exportieren", "Avg. Ping": "Durchschn. Ping", diff --git a/src/languages/en.js b/src/languages/en.js index 539d0c61a..3bb025858 100644 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -2,6 +2,8 @@ export default { languageName: "English", checkEverySecond: "Check every {0} seconds", retryCheckEverySecond: "Retry every {0} seconds", + resendEveryXTimes: "Resend every {0} times", + resendDisabled: "Resend disabled", retriesDescription: "Maximum retries before the service is marked as down and a notification is sent", ignoreTLSError: "Ignore TLS/SSL error for HTTPS websites", upsideDownModeDescription: "Flip the status upside down. If the service is reachable, it is DOWN.", @@ -72,6 +74,7 @@ export default { "Heartbeat Interval": "Heartbeat Interval", Retries: "Retries", "Heartbeat Retry Interval": "Heartbeat Retry Interval", + "Resend Notification if Down X times consequently": "Resend Notification if Down X times consequently", Advanced: "Advanced", "Upside Down Mode": "Upside Down Mode", "Max. Redirects": "Max. Redirects", diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 82859a4ff..99cbeb95f 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -275,6 +275,15 @@ +