mirror of
https://github.com/louislam/uptime-kuma.git
synced 2025-09-11 22:06:59 +08:00
Compare commits
19 Commits
1.23.5-bet
...
1.23.7
Author | SHA1 | Date | |
---|---|---|---|
|
73239d441d | ||
|
4ceeb304f1 | ||
|
711380bbbe | ||
|
9536c6aa6a | ||
|
4255496b11 | ||
|
f28dccf4e1 | ||
|
b689733d59 | ||
|
afaa7bb2f0 | ||
|
121d1a11af | ||
|
8e61158758 | ||
|
bf58838b89 | ||
|
33ce0ef02c | ||
|
c1aaad0d85 | ||
|
954e05b72f | ||
|
6d4a45f18c | ||
|
f0975cd929 | ||
|
40d6a21453 | ||
|
b383392e8f | ||
|
9964b6c4d8 |
@@ -15,12 +15,14 @@ ALTER TABLE monitor
|
||||
ALTER TABLE monitor
|
||||
ADD COLUMN kafka_producer_allow_auto_topic_creation BOOLEAN default 0 NOT NULL;
|
||||
|
||||
-- Set bring old values from `_old` COLUMNs to correct ones
|
||||
UPDATE monitor SET kafka_producer_allow_auto_topic_creation = monitor.kafka_producer_allow_auto_topic_creation_old
|
||||
WHERE monitor.kafka_producer_allow_auto_topic_creation_old IS NOT NULL;
|
||||
-- These SQL is still not fully safe. See https://github.com/louislam/uptime-kuma/issues/4039.
|
||||
|
||||
UPDATE monitor SET kafka_producer_ssl = monitor.kafka_producer_ssl_old
|
||||
WHERE monitor.kafka_producer_ssl_old IS NOT NULL;
|
||||
-- Set bring old values from `_old` COLUMNs to correct ones
|
||||
-- UPDATE monitor SET kafka_producer_allow_auto_topic_creation = monitor.kafka_producer_allow_auto_topic_creation_old
|
||||
-- WHERE monitor.kafka_producer_allow_auto_topic_creation_old IS NOT NULL;
|
||||
|
||||
-- UPDATE monitor SET kafka_producer_ssl = monitor.kafka_producer_ssl_old
|
||||
-- WHERE monitor.kafka_producer_ssl_old IS NOT NULL;
|
||||
|
||||
-- Remove old COLUMNs
|
||||
ALTER TABLE monitor
|
||||
|
7
db/patch-timeout.sql
Normal file
7
db/patch-timeout.sql
Normal file
@@ -0,0 +1,7 @@
|
||||
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
|
||||
BEGIN TRANSACTION;
|
||||
|
||||
UPDATE monitor SET timeout = (interval * 0.8)
|
||||
WHERE timeout IS NULL OR timeout <= 0;
|
||||
|
||||
COMMIT;
|
44
extra/reformat-changelog.js
Normal file
44
extra/reformat-changelog.js
Normal file
@@ -0,0 +1,44 @@
|
||||
// Generate on GitHub
|
||||
const input = `
|
||||
* Add Korean translation by @Alanimdeo in https://github.com/louislam/dockge/pull/86
|
||||
`;
|
||||
|
||||
const template = `
|
||||
### 🆕 New Features
|
||||
|
||||
### 💇♀️ Improvements
|
||||
|
||||
### 🐞 Bug Fixes
|
||||
|
||||
### ⬆️ Security Fixes
|
||||
|
||||
### 🦎 Translation Contributions
|
||||
|
||||
### Others
|
||||
- Other small changes, code refactoring and comment/doc updates in this repo:
|
||||
`;
|
||||
|
||||
const lines = input.split("\n").filter((line) => line.trim() !== "");
|
||||
|
||||
for (const line of lines) {
|
||||
// Split the last " by "
|
||||
const usernamePullRequesURL = line.split(" by ").pop();
|
||||
|
||||
if (!usernamePullRequesURL) {
|
||||
console.log("Unable to parse", line);
|
||||
continue;
|
||||
}
|
||||
|
||||
const [ username, pullRequestURL ] = usernamePullRequesURL.split(" in ");
|
||||
const pullRequestID = "#" + pullRequestURL.split("/").pop();
|
||||
let message = line.split(" by ").shift();
|
||||
|
||||
if (!message) {
|
||||
console.log("Unable to parse", line);
|
||||
continue;
|
||||
}
|
||||
|
||||
message = message.split("* ").pop();
|
||||
console.log("-", pullRequestID, message, `(Thanks ${username})`);
|
||||
}
|
||||
console.log(template);
|
18
package-lock.json
generated
18
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "uptime-kuma",
|
||||
"version": "1.23.4",
|
||||
"version": "1.23.7",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "uptime-kuma",
|
||||
"version": "1.23.4",
|
||||
"version": "1.23.7",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@grpc/grpc-js": "~1.7.3",
|
||||
@@ -33,6 +33,7 @@
|
||||
"express-static-gzip": "~2.1.7",
|
||||
"form-data": "~4.0.0",
|
||||
"gamedig": "~4.1.0",
|
||||
"html-escaper": "^3.0.3",
|
||||
"http-graceful-shutdown": "~3.1.7",
|
||||
"http-proxy-agent": "~5.0.0",
|
||||
"https-proxy-agent": "~5.0.1",
|
||||
@@ -10747,10 +10748,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/html-escaper": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
|
||||
"integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
|
||||
"dev": true
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz",
|
||||
"integrity": "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ=="
|
||||
},
|
||||
"node_modules/html-tags": {
|
||||
"version": "3.3.1",
|
||||
@@ -11558,6 +11558,12 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/istanbul-reports/node_modules/html-escaper": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
|
||||
"integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/jackspeak": {
|
||||
"version": "2.3.6",
|
||||
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "uptime-kuma",
|
||||
"version": "1.23.4",
|
||||
"version": "1.23.7",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -40,7 +40,7 @@
|
||||
"build-docker-nightly-amd64": "docker buildx build -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:nightly-amd64 --target nightly . --push --progress plain",
|
||||
"build-docker-pr-test": "docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64 -t louislam/uptime-kuma:pr-test --target pr-test . --push",
|
||||
"upload-artifacts": "docker buildx build -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:upload-artifact --build-arg VERSION --build-arg GITHUB_TOKEN --target upload-artifact . --progress plain",
|
||||
"setup": "git checkout 1.23.4 && npm ci --production && npm run download-dist",
|
||||
"setup": "git checkout 1.23.7 && npm ci --production && npm run download-dist",
|
||||
"download-dist": "node extra/download-dist.js",
|
||||
"mark-as-nightly": "node extra/mark-as-nightly.js",
|
||||
"reset-password": "node extra/reset-password.js",
|
||||
@@ -72,7 +72,8 @@
|
||||
"cypress-open": "concurrently -k -r \"node test/prepare-test-server.js && node server/server.js --port=3002 --data-dir=./data/test/\" \"cypress open --config-file ./config/cypress.config.js\"",
|
||||
"build-healthcheck-armv7": "cross-env GOOS=linux GOARCH=arm GOARM=7 go build -x -o ./extra/healthcheck-armv7 ./extra/healthcheck.go",
|
||||
"deploy-demo-server": "node extra/deploy-demo-server.js",
|
||||
"sort-contributors": "node extra/sort-contributors.js"
|
||||
"sort-contributors": "node extra/sort-contributors.js",
|
||||
"start-server-node14-win": "private\\node14\\node.exe server/server.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@grpc/grpc-js": "~1.7.3",
|
||||
@@ -99,6 +100,7 @@
|
||||
"express-static-gzip": "~2.1.7",
|
||||
"form-data": "~4.0.0",
|
||||
"gamedig": "~4.1.0",
|
||||
"html-escaper": "^3.0.3",
|
||||
"http-graceful-shutdown": "~3.1.7",
|
||||
"http-proxy-agent": "~5.0.0",
|
||||
"https-proxy-agent": "~5.0.1",
|
||||
|
@@ -83,6 +83,7 @@ class Database {
|
||||
"patch-add-gamedig-given-port.sql": true,
|
||||
"patch-notification-config.sql": true,
|
||||
"patch-fix-kafka-producer-booleans.sql": true,
|
||||
"patch-timeout.sql": true,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -1,4 +1,5 @@
|
||||
const jsesc = require("jsesc");
|
||||
const { escape } = require("html-escaper");
|
||||
|
||||
/**
|
||||
* Returns a string that represents the javascript that is required to insert the Google Analytics scripts
|
||||
@@ -7,15 +8,18 @@ const jsesc = require("jsesc");
|
||||
* @returns {string}
|
||||
*/
|
||||
function getGoogleAnalyticsScript(tagId) {
|
||||
let escapedTagId = jsesc(tagId, { isScriptContext: true });
|
||||
let escapedTagIdJS = jsesc(tagId, { isScriptContext: true });
|
||||
|
||||
if (escapedTagId) {
|
||||
escapedTagId = escapedTagId.trim();
|
||||
if (escapedTagIdJS) {
|
||||
escapedTagIdJS = escapedTagIdJS.trim();
|
||||
}
|
||||
|
||||
// Escape the tag ID for use in an HTML attribute.
|
||||
let escapedTagIdHTMLAttribute = escape(tagId);
|
||||
|
||||
return `
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=${escapedTagId}"></script>
|
||||
<script>window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date());gtag('config', '${escapedTagId}'); </script>
|
||||
<script async src="https://www.googletagmanager.com/gtag/js?id=${escapedTagIdHTMLAttribute}"></script>
|
||||
<script>window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date());gtag('config', '${escapedTagIdJS}'); </script>
|
||||
`;
|
||||
}
|
||||
|
||||
|
@@ -3,7 +3,7 @@ const dayjs = require("dayjs");
|
||||
const axios = require("axios");
|
||||
const { Prometheus } = require("../prometheus");
|
||||
const { log, UP, DOWN, PENDING, MAINTENANCE, flipStatus, TimeLogger, MAX_INTERVAL_SECOND, MIN_INTERVAL_SECOND,
|
||||
SQL_DATETIME_FORMAT, isDev, sleep, getRandomInt
|
||||
SQL_DATETIME_FORMAT
|
||||
} = require("../../src/util");
|
||||
const { tcping, ping, dnsResolve, checkCertificate, checkStatusCode, getTotalClientInRoom, setting, mssqlQuery, postgresQuery, mysqlQuery, mqttAsync, setSetting, httpNtlm, radius, grpcQuery,
|
||||
redisPingAsync, mongodbPing, kafkaProducerAsync, getOidcTokenClientCredentials, rootCertificatesFingerprints, axiosAbortSignal
|
||||
@@ -22,6 +22,7 @@ const { UptimeCacheList } = require("../uptime-cache-list");
|
||||
const Gamedig = require("gamedig");
|
||||
const jsonata = require("jsonata");
|
||||
const jwt = require("jsonwebtoken");
|
||||
const crypto = require("crypto");
|
||||
|
||||
const rootCertificates = rootCertificatesFingerprints();
|
||||
|
||||
@@ -328,16 +329,6 @@ class Monitor extends BeanModel {
|
||||
}
|
||||
}
|
||||
|
||||
// Evil
|
||||
if (isDev) {
|
||||
if (process.env.EVIL_RANDOM_MONITOR_SLEEP === "SURE") {
|
||||
if (getRandomInt(0, 100) === 0) {
|
||||
log.debug("evil", `[${this.name}] Evil mode: Random sleep: ` + beatInterval * 10000);
|
||||
await sleep(beatInterval * 10000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Expose here for prometheus update
|
||||
// undefined if not https
|
||||
let tlsInfo = undefined;
|
||||
@@ -369,7 +360,7 @@ class Monitor extends BeanModel {
|
||||
|
||||
// Runtime patch timeout if it is 0
|
||||
// See https://github.com/louislam/uptime-kuma/pull/3961#issuecomment-1804149144
|
||||
if (this.timeout <= 0) {
|
||||
if (!this.timeout || this.timeout <= 0) {
|
||||
this.timeout = this.interval * 1000 * 0.8;
|
||||
}
|
||||
|
||||
@@ -443,6 +434,7 @@ class Monitor extends BeanModel {
|
||||
const httpsAgentOptions = {
|
||||
maxCachedSessions: 0, // Use Custom agent to disable session reuse (https://github.com/nodejs/node/issues/3940)
|
||||
rejectUnauthorized: !this.getIgnoreTls(),
|
||||
secureOptions: crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT,
|
||||
};
|
||||
|
||||
log.debug("monitor", `[${this.name}] Prepare Options for axios`);
|
||||
@@ -481,7 +473,7 @@ class Monitor extends BeanModel {
|
||||
validateStatus: (status) => {
|
||||
return checkStatusCode(status, this.getAcceptedStatuscodes());
|
||||
},
|
||||
signal: axiosAbortSignal(this.timeout * 1000),
|
||||
signal: axiosAbortSignal((this.timeout + 10) * 1000),
|
||||
};
|
||||
|
||||
if (bodyValue) {
|
||||
@@ -697,6 +689,7 @@ class Monitor extends BeanModel {
|
||||
httpsAgent: CacheableDnsHttpAgent.getHttpsAgent({
|
||||
maxCachedSessions: 0, // Use Custom agent to disable session reuse (https://github.com/nodejs/node/issues/3940)
|
||||
rejectUnauthorized: !this.getIgnoreTls(),
|
||||
secureOptions: crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT,
|
||||
}),
|
||||
httpAgent: CacheableDnsHttpAgent.getHttpAgent({
|
||||
maxCachedSessions: 0,
|
||||
@@ -749,6 +742,7 @@ class Monitor extends BeanModel {
|
||||
httpsAgent: CacheableDnsHttpAgent.getHttpsAgent({
|
||||
maxCachedSessions: 0, // Use Custom agent to disable session reuse (https://github.com/nodejs/node/issues/3940)
|
||||
rejectUnauthorized: !this.getIgnoreTls(),
|
||||
secureOptions: crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT,
|
||||
}),
|
||||
httpAgent: CacheableDnsHttpAgent.getHttpAgent({
|
||||
maxCachedSessions: 0,
|
||||
@@ -934,7 +928,11 @@ class Monitor extends BeanModel {
|
||||
|
||||
} catch (error) {
|
||||
|
||||
bean.msg = error.message;
|
||||
if (error?.name === "CanceledError") {
|
||||
bean.msg = `timeout by AbortSignal (${this.timeout}s)`;
|
||||
} else {
|
||||
bean.msg = error.message;
|
||||
}
|
||||
|
||||
// If UP come in here, it must be upside down mode
|
||||
// Just reset the retries
|
||||
@@ -1016,7 +1014,6 @@ class Monitor extends BeanModel {
|
||||
if (! this.isStop) {
|
||||
log.debug("monitor", `[${this.name}] SetTimeout for next check.`);
|
||||
this.heartbeatInterval = setTimeout(safeBeat, beatInterval * 1000);
|
||||
this.lastScheduleBeatTime = dayjs();
|
||||
} else {
|
||||
log.info("monitor", `[${this.name}] isStop = true, no next check.`);
|
||||
}
|
||||
@@ -1026,9 +1023,7 @@ class Monitor extends BeanModel {
|
||||
/** Get a heartbeat and handle errors */
|
||||
const safeBeat = async () => {
|
||||
try {
|
||||
this.lastStartBeatTime = dayjs();
|
||||
await beat();
|
||||
this.lastEndBeatTime = dayjs();
|
||||
} catch (e) {
|
||||
console.trace(e);
|
||||
UptimeKumaServer.errorLog(e, false);
|
||||
@@ -1037,9 +1032,6 @@ class Monitor extends BeanModel {
|
||||
if (! this.isStop) {
|
||||
log.info("monitor", "Try to restart the monitor");
|
||||
this.heartbeatInterval = setTimeout(safeBeat, this.interval * 1000);
|
||||
this.lastScheduleBeatTime = dayjs();
|
||||
} else {
|
||||
log.info("monitor", "isStop = true, no next check.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@@ -1,6 +1,6 @@
|
||||
const { MonitorType } = require("./monitor-type");
|
||||
const { UP, log } = require("../../src/util");
|
||||
const exec = require("child_process").exec;
|
||||
const { UP } = require("../../src/util");
|
||||
const childProcess = require("child_process");
|
||||
|
||||
/**
|
||||
* A TailscalePing class extends the MonitorType.
|
||||
@@ -23,7 +23,6 @@ class TailscalePing extends MonitorType {
|
||||
let tailscaleOutput = await this.runTailscalePing(monitor.hostname, monitor.interval);
|
||||
this.parseTailscaleOutput(tailscaleOutput, heartbeat);
|
||||
} catch (err) {
|
||||
log.debug("Tailscale", err);
|
||||
// trigger log function somewhere to display a notification or alert to the user (but how?)
|
||||
throw new Error(`Error checking Tailscale ping: ${err}`);
|
||||
}
|
||||
@@ -33,30 +32,26 @@ class TailscalePing extends MonitorType {
|
||||
* Runs the Tailscale ping command to the given URL.
|
||||
*
|
||||
* @param {string} hostname - The hostname to ping.
|
||||
* @param {number} interval
|
||||
* @returns {Promise<string>} - A Promise that resolves to the output of the Tailscale ping command
|
||||
* @throws Will throw an error if the command execution encounters any error.
|
||||
*/
|
||||
async runTailscalePing(hostname, interval) {
|
||||
let cmd = `tailscale ping ${hostname}`;
|
||||
|
||||
log.debug("Tailscale", cmd);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
let timeout = interval * 1000 * 0.8;
|
||||
exec(cmd, { timeout: timeout }, (error, stdout, stderr) => {
|
||||
// we may need to handle more cases if tailscale reports an error that isn't necessarily an error (such as not-logged in or DERP health-related issues)
|
||||
if (error) {
|
||||
reject(`Execution error: ${error.message}`);
|
||||
return;
|
||||
}
|
||||
if (stderr) {
|
||||
reject(`Error in output: ${stderr}`);
|
||||
return;
|
||||
}
|
||||
|
||||
resolve(stdout);
|
||||
});
|
||||
let timeout = interval * 1000 * 0.8;
|
||||
let res = childProcess.spawnSync("tailscale", [ "ping", hostname ], {
|
||||
timeout: timeout
|
||||
});
|
||||
if (res.error) {
|
||||
throw new Error(`Execution error: ${res.error.message}`);
|
||||
}
|
||||
if (res.stderr && res.stderr.toString()) {
|
||||
throw new Error(`Error in output: ${res.stderr.toString()}`);
|
||||
}
|
||||
if (res.stdout && res.stdout.toString()) {
|
||||
return res.stdout.toString();
|
||||
} else {
|
||||
throw new Error("No output from Tailscale ping");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,7 +69,7 @@ class TailscalePing extends MonitorType {
|
||||
heartbeat.status = UP;
|
||||
let time = line.split(" in ")[1].split(" ")[0];
|
||||
heartbeat.ping = parseInt(time);
|
||||
heartbeat.msg = line;
|
||||
heartbeat.msg = "OK";
|
||||
break;
|
||||
} else if (line.includes("timed out")) {
|
||||
throw new Error(`Ping timed out: "${line}"`);
|
||||
|
@@ -1832,6 +1832,7 @@ async function pauseMonitor(userID, monitorID) {
|
||||
|
||||
if (monitorID in server.monitorList) {
|
||||
server.monitorList[monitorID].stop();
|
||||
server.monitorList[monitorID].active = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -42,24 +42,40 @@ module.exports.generalSocketHandler = (socket, server) => {
|
||||
});
|
||||
|
||||
socket.on("getGameList", async (callback) => {
|
||||
callback({
|
||||
ok: true,
|
||||
gameList: getGameList(),
|
||||
});
|
||||
});
|
||||
|
||||
socket.on("testChrome", (executable, callback) => {
|
||||
// Just noticed that await call could block the whole socket.io server!!! Use pure promise instead.
|
||||
testChrome(executable).then((version) => {
|
||||
try {
|
||||
checkLogin(socket);
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Found Chromium/Chrome. Version: " + version,
|
||||
gameList: getGameList(),
|
||||
});
|
||||
}).catch((e) => {
|
||||
} catch (e) {
|
||||
callback({
|
||||
ok: false,
|
||||
msg: e.message,
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
socket.on("testChrome", (executable, callback) => {
|
||||
try {
|
||||
checkLogin(socket);
|
||||
// Just noticed that await call could block the whole socket.io server!!! Use pure promise instead.
|
||||
testChrome(executable).then((version) => {
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Found Chromium/Chrome. Version: " + version,
|
||||
});
|
||||
}).catch((e) => {
|
||||
callback({
|
||||
ok: false,
|
||||
msg: e.message,
|
||||
});
|
||||
});
|
||||
} catch (e) {
|
||||
callback({
|
||||
ok: false,
|
||||
msg: e.message,
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@@ -12,7 +12,6 @@ const { Settings } = require("./settings");
|
||||
const dayjs = require("dayjs");
|
||||
const childProcess = require("child_process");
|
||||
const path = require("path");
|
||||
const axios = require("axios");
|
||||
// DO NOT IMPORT HERE IF THE MODULES USED `UptimeKumaServer.getInstance()`, put at the bottom of this file instead.
|
||||
|
||||
/**
|
||||
@@ -63,8 +62,6 @@ class UptimeKumaServer {
|
||||
*/
|
||||
jwtSecret = null;
|
||||
|
||||
checkMonitorsInterval = null;
|
||||
|
||||
static getInstance(args) {
|
||||
if (UptimeKumaServer.instance == null) {
|
||||
UptimeKumaServer.instance = new UptimeKumaServer(args);
|
||||
@@ -78,9 +75,6 @@ class UptimeKumaServer {
|
||||
const sslCert = args["ssl-cert"] || process.env.UPTIME_KUMA_SSL_CERT || process.env.SSL_CERT || undefined;
|
||||
const sslKeyPassphrase = args["ssl-key-passphrase"] || process.env.UPTIME_KUMA_SSL_KEY_PASSPHRASE || process.env.SSL_KEY_PASSPHRASE || undefined;
|
||||
|
||||
// Set default axios timeout to 5 minutes instead of infinity
|
||||
axios.defaults.timeout = 300 * 1000;
|
||||
|
||||
log.info("server", "Creating express and socket.io instance");
|
||||
this.app = express();
|
||||
if (sslKey && sslCert) {
|
||||
@@ -352,10 +346,6 @@ class UptimeKumaServer {
|
||||
if (enable || enable === null) {
|
||||
this.startNSCDServices();
|
||||
}
|
||||
|
||||
this.checkMonitorsInterval = setInterval(() => {
|
||||
this.checkMonitors();
|
||||
}, 60 * 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -368,8 +358,6 @@ class UptimeKumaServer {
|
||||
if (enable || enable === null) {
|
||||
this.stopNSCDServices();
|
||||
}
|
||||
|
||||
clearInterval(this.checkMonitorsInterval);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -400,83 +388,6 @@ class UptimeKumaServer {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the specified monitor
|
||||
* @param {number} monitorID ID of monitor to start
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async startMonitor(monitorID) {
|
||||
log.info("manage", `Resume Monitor: ${monitorID} by server`);
|
||||
|
||||
await R.exec("UPDATE monitor SET active = 1 WHERE id = ?", [
|
||||
monitorID,
|
||||
]);
|
||||
|
||||
let monitor = await R.findOne("monitor", " id = ? ", [
|
||||
monitorID,
|
||||
]);
|
||||
|
||||
if (monitor.id in this.monitorList) {
|
||||
this.monitorList[monitor.id].stop();
|
||||
}
|
||||
|
||||
this.monitorList[monitor.id] = monitor;
|
||||
monitor.start(this.io);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restart a given monitor
|
||||
* @param {number} monitorID ID of monitor to start
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async restartMonitor(monitorID) {
|
||||
return await this.startMonitor(monitorID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if monitors are running properly
|
||||
*/
|
||||
async checkMonitors() {
|
||||
log.debug("monitor_checker", "Checking monitors");
|
||||
|
||||
for (let monitorID in this.monitorList) {
|
||||
let monitor = this.monitorList[monitorID];
|
||||
|
||||
// Not for push monitor
|
||||
if (monitor.type === "push") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!monitor.active) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check the lastStartBeatTime, if it is too long, then restart
|
||||
if (monitor.lastScheduleBeatTime ) {
|
||||
let diff = dayjs().diff(monitor.lastStartBeatTime, "second");
|
||||
|
||||
if (diff > monitor.interval * 1.5) {
|
||||
log.error("monitor_checker", `Monitor Interval: ${monitor.interval} Monitor ` + monitorID + " lastStartBeatTime diff: " + diff);
|
||||
log.error("monitor_checker", "Unexpected error: Monitor " + monitorID + " is struck for unknown reason");
|
||||
log.error("monitor_checker", "Last start beat time: " + R.isoDateTime(monitor.lastStartBeatTime));
|
||||
log.error("monitor_checker", "Last end beat time: " + R.isoDateTime(monitor.lastEndBeatTime));
|
||||
log.error("monitor_checker", "Last ScheduleBeatTime: " + R.isoDateTime(monitor.lastScheduleBeatTime));
|
||||
|
||||
// Restart
|
||||
log.error("monitor_checker", `Restarting monitor ${monitorID} automatically now`);
|
||||
this.restartMonitor(monitorID);
|
||||
} else {
|
||||
//log.debug("monitor_checker", "Monitor " + monitorID + " is running normally");
|
||||
}
|
||||
} else {
|
||||
//log.debug("monitor_checker", "Monitor " + monitorID + " is not started yet, skipp");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
log.debug("monitor_checker", "Checking monitors end");
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
@@ -458,6 +458,7 @@ exports.postgresQuery = function (connectionString, query) {
|
||||
});
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
client.end();
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1141,7 +1142,6 @@ module.exports.axiosAbortSignal = (timeoutMs) => {
|
||||
// v16-: AbortSignal.timeout is not supported
|
||||
try {
|
||||
const abortController = new AbortController();
|
||||
|
||||
setTimeout(() => abortController.abort(), timeoutMs);
|
||||
|
||||
return abortController.signal;
|
||||
|
@@ -101,6 +101,9 @@ class Logger {
|
||||
* @param level Log level. One of INFO, WARN, ERROR, DEBUG or can be customized.
|
||||
*/
|
||||
log(module, msg, level) {
|
||||
if (level === "DEBUG" && !exports.isDev) {
|
||||
return;
|
||||
}
|
||||
if (this.hideLog[level] && this.hideLog[level].includes(module.toLowerCase())) {
|
||||
return;
|
||||
}
|
||||
|
@@ -115,6 +115,10 @@ class Logger {
|
||||
* @param level Log level. One of INFO, WARN, ERROR, DEBUG or can be customized.
|
||||
*/
|
||||
log(module: string, msg: any, level: string) {
|
||||
if (level === "DEBUG" && !isDev) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.hideLog[level] && this.hideLog[level].includes(module.toLowerCase())) {
|
||||
return;
|
||||
}
|
||||
|
Reference in New Issue
Block a user