mirror of
https://github.com/louislam/uptime-kuma.git
synced 2024-10-01 01:25:45 -04:00
Ssynchronize push monitor heartbeats to api calls
Includes a 1s buffer time to allow the push url to be called before the monitor is checked
This commit is contained in:
parent
d39dc94496
commit
39df4eea92
44
package-lock.json
generated
44
package-lock.json
generated
@ -26,7 +26,7 @@
|
|||||||
"check-password-strength": "^2.0.5",
|
"check-password-strength": "^2.0.5",
|
||||||
"command-exists": "~1.2.9",
|
"command-exists": "~1.2.9",
|
||||||
"compare-versions": "~3.6.0",
|
"compare-versions": "~3.6.0",
|
||||||
"dayjs": "~1.10.8",
|
"dayjs": "^1.11.0",
|
||||||
"express": "~4.17.3",
|
"express": "~4.17.3",
|
||||||
"express-basic-auth": "~1.2.1",
|
"express-basic-auth": "~1.2.1",
|
||||||
"favico.js": "^0.3.10",
|
"favico.js": "^0.3.10",
|
||||||
@ -49,7 +49,7 @@
|
|||||||
"prom-client": "~13.2.0",
|
"prom-client": "~13.2.0",
|
||||||
"prometheus-api-metrics": "~3.2.1",
|
"prometheus-api-metrics": "~3.2.1",
|
||||||
"qrcode": "~1.5.0",
|
"qrcode": "~1.5.0",
|
||||||
"redbean-node": "0.1.3",
|
"redbean-node": "0.1.4",
|
||||||
"socket.io": "~4.4.1",
|
"socket.io": "~4.4.1",
|
||||||
"socket.io-client": "~4.4.1",
|
"socket.io-client": "~4.4.1",
|
||||||
"socks-proxy-agent": "^6.1.1",
|
"socks-proxy-agent": "^6.1.1",
|
||||||
@ -5658,9 +5658,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/dayjs": {
|
"node_modules/dayjs": {
|
||||||
"version": "1.10.8",
|
"version": "1.11.0",
|
||||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.8.tgz",
|
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.0.tgz",
|
||||||
"integrity": "sha512-wbNwDfBHHur9UOzNUjeKUOJ0fCb0a52Wx0xInmQ7Y8FstyajiV1NmK1e00cxsr9YrE9r7yAChE0VvpuY5Rnlow=="
|
"integrity": "sha512-JLC809s6Y948/FuCZPm5IX8rRhQwOiyMb2TfVVQEixG7P8Lm/gt5S7yoQZmC8x1UehI9Pb7sksEt4xx14m+7Ug=="
|
||||||
},
|
},
|
||||||
"node_modules/debug": {
|
"node_modules/debug": {
|
||||||
"version": "4.3.4",
|
"version": "4.3.4",
|
||||||
@ -13939,15 +13939,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/redbean-node": {
|
"node_modules/redbean-node": {
|
||||||
"version": "0.1.3",
|
"version": "0.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/redbean-node/-/redbean-node-0.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/redbean-node/-/redbean-node-0.1.4.tgz",
|
||||||
"integrity": "sha512-itAouTnNK12QXy10DxScFRDv/R3Zt1sZw+tfUQCsBALxDDCNXVUdkNTgClouUwbTDG1YMQkeoD1Je9ujN7u3yg==",
|
"integrity": "sha512-c1U6wnTeWS0c44tn9hkJWzjGgckLNJ8sN1E2bxnnnQsULOfvEVFLf8dLMjqhyyMrZ1L1mp8UvV4OfhRtH/ZrgQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": "^14.17.7",
|
"@types/node": "^14.18.12",
|
||||||
"await-lock": "^2.1.0",
|
"await-lock": "^2.1.0",
|
||||||
"dayjs": "^1.10.6",
|
"dayjs": "^1.11.0",
|
||||||
"glob": "^7.1.7",
|
"glob": "^7.2.0",
|
||||||
"knex": "^0.95.9",
|
"knex": "^0.95.15",
|
||||||
"lodash": "^4.17.21"
|
"lodash": "^4.17.21"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -20965,9 +20965,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"dayjs": {
|
"dayjs": {
|
||||||
"version": "1.10.8",
|
"version": "1.11.0",
|
||||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.8.tgz",
|
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.0.tgz",
|
||||||
"integrity": "sha512-wbNwDfBHHur9UOzNUjeKUOJ0fCb0a52Wx0xInmQ7Y8FstyajiV1NmK1e00cxsr9YrE9r7yAChE0VvpuY5Rnlow=="
|
"integrity": "sha512-JLC809s6Y948/FuCZPm5IX8rRhQwOiyMb2TfVVQEixG7P8Lm/gt5S7yoQZmC8x1UehI9Pb7sksEt4xx14m+7Ug=="
|
||||||
},
|
},
|
||||||
"debug": {
|
"debug": {
|
||||||
"version": "4.3.4",
|
"version": "4.3.4",
|
||||||
@ -27229,15 +27229,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"redbean-node": {
|
"redbean-node": {
|
||||||
"version": "0.1.3",
|
"version": "0.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/redbean-node/-/redbean-node-0.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/redbean-node/-/redbean-node-0.1.4.tgz",
|
||||||
"integrity": "sha512-itAouTnNK12QXy10DxScFRDv/R3Zt1sZw+tfUQCsBALxDDCNXVUdkNTgClouUwbTDG1YMQkeoD1Je9ujN7u3yg==",
|
"integrity": "sha512-c1U6wnTeWS0c44tn9hkJWzjGgckLNJ8sN1E2bxnnnQsULOfvEVFLf8dLMjqhyyMrZ1L1mp8UvV4OfhRtH/ZrgQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/node": "^14.17.7",
|
"@types/node": "^14.18.12",
|
||||||
"await-lock": "^2.1.0",
|
"await-lock": "^2.1.0",
|
||||||
"dayjs": "^1.10.6",
|
"dayjs": "^1.11.0",
|
||||||
"glob": "^7.1.7",
|
"glob": "^7.2.0",
|
||||||
"knex": "^0.95.9",
|
"knex": "^0.95.15",
|
||||||
"lodash": "^4.17.21"
|
"lodash": "^4.17.21"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
@ -76,7 +76,7 @@
|
|||||||
"check-password-strength": "^2.0.5",
|
"check-password-strength": "^2.0.5",
|
||||||
"command-exists": "~1.2.9",
|
"command-exists": "~1.2.9",
|
||||||
"compare-versions": "~3.6.0",
|
"compare-versions": "~3.6.0",
|
||||||
"dayjs": "~1.10.8",
|
"dayjs": "^1.11.0",
|
||||||
"express": "~4.17.3",
|
"express": "~4.17.3",
|
||||||
"express-basic-auth": "~1.2.1",
|
"express-basic-auth": "~1.2.1",
|
||||||
"favico.js": "^0.3.10",
|
"favico.js": "^0.3.10",
|
||||||
@ -99,7 +99,7 @@
|
|||||||
"prom-client": "~13.2.0",
|
"prom-client": "~13.2.0",
|
||||||
"prometheus-api-metrics": "~3.2.1",
|
"prometheus-api-metrics": "~3.2.1",
|
||||||
"qrcode": "~1.5.0",
|
"qrcode": "~1.5.0",
|
||||||
"redbean-node": "0.1.3",
|
"redbean-node": "0.1.4",
|
||||||
"socket.io": "~4.4.1",
|
"socket.io": "~4.4.1",
|
||||||
"socket.io-client": "~4.4.1",
|
"socket.io-client": "~4.4.1",
|
||||||
"socks-proxy-agent": "^6.1.1",
|
"socks-proxy-agent": "^6.1.1",
|
||||||
|
@ -173,7 +173,7 @@ class Monitor extends BeanModel {
|
|||||||
|
|
||||||
let bean = R.dispense("heartbeat");
|
let bean = R.dispense("heartbeat");
|
||||||
bean.monitor_id = this.id;
|
bean.monitor_id = this.id;
|
||||||
bean.time = R.isoDateTime(dayjs.utc());
|
bean.time = R.isoDateTimeMillis(dayjs.utc());
|
||||||
bean.status = DOWN;
|
bean.status = DOWN;
|
||||||
|
|
||||||
if (this.isUpsideDown()) {
|
if (this.isUpsideDown()) {
|
||||||
@ -348,25 +348,30 @@ class Monitor extends BeanModel {
|
|||||||
bean.msg = dnsMessage;
|
bean.msg = dnsMessage;
|
||||||
bean.status = UP;
|
bean.status = UP;
|
||||||
} else if (this.type === "push") { // Type: Push
|
} else if (this.type === "push") { // Type: Push
|
||||||
const time = R.isoDateTime(dayjs.utc().subtract(this.interval, "second"));
|
log.debug(`[${this.name}] Checking monitor at ${dayjs().format("YYYY-MM-DD HH:mm:ss.SSS")}`);
|
||||||
|
const bufferTime = 1000; // 1s buffer to accommodate clock differences
|
||||||
let heartbeatCount = await R.count("heartbeat", " monitor_id = ? AND time > ? ", [
|
// Fix #922, since previous heartbeat could be inserted by api, it should get from database
|
||||||
this.id,
|
previousBeat = await Monitor.getPreviousHeartbeat(this.id);
|
||||||
time
|
//If the previous beat was nonexistent, down or pending we use the regular
|
||||||
]);
|
// beatInterval/retryInterval in the setTimeout further below
|
||||||
|
if (previousBeat) {
|
||||||
log.debug("monitor", "heartbeatCount" + heartbeatCount + " " + time);
|
const msSinceLastBeat = dayjs.utc().valueOf() - dayjs.utc(previousBeat.time).valueOf();
|
||||||
|
log.debug(`[${this.name}] msSinceLastBeat = ${msSinceLastBeat}`);
|
||||||
if (heartbeatCount <= 0) {
|
if (previousBeat.status !== UP || msSinceLastBeat > beatInterval * 1000 + bufferTime) {
|
||||||
// Fix #922, since previous heartbeat could be inserted by api, it should get from database
|
throw new Error("No heartbeat in the time window");
|
||||||
previousBeat = await Monitor.getPreviousHeartbeat(this.id);
|
} else {
|
||||||
|
let timeout = beatInterval * 1000 - msSinceLastBeat;
|
||||||
throw new Error("No heartbeat in the time window");
|
if (timeout < 0) {
|
||||||
} else {
|
timeout = bufferTime;
|
||||||
// No need to insert successful heartbeat for push type, so end here
|
} else {
|
||||||
retries = 0;
|
timeout += bufferTime;
|
||||||
this.heartbeatInterval = setTimeout(beat, beatInterval * 1000);
|
}
|
||||||
return;
|
// No need to insert successful heartbeat for push type, so end here
|
||||||
|
retries = 0;
|
||||||
|
log.debug(`[${this.name}] timeout = ${timeout}`);
|
||||||
|
this.heartbeatInterval = setTimeout(beat, timeout);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (this.type === "steam") {
|
} else if (this.type === "steam") {
|
||||||
@ -694,7 +699,7 @@ class Monitor extends BeanModel {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Handle new monitor with only one beat, because the beat's duration = 0
|
// Handle new monitor with only one beat, because the beat's duration = 0
|
||||||
let status = parseInt(await R.getCell("SELECT `status` FROM heartbeat WHERE monitor_id = ?", [monitorID]));
|
let status = parseInt(await R.getCell("SELECT `status` FROM heartbeat WHERE monitor_id = ?", [ monitorID ]));
|
||||||
|
|
||||||
if (status === UP) {
|
if (status === UP) {
|
||||||
uptime = 1;
|
uptime = 1;
|
||||||
|
@ -55,7 +55,7 @@ router.get("/api/push/:pushToken", async (request, response) => {
|
|||||||
let duration = 0;
|
let duration = 0;
|
||||||
|
|
||||||
let bean = R.dispense("heartbeat");
|
let bean = R.dispense("heartbeat");
|
||||||
bean.time = R.isoDateTime(dayjs.utc());
|
bean.time = R.isoDateTimeMillis(dayjs.utc());
|
||||||
|
|
||||||
if (previousHeartbeat) {
|
if (previousHeartbeat) {
|
||||||
isFirstBeat = false;
|
isFirstBeat = false;
|
||||||
@ -63,8 +63,9 @@ router.get("/api/push/:pushToken", async (request, response) => {
|
|||||||
duration = dayjs(bean.time).diff(dayjs(previousHeartbeat.time), "second");
|
duration = dayjs(bean.time).diff(dayjs(previousHeartbeat.time), "second");
|
||||||
}
|
}
|
||||||
|
|
||||||
log.debug("router", "PreviousStatus: " + previousStatus);
|
log.debug(`/api/push/ called at ${dayjs().format("YYYY-MM-DD HH:mm:ss.SSS")}`);
|
||||||
log.debug("router", "Current Status: " + status);
|
log.debug("PreviousStatus: " + previousStatus);
|
||||||
|
log.debug("Current Status: " + status);
|
||||||
|
|
||||||
bean.important = Monitor.isImportantBeat(isFirstBeat, previousStatus, status);
|
bean.important = Monitor.isImportantBeat(isFirstBeat, previousStatus, status);
|
||||||
bean.monitor_id = monitor.id;
|
bean.monitor_id = monitor.id;
|
||||||
|
Loading…
Reference in New Issue
Block a user