Add Overall Status and Uptime to DashboardHome

- expand sended stats with sendAverageUptime(duration)
- Display 24h, 7d, 30d, 90d average uptime of all monitors
- Change Uptime.vue component to support displaying average uptime of all monitors

Issue #312
This commit is contained in:
Lucas 2021-09-18 04:27:52 +02:00
parent c3122a9807
commit f1c6900f51
22 changed files with 580 additions and 7 deletions

View file

@ -372,6 +372,10 @@ class Monitor extends BeanModel {
await Monitor.sendAvgPing(24, io, monitorID, userID);
await Monitor.sendUptime(24, io, monitorID, userID);
await Monitor.sendUptime(24 * 30, io, monitorID, userID);
await Monitor.sendAverageUptime(24, io, userID);
await Monitor.sendAverageUptime(24 * 7, io, userID);
await Monitor.sendAverageUptime(24 * 30, io, userID);
await Monitor.sendAverageUptime(24 * 90, io, userID);
await Monitor.sendCertInfo(io, monitorID, userID);
} else {
debug("No clients in the room, no need to send stats");
@ -468,7 +472,6 @@ class Monitor extends BeanModel {
} else {
// 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 ]));
console.log("here???" + status);
if (status === UP) {
uptime = 1;
}
@ -476,6 +479,71 @@ class Monitor extends BeanModel {
io.to(userID).emit("uptime", monitorID, duration, uptime);
}
/**
* Average Uptime of all Monitors
* Calculation based on:
* https://www.uptrends.com/support/kb/reporting/calculation-of-uptime-and-downtime
* @param duration : int Hours
*/
static async sendAverageUptime(duration, io, userID) {
const timeLogger = new TimeLogger();
const startTime = R.isoDateTime(dayjs.utc().subtract(duration, "hour"));
// Handle if heartbeat duration longer than the target duration
// e.g. If the last beat's duration is bigger that the 24hrs window, it will use the duration between the (beat time - window margin) (THEN case in SQL)
// JOIN is necessary, because heartbeat has still data of deleted monitors.
let result = await R.getRow(`
SELECT
-- SUM all duration, also trim off the beat out of time window
SUM(
CASE
WHEN (JULIANDAY(\`time\`) - JULIANDAY(?)) * 86400 < duration
THEN (JULIANDAY(\`time\`) - JULIANDAY(?)) * 86400
ELSE duration
END
) AS total_duration,
-- SUM all uptime duration, also trim off the beat out of time window
SUM(
CASE
WHEN (status = 1)
THEN
CASE
WHEN (JULIANDAY(\`time\`) - JULIANDAY(?)) * 86400 < duration
THEN (JULIANDAY(\`time\`) - JULIANDAY(?)) * 86400
ELSE duration
END
END
) AS uptime_duration
FROM heartbeat
JOIN monitor on monitor.id == heartbeat.monitor_id
WHERE time > ?
`, [
startTime, startTime, startTime, startTime, startTime
]);
timeLogger.print(`[${duration}] sendAverageUptime`);
let totalDuration = result.total_duration;
let uptimeDuration = result.uptime_duration;
let uptime = 0;
if (totalDuration > 0) {
uptime = uptimeDuration / totalDuration;
if (uptime < 0) {
uptime = 0;
}
} else {
// Handle new monitor with only one beat, because the beat's duration = 0
let result = await R.getRow("SELECT SUM(`status`) AS up_monitor, COUNT(`status`) AS sum_monitor FROM heartbeat JOIN monitor on monitor.id == heartbeat.monitor_id");
uptime = result.up_monitor / result.sum_monitor;
}
io.to(userID).emit("average_uptime", duration, uptime);
}
}
module.exports = Monitor;

View file

@ -15,11 +15,17 @@ export default {
computed: {
uptime() {
// If monitor is not set, display average uptime of all monitors
if (this.monitor) {
let key = this.monitor.id + "_" + this.type;
let key = this.monitor.id + "_" + this.type;
if (this.$root.uptimeList[key] !== undefined) {
return Math.round(this.$root.uptimeList[key] * 10000) / 100 + "%";
if (this.$root.uptimeList[key] !== undefined) {
return Math.round(this.$root.uptimeList[key] * 10000) / 100 + "%";
}
} else {
if (this.$root.averageUptimeList[this.type] !== undefined) {
return Math.round(this.$root.averageUptimeList[this.type] * 10000) / 100 + "%";
}
}
return this.$t("notAvailableShort")
@ -42,7 +48,7 @@ export default {
},
lastHeartBeat() {
if (this.monitor.id in this.$root.lastHeartbeatList && this.$root.lastHeartbeatList[this.monitor.id]) {
if (this.monitor && this.monitor.id in this.$root.lastHeartbeatList && this.$root.lastHeartbeatList[this.monitor.id]) {
return this.$root.lastHeartbeatList[this.monitor.id]
}

View file

@ -143,4 +143,32 @@ export default {
Token: "Token",
"Show URI": "Show URI",
"Clear all statistics": "Clear all Statistics",
retryCheckEverySecond: "Retry every {0} seconds.",
importHandleDescription: "Choose 'Skip existing' if you want to skip every monitor or notification with the same name. 'Overwrite' will delete every existing monitor and notification.",
confirmImportMsg: "Are you sure to import the backup? Please make sure you've selected the right import option.",
"Heartbeat Retry Interval": "Heartbeat Retry Interval",
"Import Backup": "Import Backup",
"Export Backup": "Export Backup",
"Skip existing": "Skip existing",
Overwrite: "Overwrite",
Options: "Options",
"Keep both": "Keep both",
Tags: "Tags",
"Add New below or Select...": "Add New below or Select...",
"Tag with this name already exist.": "Tag with this name already exist.",
"Tag with this value already exist.": "Tag with this value already exist.",
color: "color",
"value (optional)": "value (optional)",
Gray: "Gray",
Red: "Red",
Orange: "Orange",
Green: "Green",
Blue: "Blue",
Indigo: "Indigo",
Purple: "Purple",
Pink: "Pink",
"Search...": "Search...",
allMonitorsOperational: "All Systems operational",
notAllMonitorsOperational: "Not all systems operational",
overallUptime: "Overall uptime",
}

View file

@ -167,4 +167,7 @@ export default {
retryCheckEverySecond: "Versuche alle {0} Sekunden",
"Import Backup": "Import Backup",
"Export Backup": "Export Backup",
allMonitorsOperational: "Alle Systeme in Betrieb",
notAllMonitorsOperational: "Nicht alle Systeme in Betrieb",
overallUptime: "Durchschnittliche Verfügbarkeit",
}

View file

@ -167,4 +167,7 @@ export default {
Purple: "Purple",
Pink: "Pink",
"Search...": "Search...",
allMonitorsOperational: "All systems operational",
notAllMonitorsOperational: "Not all systems operational",
overallUptime: "Overall uptime",
}

View file

@ -143,4 +143,32 @@ export default {
Token: "Token",
"Show URI": "Show URI",
"Clear all statistics": "Clear all Statistics",
retryCheckEverySecond: "Retry every {0} seconds.",
importHandleDescription: "Choose 'Skip existing' if you want to skip every monitor or notification with the same name. 'Overwrite' will delete every existing monitor and notification.",
confirmImportMsg: "Are you sure to import the backup? Please make sure you've selected the right import option.",
"Heartbeat Retry Interval": "Heartbeat Retry Interval",
"Import Backup": "Import Backup",
"Export Backup": "Export Backup",
"Skip existing": "Skip existing",
Overwrite: "Overwrite",
Options: "Options",
"Keep both": "Keep both",
Tags: "Tags",
"Add New below or Select...": "Add New below or Select...",
"Tag with this name already exist.": "Tag with this name already exist.",
"Tag with this value already exist.": "Tag with this value already exist.",
color: "color",
"value (optional)": "value (optional)",
Gray: "Gray",
Red: "Red",
Orange: "Orange",
Green: "Green",
Blue: "Blue",
Indigo: "Indigo",
Purple: "Purple",
Pink: "Pink",
"Search...": "Search...",
allMonitorsOperational: "All Systems operational",
notAllMonitorsOperational: "Not all systems operational",
overallUptime: "Overall uptime",
}

View file

@ -143,4 +143,32 @@ export default {
Token: "Token",
"Show URI": "Show URI",
"Clear all statistics": "Clear all Statistics",
retryCheckEverySecond: "Retry every {0} seconds.",
importHandleDescription: "Choose 'Skip existing' if you want to skip every monitor or notification with the same name. 'Overwrite' will delete every existing monitor and notification.",
confirmImportMsg: "Are you sure to import the backup? Please make sure you've selected the right import option.",
"Heartbeat Retry Interval": "Heartbeat Retry Interval",
"Import Backup": "Import Backup",
"Export Backup": "Export Backup",
"Skip existing": "Skip existing",
Overwrite: "Overwrite",
Options: "Options",
"Keep both": "Keep both",
Tags: "Tags",
"Add New below or Select...": "Add New below or Select...",
"Tag with this name already exist.": "Tag with this name already exist.",
"Tag with this value already exist.": "Tag with this value already exist.",
color: "color",
"value (optional)": "value (optional)",
Gray: "Gray",
Red: "Red",
Orange: "Orange",
Green: "Green",
Blue: "Blue",
Indigo: "Indigo",
Purple: "Purple",
Pink: "Pink",
"Search...": "Search...",
allMonitorsOperational: "All Systems operational",
notAllMonitorsOperational: "Not all systems operational",
overallUptime: "Overall uptime",
}

View file

@ -143,4 +143,32 @@ export default {
Token: "Token",
"Show URI": "Show URI",
"Clear all statistics": "Clear all Statistics",
retryCheckEverySecond: "Retry every {0} seconds.",
importHandleDescription: "Choose 'Skip existing' if you want to skip every monitor or notification with the same name. 'Overwrite' will delete every existing monitor and notification.",
confirmImportMsg: "Are you sure to import the backup? Please make sure you've selected the right import option.",
"Heartbeat Retry Interval": "Heartbeat Retry Interval",
"Import Backup": "Import Backup",
"Export Backup": "Export Backup",
"Skip existing": "Skip existing",
Overwrite: "Overwrite",
Options: "Options",
"Keep both": "Keep both",
Tags: "Tags",
"Add New below or Select...": "Add New below or Select...",
"Tag with this name already exist.": "Tag with this name already exist.",
"Tag with this value already exist.": "Tag with this value already exist.",
color: "color",
"value (optional)": "value (optional)",
Gray: "Gray",
Red: "Red",
Orange: "Orange",
Green: "Green",
Blue: "Blue",
Indigo: "Indigo",
Purple: "Purple",
Pink: "Pink",
"Search...": "Search...",
allMonitorsOperational: "All Systems operational",
notAllMonitorsOperational: "Not all systems operational",
overallUptime: "Overall uptime",
}

View file

@ -158,4 +158,17 @@ export default {
Purple: "Viola",
Pink: "Rosa",
"Search...": "Cerca...",
retryCheckEverySecond: "Retry every {0} seconds.",
importHandleDescription: "Choose 'Skip existing' if you want to skip every monitor or notification with the same name. 'Overwrite' will delete every existing monitor and notification.",
confirmImportMsg: "Are you sure to import the backup? Please make sure you've selected the right import option.",
"Heartbeat Retry Interval": "Heartbeat Retry Interval",
"Import Backup": "Import Backup",
"Export Backup": "Export Backup",
"Skip existing": "Skip existing",
Overwrite: "Overwrite",
Options: "Options",
"Keep both": "Keep both",
allMonitorsOperational: "All Systems operational",
notAllMonitorsOperational: "Not all systems operational",
overallUptime: "Overall uptime",
}

View file

@ -143,4 +143,32 @@ export default {
Token: "Token",
"Show URI": "Show URI",
"Clear all statistics": "Clear all Statistics",
retryCheckEverySecond: "Retry every {0} seconds.",
importHandleDescription: "Choose 'Skip existing' if you want to skip every monitor or notification with the same name. 'Overwrite' will delete every existing monitor and notification.",
confirmImportMsg: "Are you sure to import the backup? Please make sure you've selected the right import option.",
"Heartbeat Retry Interval": "Heartbeat Retry Interval",
"Import Backup": "Import Backup",
"Export Backup": "Export Backup",
"Skip existing": "Skip existing",
Overwrite: "Overwrite",
Options: "Options",
"Keep both": "Keep both",
Tags: "Tags",
"Add New below or Select...": "Add New below or Select...",
"Tag with this name already exist.": "Tag with this name already exist.",
"Tag with this value already exist.": "Tag with this value already exist.",
color: "color",
"value (optional)": "value (optional)",
Gray: "Gray",
Red: "Red",
Orange: "Orange",
Green: "Green",
Blue: "Blue",
Indigo: "Indigo",
Purple: "Purple",
Pink: "Pink",
"Search...": "Search...",
allMonitorsOperational: "All Systems operational",
notAllMonitorsOperational: "Not all systems operational",
overallUptime: "Overall uptime",
}

View file

@ -143,4 +143,32 @@ export default {
Token: "Token",
"Show URI": "Show URI",
"Clear all statistics": "Clear all Statistics",
retryCheckEverySecond: "Retry every {0} seconds.",
importHandleDescription: "Choose 'Skip existing' if you want to skip every monitor or notification with the same name. 'Overwrite' will delete every existing monitor and notification.",
confirmImportMsg: "Are you sure to import the backup? Please make sure you've selected the right import option.",
"Heartbeat Retry Interval": "Heartbeat Retry Interval",
"Import Backup": "Import Backup",
"Export Backup": "Export Backup",
"Skip existing": "Skip existing",
Overwrite: "Overwrite",
Options: "Options",
"Keep both": "Keep both",
Tags: "Tags",
"Add New below or Select...": "Add New below or Select...",
"Tag with this name already exist.": "Tag with this name already exist.",
"Tag with this value already exist.": "Tag with this value already exist.",
color: "color",
"value (optional)": "value (optional)",
Gray: "Gray",
Red: "Red",
Orange: "Orange",
Green: "Green",
Blue: "Blue",
Indigo: "Indigo",
Purple: "Purple",
Pink: "Pink",
"Search...": "Search...",
allMonitorsOperational: "All Systems operational",
notAllMonitorsOperational: "Not all systems operational",
overallUptime: "Overall uptime",
}

View file

@ -143,4 +143,32 @@ export default {
Token: "Token",
"Show URI": "Toon URI",
"Clear all statistics": "Wis alle statistieken",
retryCheckEverySecond: "Retry every {0} seconds.",
importHandleDescription: "Choose 'Skip existing' if you want to skip every monitor or notification with the same name. 'Overwrite' will delete every existing monitor and notification.",
confirmImportMsg: "Are you sure to import the backup? Please make sure you've selected the right import option.",
"Heartbeat Retry Interval": "Heartbeat Retry Interval",
"Import Backup": "Import Backup",
"Export Backup": "Export Backup",
"Skip existing": "Skip existing",
Overwrite: "Overwrite",
Options: "Options",
"Keep both": "Keep both",
Tags: "Tags",
"Add New below or Select...": "Add New below or Select...",
"Tag with this name already exist.": "Tag with this name already exist.",
"Tag with this value already exist.": "Tag with this value already exist.",
color: "color",
"value (optional)": "value (optional)",
Gray: "Gray",
Red: "Red",
Orange: "Orange",
Green: "Green",
Blue: "Blue",
Indigo: "Indigo",
Purple: "Purple",
Pink: "Pink",
"Search...": "Search...",
allMonitorsOperational: "All Systems operational",
notAllMonitorsOperational: "Not all systems operational",
overallUptime: "Overall uptime",
}

View file

@ -143,4 +143,32 @@ export default {
Token: "Token",
"Show URI": "Pokaż URI",
"Clear all statistics": "Wyczyść wszystkie statystyki",
retryCheckEverySecond: "Retry every {0} seconds.",
importHandleDescription: "Choose 'Skip existing' if you want to skip every monitor or notification with the same name. 'Overwrite' will delete every existing monitor and notification.",
confirmImportMsg: "Are you sure to import the backup? Please make sure you've selected the right import option.",
"Heartbeat Retry Interval": "Heartbeat Retry Interval",
"Import Backup": "Import Backup",
"Export Backup": "Export Backup",
"Skip existing": "Skip existing",
Overwrite: "Overwrite",
Options: "Options",
"Keep both": "Keep both",
Tags: "Tags",
"Add New below or Select...": "Add New below or Select...",
"Tag with this name already exist.": "Tag with this name already exist.",
"Tag with this value already exist.": "Tag with this value already exist.",
color: "color",
"value (optional)": "value (optional)",
Gray: "Gray",
Red: "Red",
Orange: "Orange",
Green: "Green",
Blue: "Blue",
Indigo: "Indigo",
Purple: "Purple",
Pink: "Pink",
"Search...": "Search...",
allMonitorsOperational: "All Systems operational",
notAllMonitorsOperational: "Not all systems operational",
overallUptime: "Overall uptime",
}

View file

@ -143,4 +143,32 @@ export default {
Token: "Token",
"Show URI": "Show URI",
"Clear all statistics": "Clear all Statistics",
retryCheckEverySecond: "Retry every {0} seconds.",
importHandleDescription: "Choose 'Skip existing' if you want to skip every monitor or notification with the same name. 'Overwrite' will delete every existing monitor and notification.",
confirmImportMsg: "Are you sure to import the backup? Please make sure you've selected the right import option.",
"Heartbeat Retry Interval": "Heartbeat Retry Interval",
"Import Backup": "Import Backup",
"Export Backup": "Export Backup",
"Skip existing": "Skip existing",
Overwrite: "Overwrite",
Options: "Options",
"Keep both": "Keep both",
Tags: "Tags",
"Add New below or Select...": "Add New below or Select...",
"Tag with this name already exist.": "Tag with this name already exist.",
"Tag with this value already exist.": "Tag with this value already exist.",
color: "color",
"value (optional)": "value (optional)",
Gray: "Gray",
Red: "Red",
Orange: "Orange",
Green: "Green",
Blue: "Blue",
Indigo: "Indigo",
Purple: "Purple",
Pink: "Pink",
"Search...": "Search...",
allMonitorsOperational: "All Systems operational",
notAllMonitorsOperational: "Not all systems operational",
overallUptime: "Overall uptime",
}

View file

@ -143,4 +143,32 @@ export default {
Token: "Token",
"Show URI": "Show URI",
"Clear all statistics": "Clear all Statistics",
retryCheckEverySecond: "Retry every {0} seconds.",
importHandleDescription: "Choose 'Skip existing' if you want to skip every monitor or notification with the same name. 'Overwrite' will delete every existing monitor and notification.",
confirmImportMsg: "Are you sure to import the backup? Please make sure you've selected the right import option.",
"Heartbeat Retry Interval": "Heartbeat Retry Interval",
"Import Backup": "Import Backup",
"Export Backup": "Export Backup",
"Skip existing": "Skip existing",
Overwrite: "Overwrite",
Options: "Options",
"Keep both": "Keep both",
Tags: "Tags",
"Add New below or Select...": "Add New below or Select...",
"Tag with this name already exist.": "Tag with this name already exist.",
"Tag with this value already exist.": "Tag with this value already exist.",
color: "color",
"value (optional)": "value (optional)",
Gray: "Gray",
Red: "Red",
Orange: "Orange",
Green: "Green",
Blue: "Blue",
Indigo: "Indigo",
Purple: "Purple",
Pink: "Pink",
"Search...": "Search...",
allMonitorsOperational: "All Systems operational",
notAllMonitorsOperational: "Not all systems operational",
overallUptime: "Overall uptime",
}

View file

@ -143,4 +143,32 @@ export default {
Token: "Token",
"Show URI": "Show URI",
"Clear all statistics": "Clear all Statistics",
retryCheckEverySecond: "Retry every {0} seconds.",
importHandleDescription: "Choose 'Skip existing' if you want to skip every monitor or notification with the same name. 'Overwrite' will delete every existing monitor and notification.",
confirmImportMsg: "Are you sure to import the backup? Please make sure you've selected the right import option.",
"Heartbeat Retry Interval": "Heartbeat Retry Interval",
"Import Backup": "Import Backup",
"Export Backup": "Export Backup",
"Skip existing": "Skip existing",
Overwrite: "Overwrite",
Options: "Options",
"Keep both": "Keep both",
Tags: "Tags",
"Add New below or Select...": "Add New below or Select...",
"Tag with this name already exist.": "Tag with this name already exist.",
"Tag with this value already exist.": "Tag with this value already exist.",
color: "color",
"value (optional)": "value (optional)",
Gray: "Gray",
Red: "Red",
Orange: "Orange",
Green: "Green",
Blue: "Blue",
Indigo: "Indigo",
Purple: "Purple",
Pink: "Pink",
"Search...": "Search...",
allMonitorsOperational: "All Systems operational",
notAllMonitorsOperational: "Not all systems operational",
overallUptime: "Overall uptime",
}

View file

@ -143,4 +143,32 @@ export default {
Token: "Token",
"Show URI": "Show URI",
"Clear all statistics": "Clear all Statistics",
retryCheckEverySecond: "Retry every {0} seconds.",
importHandleDescription: "Choose 'Skip existing' if you want to skip every monitor or notification with the same name. 'Overwrite' will delete every existing monitor and notification.",
confirmImportMsg: "Are you sure to import the backup? Please make sure you've selected the right import option.",
"Heartbeat Retry Interval": "Heartbeat Retry Interval",
"Import Backup": "Import Backup",
"Export Backup": "Export Backup",
"Skip existing": "Skip existing",
Overwrite: "Overwrite",
Options: "Options",
"Keep both": "Keep both",
Tags: "Tags",
"Add New below or Select...": "Add New below or Select...",
"Tag with this name already exist.": "Tag with this name already exist.",
"Tag with this value already exist.": "Tag with this value already exist.",
color: "color",
"value (optional)": "value (optional)",
Gray: "Gray",
Red: "Red",
Orange: "Orange",
Green: "Green",
Blue: "Blue",
Indigo: "Indigo",
Purple: "Purple",
Pink: "Pink",
"Search...": "Search...",
allMonitorsOperational: "All Systems operational",
notAllMonitorsOperational: "Not all systems operational",
overallUptime: "Overall uptime",
}

View file

@ -117,4 +117,57 @@ export default {
Events: "Olaylar",
Heartbeats: "Sağlık Durumları",
"Auto Get": "Otomatik Al",
retryCheckEverySecond: "Retry every {0} seconds.",
enableDefaultNotificationDescription: "For every new monitor this notification will be enabled by default. You can still disable the notification separately for each monitor.",
importHandleDescription: "Choose 'Skip existing' if you want to skip every monitor or notification with the same name. 'Overwrite' will delete every existing monitor and notification.",
confirmImportMsg: "Are you sure to import the backup? Please make sure you've selected the right import option.",
twoFAVerifyLabel: "Please type in your token to verify that 2FA is working",
tokenValidSettingsMsg: "Token is valid! You can now save the 2FA settings.",
confirmEnableTwoFAMsg: "Are you sure you want to enable 2FA?",
confirmDisableTwoFAMsg: "Are you sure you want to disable 2FA?",
"Heartbeat Retry Interval": "Heartbeat Retry Interval",
"Import Backup": "Import Backup",
"Export Backup": "Export Backup",
Export: "Export",
Import: "Import",
"Default enabled": "Default enabled",
"Apply on all existing monitors": "Apply on all existing monitors",
backupDescription: "You can backup all monitors and all notifications into a JSON file.",
backupDescription2: "PS: History and event data is not included.",
backupDescription3: "Sensitive data such as notification tokens is included in the export file, please keep it carefully.",
alertNoFile: "Please select a file to import.",
alertWrongFileType: "Please select a JSON file.",
"Clear all statistics": "Clear all Statistics",
"Skip existing": "Skip existing",
Overwrite: "Overwrite",
Options: "Options",
"Keep both": "Keep both",
"Verify Token": "Verify Token",
"Setup 2FA": "Setup 2FA",
"Enable 2FA": "Enable 2FA",
"Disable 2FA": "Disable 2FA",
"2FA Settings": "2FA Settings",
"Two Factor Authentication": "Two Factor Authentication",
Active: "Active",
Inactive: "Inactive",
Token: "Token",
"Show URI": "Show URI",
Tags: "Tags",
"Add New below or Select...": "Add New below or Select...",
"Tag with this name already exist.": "Tag with this name already exist.",
"Tag with this value already exist.": "Tag with this value already exist.",
color: "color",
"value (optional)": "value (optional)",
Gray: "Gray",
Red: "Red",
Orange: "Orange",
Green: "Green",
Blue: "Blue",
Indigo: "Indigo",
Purple: "Purple",
Pink: "Pink",
"Search...": "Search...",
allMonitorsOperational: "All Systems operational",
notAllMonitorsOperational: "Not all systems operational",
overallUptime: "Overall uptime",
}

View file

@ -143,4 +143,32 @@ export default {
Token: "Token",
"Show URI": "Show URI",
"Clear all statistics": "Clear all Statistics",
retryCheckEverySecond: "Retry every {0} seconds.",
importHandleDescription: "Choose 'Skip existing' if you want to skip every monitor or notification with the same name. 'Overwrite' will delete every existing monitor and notification.",
confirmImportMsg: "Are you sure to import the backup? Please make sure you've selected the right import option.",
"Heartbeat Retry Interval": "Heartbeat Retry Interval",
"Import Backup": "Import Backup",
"Export Backup": "Export Backup",
"Skip existing": "Skip existing",
Overwrite: "Overwrite",
Options: "Options",
"Keep both": "Keep both",
Tags: "Tags",
"Add New below or Select...": "Add New below or Select...",
"Tag with this name already exist.": "Tag with this name already exist.",
"Tag with this value already exist.": "Tag with this value already exist.",
color: "color",
"value (optional)": "value (optional)",
Gray: "Gray",
Red: "Red",
Orange: "Orange",
Green: "Green",
Blue: "Blue",
Indigo: "Indigo",
Purple: "Purple",
Pink: "Pink",
"Search...": "Search...",
allMonitorsOperational: "All Systems operational",
notAllMonitorsOperational: "Not all systems operational",
overallUptime: "Overall uptime",
}

View file

@ -143,4 +143,32 @@ export default {
Token: "Token",
"Show URI": "顯示 URI",
"Clear all statistics": "清除所有歷史記錄",
retryCheckEverySecond: "Retry every {0} seconds.",
importHandleDescription: "Choose 'Skip existing' if you want to skip every monitor or notification with the same name. 'Overwrite' will delete every existing monitor and notification.",
confirmImportMsg: "Are you sure to import the backup? Please make sure you've selected the right import option.",
"Heartbeat Retry Interval": "Heartbeat Retry Interval",
"Import Backup": "Import Backup",
"Export Backup": "Export Backup",
"Skip existing": "Skip existing",
Overwrite: "Overwrite",
Options: "Options",
"Keep both": "Keep both",
Tags: "Tags",
"Add New below or Select...": "Add New below or Select...",
"Tag with this name already exist.": "Tag with this name already exist.",
"Tag with this value already exist.": "Tag with this value already exist.",
color: "color",
"value (optional)": "value (optional)",
Gray: "Gray",
Red: "Red",
Orange: "Orange",
Green: "Green",
Blue: "Blue",
Indigo: "Indigo",
Purple: "Purple",
Pink: "Pink",
"Search...": "Search...",
allMonitorsOperational: "All Systems operational",
notAllMonitorsOperational: "Not all systems operational",
overallUptime: "Overall uptime",
}

View file

@ -23,6 +23,7 @@ export default {
importantHeartbeatList: { },
avgPingList: { },
uptimeList: { },
averageUptimeList: {},
certInfoList: {},
notificationList: [],
connectionErrorMsg: "Cannot connect to the socket server. Reconnecting...",
@ -125,6 +126,10 @@ export default {
this.uptimeList[`${monitorID}_${type}`] = data
});
socket.on("average_uptime", (type, data) => {
this.averageUptimeList[`${type}`] = data
});
socket.on("certInfo", (monitorID, data) => {
this.certInfoList[monitorID] = JSON.parse(data)
});

View file

@ -4,7 +4,35 @@
<h1 class="mb-3">
{{ $t("Quick Stats") }}
</h1>
<div class="shadow-box big-padding text-start mb-4 d-flex flex-row justify-content-start align-items-center">
<span class="rounded-circle bg-primary d-inline-block me-3" :class="{'bg-primary': (stats.down === 0), 'bg-danger': (stats.down !== 0)}" :style="{width: '1.5em', height: '1.5em'}" />
<h3 class="mb-0">{{ (stats.down === 0) ? $t("allMonitorsOperational") : $t("notAllMonitorsOperational") }}</h3>
</div>
<div class="shadow-box big-padding text-center mb-4">
<div class="row">
<div class="col">
<h3>{{ $t("overallUptime") }}</h3>
</div>
</div>
<div class="row">
<div class="col">
<h4>24{{ $t("-hour") }}</h4>
<span class="num"><Uptime :type="24" /></span>
</div>
<div class="col">
<h4>7{{ $t("-day") }}</h4>
<span class="num"><Uptime :type="168" /></span>
</div>
<div class="col">
<h4>30{{ $t("-day") }}</h4>
<span class="num"><Uptime :type="720" /></span>
</div>
<div class="col">
<h4>90{{ $t("-day") }}</h4>
<span class="num"><Uptime :type="2160" /></span>
</div>
</div>
</div>
<div class="shadow-box big-padding text-center mb-4">
<div class="row">
<div class="col">
@ -69,10 +97,12 @@
import Status from "../components/Status.vue";
import Datetime from "../components/Datetime.vue";
import Pagination from "v-pagination-3";
import Uptime from "../components/Uptime.vue";
export default {
components: {
Datetime,
Uptime,
Status,
Pagination,
},