Merge branch 'master' into feature/mariadb-add-connection-socket-config
This commit is contained in:
commit
734716acb4
@ -1505,24 +1505,46 @@ class Monitor extends BeanModel {
|
||||
|
||||
let msg = `[${monitor.name}] [${text}] ${bean.msg}`;
|
||||
|
||||
const heartbeatJSON = await bean.toJSONAsync({ decodeResponse: true });
|
||||
const monitorData = [{ id: monitor.id, active: monitor.active, name: monitor.name }];
|
||||
const preloadData = await Monitor.preparePreloadData(monitorData);
|
||||
// Prevent if the msg is undefined, notifications such as Discord cannot send out.
|
||||
if (!heartbeatJSON["msg"]) {
|
||||
heartbeatJSON["msg"] = "N/A";
|
||||
}
|
||||
|
||||
// Also provide the time in server timezone
|
||||
heartbeatJSON["timezone"] = await UptimeKumaServer.getInstance().getTimezone();
|
||||
heartbeatJSON["timezoneOffset"] = UptimeKumaServer.getInstance().getTimezoneOffset();
|
||||
heartbeatJSON["localDateTime"] = dayjs
|
||||
.utc(heartbeatJSON["time"])
|
||||
.tz(heartbeatJSON["timezone"])
|
||||
.format(SQL_DATETIME_FORMAT);
|
||||
|
||||
// Calculate downtime tracking information when service comes back up
|
||||
// This makes downtime information available to all notification providers
|
||||
if (bean.status === UP && monitor.id) {
|
||||
try {
|
||||
const lastDownHeartbeat = await R.getRow(
|
||||
"SELECT time FROM heartbeat WHERE monitor_id = ? AND status = ? ORDER BY time DESC LIMIT 1",
|
||||
[monitor.id, DOWN]
|
||||
);
|
||||
|
||||
if (lastDownHeartbeat && lastDownHeartbeat.time) {
|
||||
heartbeatJSON["lastDownTime"] = lastDownHeartbeat.time;
|
||||
}
|
||||
} catch (error) {
|
||||
// If we can't calculate downtime, just continue without it
|
||||
// Silently fail to avoid disrupting notification sending
|
||||
log.debug(
|
||||
"monitor",
|
||||
`[${monitor.name}] Could not calculate downtime information: ${error.message}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for (let notification of notificationList) {
|
||||
try {
|
||||
const heartbeatJSON = await bean.toJSONAsync({ decodeResponse: true });
|
||||
const monitorData = [{ id: monitor.id, active: monitor.active, name: monitor.name }];
|
||||
const preloadData = await Monitor.preparePreloadData(monitorData);
|
||||
// Prevent if the msg is undefined, notifications such as Discord cannot send out.
|
||||
if (!heartbeatJSON["msg"]) {
|
||||
heartbeatJSON["msg"] = "N/A";
|
||||
}
|
||||
|
||||
// Also provide the time in server timezone
|
||||
heartbeatJSON["timezone"] = await UptimeKumaServer.getInstance().getTimezone();
|
||||
heartbeatJSON["timezoneOffset"] = UptimeKumaServer.getInstance().getTimezoneOffset();
|
||||
heartbeatJSON["localDateTime"] = dayjs
|
||||
.utc(heartbeatJSON["time"])
|
||||
.tz(heartbeatJSON["timezone"])
|
||||
.format(SQL_DATETIME_FORMAT);
|
||||
|
||||
await Notification.send(
|
||||
JSON.parse(notification.config),
|
||||
msg,
|
||||
|
||||
@ -56,6 +56,8 @@ class Discord extends NotificationProvider {
|
||||
// If heartbeatJSON is not null, we go into the normal alerting loop.
|
||||
let addess = this.extractAddress(monitorJSON);
|
||||
if (heartbeatJSON["status"] === DOWN) {
|
||||
const wentOfflineTimestamp = Math.floor(new Date(heartbeatJSON["time"]).getTime() / 1000);
|
||||
|
||||
let discorddowndata = {
|
||||
username: discordDisplayName,
|
||||
embeds: [
|
||||
@ -76,6 +78,11 @@ class Discord extends NotificationProvider {
|
||||
},
|
||||
]
|
||||
: []),
|
||||
{
|
||||
name: "Went Offline",
|
||||
// F for full date/time
|
||||
value: `<t:${wentOfflineTimestamp}:F>`,
|
||||
},
|
||||
{
|
||||
name: `Time (${heartbeatJSON["timezone"]})`,
|
||||
value: heartbeatJSON["localDateTime"],
|
||||
@ -104,6 +111,14 @@ class Discord extends NotificationProvider {
|
||||
await axios.post(webhookUrl.toString(), discorddowndata, config);
|
||||
return okMsg;
|
||||
} else if (heartbeatJSON["status"] === UP) {
|
||||
const backOnlineTimestamp = Math.floor(new Date(heartbeatJSON["time"]).getTime() / 1000);
|
||||
let downtimeDuration = null;
|
||||
let wentOfflineTimestamp = null;
|
||||
if (heartbeatJSON["lastDownTime"]) {
|
||||
wentOfflineTimestamp = Math.floor(new Date(heartbeatJSON["lastDownTime"]).getTime() / 1000);
|
||||
downtimeDuration = this.formatDuration(backOnlineTimestamp - wentOfflineTimestamp);
|
||||
}
|
||||
|
||||
let discordupdata = {
|
||||
username: discordDisplayName,
|
||||
embeds: [
|
||||
@ -124,10 +139,23 @@ class Discord extends NotificationProvider {
|
||||
},
|
||||
]
|
||||
: []),
|
||||
{
|
||||
name: `Time (${heartbeatJSON["timezone"]})`,
|
||||
value: heartbeatJSON["localDateTime"],
|
||||
},
|
||||
...(wentOfflineTimestamp
|
||||
? [
|
||||
{
|
||||
name: "Went Offline",
|
||||
// F for full date/time
|
||||
value: `<t:${wentOfflineTimestamp}:F>`,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...(downtimeDuration
|
||||
? [
|
||||
{
|
||||
name: "Downtime Duration",
|
||||
value: downtimeDuration,
|
||||
},
|
||||
]
|
||||
: []),
|
||||
...(heartbeatJSON["ping"] != null
|
||||
? [
|
||||
{
|
||||
@ -162,6 +190,32 @@ class Discord extends NotificationProvider {
|
||||
this.throwGeneralAxiosError(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Format duration as human-readable string (e.g., "1h 23m", "45m 30s")
|
||||
* TODO: Update below to `Intl.DurationFormat("en", { style: "short" }).format(duration)` once we are on a newer node version
|
||||
* @param {number} timeInSeconds The time in seconds to format a duration for
|
||||
* @returns {string} The formatted duration
|
||||
*/
|
||||
formatDuration(timeInSeconds) {
|
||||
const hours = Math.floor(timeInSeconds / 3600);
|
||||
const minutes = Math.floor((timeInSeconds % 3600) / 60);
|
||||
const seconds = timeInSeconds % 60;
|
||||
|
||||
const durationParts = [];
|
||||
if (hours > 0) {
|
||||
durationParts.push(`${hours}h`);
|
||||
}
|
||||
if (minutes > 0) {
|
||||
durationParts.push(`${minutes}m`);
|
||||
}
|
||||
if (seconds > 0 && hours === 0) {
|
||||
// Only show seconds if less than an hour
|
||||
durationParts.push(`${seconds}s`);
|
||||
}
|
||||
|
||||
return durationParts.length > 0 ? durationParts.join(" ") : "0s";
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Discord;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user