[status page] implement rest api for heartbeat

This commit is contained in:
LouisLam 2021-09-19 23:24:51 +08:00
parent 6350c43cc3
commit 7ee98d989c
5 changed files with 67 additions and 38 deletions

View file

@ -4,17 +4,7 @@ const { R } = require("redbean-node");
class Group extends BeanModel {
async toPublicJSON() {
let monitorBeanList = R.convertToBeans("monitor", await R.getAll(`
SELECT * FROM monitor, monitor_group
WHERE monitor.id = monitor_group.monitor_id
AND group_id = ?
`, [
this.id,
]));
console.log(monitorBeanList);
let monitorBeanList = await this.getMonitorList();
let monitorList = [];
for (let bean of monitorBeanList) {
@ -28,6 +18,16 @@ class Group extends BeanModel {
monitorList,
};
}
async getMonitorList() {
return R.convertToBeans("monitor", await R.getAll(`
SELECT monitor.* FROM monitor, monitor_group
WHERE monitor.id = monitor_group.monitor_id
AND group_id = ?
`, [
this.id,
]));
}
}
module.exports = Group;

View file

@ -1,8 +1,8 @@
const dayjs = require("dayjs");
const utc = require("dayjs/plugin/utc")
let timezone = require("dayjs/plugin/timezone")
dayjs.extend(utc)
dayjs.extend(timezone)
const utc = require("dayjs/plugin/utc");
let timezone = require("dayjs/plugin/timezone");
dayjs.extend(utc);
dayjs.extend(timezone);
const { BeanModel } = require("redbean-node/dist/bean-model");
/**
@ -13,6 +13,15 @@ const { BeanModel } = require("redbean-node/dist/bean-model");
*/
class Heartbeat extends BeanModel {
toPublicJSON() {
return {
status: this.status,
time: this.time,
msg: "", // Hide for public
ping: this.ping,
};
}
toJSON() {
return {
monitorID: this.monitor_id,

View file

@ -38,9 +38,15 @@ router.get("/api/status-page/incident", async (_, response) => {
try {
await checkPublished();
let incident = await R.findOne("incident", " pin = 1 AND active = 1");
if (incident) {
incident = incident.toPublicJSON();
}
response.json({
ok: true,
incident: (await R.findOne("incident", " pin = 1 AND active = 1")).toPublicJSON(),
incident,
});
} catch (error) {
@ -56,7 +62,7 @@ router.get("/api/status-page/monitor-list", async (_request, response) => {
try {
await checkPublished();
const publicGroupList = [];
let list = await R.find("group", " public = 1 ORDER BY weight, name ");
let list = await R.find("group", " public = 1 ORDER BY weight ");
for (let groupBean of list) {
publicGroupList.push(await groupBean.toPublicJSON());
@ -76,16 +82,30 @@ router.get("/api/status-page/heartbeat", async (_request, response) => {
try {
await checkPublished();
const monitorList = {};
let list = await R.find("", " ", [
]);
let heartbeatList = {};
for (let monitor of list) {
monitorList[monitor.id] = await monitor.toJSON();
let monitorIDList = await R.getCol(`
SELECT monitor_group.monitor_id FROM monitor_group, \`group\`
WHERE monitor_group.group_id = \`group\`.id
AND public = 1
`);
for (let monitorID of monitorIDList) {
let list = await R.getAll(`
SELECT * FROM heartbeat
WHERE monitor_id = ?
ORDER BY time DESC
LIMIT 100
`, [
monitorID,
]);
list = R.convertToBeans("heartbeat", list);
heartbeatList[monitorID] = list.reverse().map(row => row.toPublicJSON());
}
response.json({
monitorList: monitorList,
heartbeatList,
});
} catch (error) {

View file

@ -17,8 +17,6 @@ export default {
publicMonitorList() {
let result = {};
console.log(this.publicGroupList);
for (let group of this.publicGroupList) {
for (let monitor of group.monitorList) {
result[monitor.id] = monitor;

View file

@ -30,10 +30,10 @@
Edit Status Page
</button>
<router-link to="/dashboard" class="btn btn-info">
<a href="/dashboard" class="btn btn-info">
<font-awesome-icon icon="tachometer-alt" />
Go to Dashboard
</router-link>
</a>
</div>
<div v-else>
@ -168,13 +168,10 @@
</div>
<div class="mt-3">
<VueMultiselect
v-model="selectedMonitor"
:options="allMonitorList"
:custom-label="monitorSelectorLabel"
:searchable="true"
placeholder="Add a monitor"
></VueMultiselect>
<label>Add a monitor:</label>
<select v-model="selectedMonitor" class="form-control">
<option v-for="monitor in allMonitorList" :key="monitor.id" :value="monitor">{{ monitor.name }}</option>
</select>
</div>
</div>
@ -382,16 +379,21 @@ export default {
});
// 5mins a loop
this.updateHeartbeatList();
feedInterval = setInterval(() => {
this.updateHeartbeatList();
}, 10 * 1000);
},
methods: {
updateHeartbeatList() {
// If editMode, it will use the data from websocket.
if (! this.editMode) {
axios.get("/api/status-page/heartbeat").then((res) => {
// TODO
this.$root.heartbeatList = res.data.heartbeatList;
});
}
}, 5 * 60 * 1000);
},
methods: {
},
edit() {
this.$root.initSocketIO(true);