|
|
@ -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;
|
|
|
|