mirror of
https://github.com/louislam/uptime-kuma.git
synced 2025-07-19 07:44:02 +02:00
DEVOPS-000 feractoring feature
This commit is contained in:
parent
dbc79f8d8d
commit
85df67e4e4
8 changed files with 84 additions and 63 deletions
12
db/knex_migrations/2025-06-11-0000-add-manual-monitor.js
Normal file
12
db/knex_migrations/2025-06-11-0000-add-manual-monitor.js
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
exports.up = function (knex) {
|
||||||
|
return knex.schema
|
||||||
|
.alterTable("monitor", function (table) {
|
||||||
|
table.string("manual_status").defaultTo(null);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.down = function (knex) {
|
||||||
|
return knex.schema.alterTable("monitor", function (table) {
|
||||||
|
table.dropColumn("manual_status");
|
||||||
|
});
|
||||||
|
};
|
|
@ -636,17 +636,7 @@ class Monitor extends BeanModel {
|
||||||
bean.duration = beatInterval;
|
bean.duration = beatInterval;
|
||||||
throw new Error("No heartbeat in the time window");
|
throw new Error("No heartbeat in the time window");
|
||||||
}
|
}
|
||||||
} else if (this.type === "manual") {
|
|
||||||
const lastHeartbeat = await Monitor.getPreviousHeartbeat(this.id);
|
|
||||||
if (lastHeartbeat) {
|
|
||||||
bean.status = lastHeartbeat.status;
|
|
||||||
bean.msg = lastHeartbeat.msg || "Manual monitoring";
|
|
||||||
} else {
|
|
||||||
bean.status = PENDING;
|
|
||||||
bean.msg = "Manual monitoring - No previous status";
|
|
||||||
}
|
|
||||||
bean.time = new Date().getTime();
|
|
||||||
retries = 0;
|
|
||||||
} else if (this.type === "steam") {
|
} else if (this.type === "steam") {
|
||||||
const steamApiUrl = "https://api.steampowered.com/IGameServersService/GetServerList/v1/";
|
const steamApiUrl = "https://api.steampowered.com/IGameServersService/GetServerList/v1/";
|
||||||
const steamAPIKey = await setting("steamAPIKey");
|
const steamAPIKey = await setting("steamAPIKey");
|
||||||
|
|
|
@ -1,23 +1,33 @@
|
||||||
const { MonitorType } = require("./monitor-type");
|
const { MonitorType } = require("./monitor-type");
|
||||||
|
const { UP, DOWN, PENDING, MAINTENANCE } = require("../../src/util");
|
||||||
|
|
||||||
class ManualMonitorType extends MonitorType {
|
class ManualMonitorType extends MonitorType {
|
||||||
name = "Manual";
|
name = "Manual";
|
||||||
type = "manual";
|
type = "manual";
|
||||||
description = "Manual monitoring";
|
description = "A monitor that allows manual control of the status";
|
||||||
supportsConditions = false;
|
supportsConditions = false;
|
||||||
conditionVariables = [];
|
conditionVariables = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks the status of the monitor manually
|
* Checks the status of the monitor based on the manually set status
|
||||||
* @param {object} monitor - Monitor object
|
* This monitor type is specifically designed for status pages where manual control is needed
|
||||||
|
* @param {object} monitor - Monitor object containing the current status and message
|
||||||
* @param {object} heartbeat - Object to write the status of the check
|
* @param {object} heartbeat - Object to write the status of the check
|
||||||
* @param {object} server - Server object
|
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
async check(monitor, heartbeat, server) {
|
async check(monitor, heartbeat) {
|
||||||
heartbeat.status = monitor.status;
|
if (monitor.manual_status !== null) {
|
||||||
heartbeat.msg = monitor.msg || "Manual monitoring";
|
heartbeat.status = monitor.manual_status;
|
||||||
heartbeat.time = new Date().getTime();
|
heartbeat.msg = monitor.manual_status === UP ? "Up" :
|
||||||
|
monitor.manual_status === DOWN ? "Down" :
|
||||||
|
monitor.manual_status === MAINTENANCE ? "Maintenance" :
|
||||||
|
"Pending";
|
||||||
|
heartbeat.ping = null;
|
||||||
|
} else {
|
||||||
|
heartbeat.status = PENDING;
|
||||||
|
heartbeat.msg = "Manual monitoring - No status set";
|
||||||
|
heartbeat.ping = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ if (!semver.satisfies(nodeVersion, requiredNodeVersions)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const args = require("args-parser")(process.argv);
|
const args = require("args-parser")(process.argv);
|
||||||
const { sleep, log, getRandomInt, genSecret, isDev } = require("../src/util");
|
const { sleep, log, getRandomInt, genSecret, isDev, UP, DOWN, PENDING, MAINTENANCE } = require("../src/util");
|
||||||
const config = require("./config");
|
const config = require("./config");
|
||||||
|
|
||||||
log.debug("server", "Arguments");
|
log.debug("server", "Arguments");
|
||||||
|
@ -1542,34 +1542,6 @@ let needSetup = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on("addHeartbeat", async (heartbeat, callback) => {
|
|
||||||
try {
|
|
||||||
checkLogin(socket);
|
|
||||||
|
|
||||||
let bean = R.dispense("heartbeat");
|
|
||||||
bean.monitor_id = heartbeat.monitorID;
|
|
||||||
bean.status = heartbeat.status;
|
|
||||||
bean.msg = heartbeat.msg;
|
|
||||||
bean.time = heartbeat.time;
|
|
||||||
bean.ping = heartbeat.ping;
|
|
||||||
bean.important = true;
|
|
||||||
|
|
||||||
await R.store(bean);
|
|
||||||
|
|
||||||
io.to(socket.userID).emit("heartbeat", bean.toJSON());
|
|
||||||
|
|
||||||
callback({
|
|
||||||
ok: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
} catch (e) {
|
|
||||||
callback({
|
|
||||||
ok: false,
|
|
||||||
msg: e.message,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
socket.on("clearStatistics", async (callback) => {
|
socket.on("clearStatistics", async (callback) => {
|
||||||
try {
|
try {
|
||||||
checkLogin(socket);
|
checkLogin(socket);
|
||||||
|
@ -1626,6 +1598,48 @@ let needSetup = false;
|
||||||
log.debug("auth", "need auth");
|
log.debug("auth", "need auth");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
socket.on("updateManual", async (data, callback) => {
|
||||||
|
try {
|
||||||
|
checkLogin(socket);
|
||||||
|
|
||||||
|
let monitor = await R.findOne("monitor", " id = ? AND user_id = ? ", [
|
||||||
|
data.monitorID,
|
||||||
|
socket.userID,
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!monitor) {
|
||||||
|
throw new Error("Monitor not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
let status;
|
||||||
|
if (data.status === 1) {
|
||||||
|
status = UP;
|
||||||
|
} else if (data.status === 0) {
|
||||||
|
status = DOWN;
|
||||||
|
} else if (data.status === 3) {
|
||||||
|
status = MAINTENANCE;
|
||||||
|
} else {
|
||||||
|
status = PENDING;
|
||||||
|
}
|
||||||
|
|
||||||
|
monitor.manual_status = status;
|
||||||
|
await R.store(monitor);
|
||||||
|
|
||||||
|
callback({
|
||||||
|
ok: true,
|
||||||
|
msg: "Saved.",
|
||||||
|
msgi18n: true,
|
||||||
|
id: monitor.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
callback({
|
||||||
|
ok: true,
|
||||||
|
msg: e.message,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
log.debug("server", "Init the server");
|
log.debug("server", "Init the server");
|
||||||
|
|
|
@ -543,10 +543,6 @@ class UptimeCalculator {
|
||||||
* @throws {Error} Invalid status
|
* @throws {Error} Invalid status
|
||||||
*/
|
*/
|
||||||
flatStatus(status) {
|
flatStatus(status) {
|
||||||
if (typeof status !== "number") {
|
|
||||||
throw new Error("Invalid status: status must be a number");
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case UP:
|
case UP:
|
||||||
case MAINTENANCE:
|
case MAINTENANCE:
|
||||||
|
@ -554,9 +550,8 @@ class UptimeCalculator {
|
||||||
case DOWN:
|
case DOWN:
|
||||||
case PENDING:
|
case PENDING:
|
||||||
return DOWN;
|
return DOWN;
|
||||||
default:
|
|
||||||
throw new Error("Invalid status: " + status);
|
|
||||||
}
|
}
|
||||||
|
throw new Error("Invalid status");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -7,7 +7,7 @@ export default {
|
||||||
props: {
|
props: {
|
||||||
/** Value of date time */
|
/** Value of date time */
|
||||||
value: {
|
value: {
|
||||||
type: [ String, Number ],
|
type: String,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
/** Should only the date be displayed? */
|
/** Should only the date be displayed? */
|
||||||
|
|
|
@ -1110,8 +1110,5 @@
|
||||||
"Sender name": "Sender name",
|
"Sender name": "Sender name",
|
||||||
"smsplanetNeedToApproveName": "Needs to be approved in the client panel",
|
"smsplanetNeedToApproveName": "Needs to be approved in the client panel",
|
||||||
"Disable URL in Notification": "Disable URL in Notification",
|
"Disable URL in Notification": "Disable URL in Notification",
|
||||||
"Manual": "Manual",
|
"Manual": "Manual"
|
||||||
"Manual Status": "Manual Status",
|
|
||||||
"Manual status set to": "Manual status set to",
|
|
||||||
"Status updated": "Status updated"
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -776,7 +776,7 @@
|
||||||
|
|
||||||
<div v-if="monitor.type === 'manual'" class="mb-3">
|
<div v-if="monitor.type === 'manual'" class="mb-3">
|
||||||
<label class="form-label">{{ $t("Manual Status") }}</label>
|
<label class="form-label">{{ $t("Manual Status") }}</label>
|
||||||
<div class="btn-group w-100">
|
<div v-if="!isAdd" class="btn-group w-100 mb-3">
|
||||||
<button class="btn btn-success" @click="setManualStatus('up')">
|
<button class="btn btn-success" @click="setManualStatus('up')">
|
||||||
<i class="fas fa-check"></i> {{ $t("Up") }}
|
<i class="fas fa-check"></i> {{ $t("Up") }}
|
||||||
</button>
|
</button>
|
||||||
|
@ -787,6 +787,9 @@
|
||||||
<i class="fas fa-tools"></i> {{ $t("Maintenance") }}
|
<i class="fas fa-tools"></i> {{ $t("Maintenance") }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-else class="alert alert-secondary">
|
||||||
|
{{ $t("Manual status can be set after monitor is created") }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1229,6 +1232,7 @@ export default {
|
||||||
remoteBrowsersEnabled: false,
|
remoteBrowsersEnabled: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
timeoutStep() {
|
timeoutStep() {
|
||||||
return this.monitor.type === "ping" ? 1 : 0.1;
|
return this.monitor.type === "ping" ? 1 : 0.1;
|
||||||
|
@ -2039,12 +2043,11 @@ message HealthCheckResponse {
|
||||||
let updatedMonitor = { ...this.monitor };
|
let updatedMonitor = { ...this.monitor };
|
||||||
updatedMonitor.id = this.monitor.id;
|
updatedMonitor.id = this.monitor.id;
|
||||||
|
|
||||||
this.$root.getSocket().emit("addHeartbeat", {
|
this.$root.getSocket().emit("updateManual", {
|
||||||
monitorID: this.monitor.id,
|
monitorID: this.monitor.id,
|
||||||
status: status === "up" ? 1 : status === "down" ? 0 : status === "maintenance" ? 3 : 2,
|
status: status === "up" ? 1 : status === "down" ? 0 : 3,
|
||||||
msg: status === "up" ? "Up" : status === "down" ? "Down" : "Maintenance",
|
msg: status === "up" ? "Up" : status === "down" ? "Down" : "Maintenance",
|
||||||
time: new Date().getTime(),
|
time: new Date().getTime(),
|
||||||
ping: 0
|
|
||||||
}, (res) => {
|
}, (res) => {
|
||||||
if (res.ok) {
|
if (res.ok) {
|
||||||
this.toast.success(this.$t("Success"));
|
this.toast.success(this.$t("Success"));
|
||||||
|
|
Loading…
Add table
Reference in a new issue