mirror of
https://github.com/louislam/uptime-kuma.git
synced 2024-11-23 14:54:05 +00:00
implement uptime
This commit is contained in:
parent
82afddcfd6
commit
84c21b71c0
7 changed files with 145 additions and 49 deletions
|
@ -20,7 +20,7 @@ class Monitor extends BeanModel {
|
|||
id: this.id,
|
||||
name: this.name,
|
||||
url: this.url,
|
||||
upRate: this.upRate,
|
||||
weight: this.weight,
|
||||
active: this.active,
|
||||
type: this.type,
|
||||
interval: this.interval,
|
||||
|
@ -91,15 +91,20 @@ class Monitor extends BeanModel {
|
|||
|
||||
static async sendStats(io, monitorID, userID) {
|
||||
Monitor.sendAvgPing(24, io, monitorID, userID);
|
||||
//Monitor.sendUptime(24, io, this.id);
|
||||
//Monitor.sendUptime(24 * 30, io, this.id);
|
||||
Monitor.sendUptime(24, io, monitorID, userID);
|
||||
Monitor.sendUptime(24 * 30, io, monitorID, userID);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param duration : int Hours
|
||||
*/
|
||||
static async sendAvgPing(duration, io, monitorID, userID) {
|
||||
let avgPing = parseInt(await R.getCell(`
|
||||
SELECT AVG(ping)
|
||||
FROM heartbeat
|
||||
WHERE time > DATE('now', ? || ' hours')
|
||||
AND ping IS NOT NULL
|
||||
AND monitor_id = ? `, [
|
||||
-duration,
|
||||
monitorID
|
||||
|
@ -108,8 +113,25 @@ class Monitor extends BeanModel {
|
|||
io.to(userID).emit("avgPing", monitorID, avgPing);
|
||||
}
|
||||
|
||||
sendUptime(duration) {
|
||||
/**
|
||||
*
|
||||
* @param duration : int Hours
|
||||
*/
|
||||
static async sendUptime(duration, io, monitorID, userID) {
|
||||
let downtime = parseInt(await R.getCell(`
|
||||
SELECT SUM(duration)
|
||||
FROM heartbeat
|
||||
WHERE time > DATE('now', ? || ' hours')
|
||||
AND status = 0
|
||||
AND monitor_id = ? `, [
|
||||
-duration,
|
||||
monitorID
|
||||
]));
|
||||
|
||||
let sec = duration * 3600;
|
||||
let uptime = (sec - downtime) / sec;
|
||||
|
||||
io.to(userID).emit("uptime", monitorID, duration, uptime);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -340,7 +340,7 @@ async function afterLogin(socket, user) {
|
|||
async function getMonitorJSONList(userID) {
|
||||
let result = {};
|
||||
|
||||
let monitorList = await R.find("monitor", " user_id = ? ORDER BY active DESC, name ASC ", [
|
||||
let monitorList = await R.find("monitor", " user_id = ? ", [
|
||||
userID
|
||||
])
|
||||
|
||||
|
|
|
@ -18,9 +18,6 @@ export default {
|
|||
|
||||
computed: {
|
||||
displayText() {
|
||||
|
||||
console.log(dayjs.tz.guess())
|
||||
|
||||
return this.value
|
||||
},
|
||||
}
|
||||
|
|
61
src/components/Uptime.vue
Normal file
61
src/components/Uptime.vue
Normal file
|
@ -0,0 +1,61 @@
|
|||
<template>
|
||||
<span :class="className">{{ uptime }}</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
monitor : Object,
|
||||
type: String,
|
||||
pill: {
|
||||
Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
|
||||
computed: {
|
||||
uptime() {
|
||||
|
||||
let key = this.monitor.id + "_" + this.type;
|
||||
|
||||
if (this.$root.uptimeList[key]) {
|
||||
return Math.round(this.$root.uptimeList[key] * 10000) / 100 + "%";
|
||||
} else {
|
||||
return "N/A"
|
||||
}
|
||||
},
|
||||
|
||||
color() {
|
||||
if (this.lastHeartBeat.status === 0) {
|
||||
return "danger"
|
||||
} else if (this.lastHeartBeat.status === 1) {
|
||||
return "primary"
|
||||
} else {
|
||||
return "secondary"
|
||||
}
|
||||
},
|
||||
|
||||
lastHeartBeat() {
|
||||
if (this.monitor.id in this.$root.lastHeartbeatList && this.$root.lastHeartbeatList[this.monitor.id]) {
|
||||
return this.$root.lastHeartbeatList[this.monitor.id]
|
||||
} else {
|
||||
return { status: -1 }
|
||||
}
|
||||
},
|
||||
|
||||
className() {
|
||||
if (this.pill) {
|
||||
return `badge rounded-pill bg-${this.color}`;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
|
@ -17,18 +17,11 @@ export default {
|
|||
},
|
||||
allowLoginDialog: false, // Allowed to show login dialog, but "loggedIn" have to be true too. This exists because prevent the login dialog show 0.1s in first before the socket server auth-ed.
|
||||
loggedIn: false,
|
||||
monitorList: [
|
||||
|
||||
],
|
||||
heartbeatList: {
|
||||
|
||||
},
|
||||
importantHeartbeatList: {
|
||||
|
||||
},
|
||||
avgPingList: {
|
||||
|
||||
}
|
||||
monitorList: { },
|
||||
heartbeatList: { },
|
||||
importantHeartbeatList: { },
|
||||
avgPingList: { },
|
||||
uptimeList: { }
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -85,6 +78,10 @@ export default {
|
|||
this.avgPingList[monitorID] = data
|
||||
});
|
||||
|
||||
socket.on('uptime', (monitorID, type, data) => {
|
||||
this.uptimeList[`${monitorID}_${type}`] = data
|
||||
});
|
||||
|
||||
socket.on('importantHeartbeatList', (monitorID, data) => {
|
||||
if (! (monitorID in this.importantHeartbeatList)) {
|
||||
this.importantHeartbeatList[monitorID] = data;
|
||||
|
|
|
@ -11,18 +11,18 @@
|
|||
|
||||
<span v-if="$root.monitorList.length === 0">No Monitors, please <router-link to="/add">add one</router-link>.</span>
|
||||
|
||||
<router-link :to="monitorURL(item.id)" class="item" :class="{ 'disabled': ! item.active }" v-for="item in $root.monitorList">
|
||||
<router-link :to="monitorURL(item.id)" class="item" :class="{ 'disabled': ! item.active }" v-for="item in sortedMonitorList">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="col-6 col-md-8 small-padding">
|
||||
|
||||
<div class="info">
|
||||
<span class="badge rounded-pill bg-primary">{{ item.upRate }}%</span>
|
||||
<Uptime :monitor="item" type="24" :pill="true" />
|
||||
{{ item.name }}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="col-6 col-md-4">
|
||||
<HeartbeatBar size="small" :monitor-id="item.id" />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -42,15 +42,49 @@
|
|||
<script>
|
||||
|
||||
import HeartbeatBar from "../components/HeartbeatBar.vue";
|
||||
import Uptime from "../components/Uptime.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Uptime,
|
||||
HeartbeatBar
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
sortedMonitorList() {
|
||||
let result = Object.values(this.$root.monitorList);
|
||||
|
||||
result.sort((m1, m2) => {
|
||||
|
||||
if (m1.active !== m2.active) {
|
||||
if (m1.active === 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (m2.active === 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (m1.weight !== m2.weight) {
|
||||
if (m1.weight > m2.weight) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (m1.weight < m2.weight) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return m1.name.localeCompare(m2.name);
|
||||
})
|
||||
|
||||
return result;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
monitorURL(id) {
|
||||
return "/dashboard/" + id;
|
||||
|
@ -98,29 +132,13 @@ export default {
|
|||
}
|
||||
}
|
||||
|
||||
.hp-bar {
|
||||
white-space: nowrap;
|
||||
margin-top: 4px;
|
||||
text-align: right;
|
||||
.badge {
|
||||
min-width: 58px;
|
||||
}
|
||||
|
||||
div {
|
||||
display: inline-block;
|
||||
background-color: $primary;
|
||||
width: 0.35rem;
|
||||
height: 1rem;
|
||||
margin: 0.15rem;
|
||||
border-radius: 50rem;
|
||||
transition: all ease-in-out 0.15s;
|
||||
|
||||
&.empty {
|
||||
background-color: aliceblue;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
transform: scale(1.5);
|
||||
}
|
||||
}
|
||||
.small-padding {
|
||||
padding-left: 5px !important;
|
||||
padding-right: 5px !important;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
|
|
@ -36,12 +36,12 @@
|
|||
<div class="col">
|
||||
<h4>Uptime</h4>
|
||||
<p>(24-hour)</p>
|
||||
<span class="num"></span>
|
||||
<span class="num"><Uptime :monitor="monitor" type="24" /></span>
|
||||
</div>
|
||||
<div class="col">
|
||||
<h4>Uptime</h4>
|
||||
<p>(30-day)</p>
|
||||
<span class="num"></span>
|
||||
<span class="num"><Uptime :monitor="monitor" type="720" /></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -86,9 +86,11 @@ import HeartbeatBar from "../components/HeartbeatBar.vue";
|
|||
import Status from "../components/Status.vue";
|
||||
import Datetime from "../components/Datetime.vue";
|
||||
import CountUp from "../components/CountUp.vue";
|
||||
import Uptime from "../components/Uptime.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
Uptime,
|
||||
CountUp,
|
||||
Datetime,
|
||||
HeartbeatBar,
|
||||
|
@ -233,7 +235,6 @@ table {
|
|||
font-size: 14px;
|
||||
|
||||
tr {
|
||||
--bs-table-accent-bg: white;
|
||||
transition: all ease-in-out 0.2ms;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue