From 48d91cd15ee0231208efcacdcaa402ce7df3a1be Mon Sep 17 00:00:00 2001 From: Cassandra Beelen Date: Thu, 19 Sep 2024 09:36:33 +0200 Subject: [PATCH 1/7] chore: addressing of simple deprecations surrounding `Settings` and `log` Co-authored-by: Frank Elsinga Closes: #4391 Squashed commit of the following: commit 828d2a73d42df7f05a762060c61999102c11cc76 Merge: 10f771cf dd758903 Author: Frank Elsinga Date: Fri Sep 13 22:51:25 2024 +0800 Merge branch 'master' into deprecations commit 10f771cfc6114d47cf4a177f2b714fda0f62f24e Author: Frank Elsinga Date: Thu Jan 18 22:36:12 2024 +0100 formatting fixes commit d737b19e2ff865ff9a013e922a76a95d14ef9b6d Author: Frank Elsinga Date: Thu Jan 18 21:27:30 2024 +0100 migrated all settings to use the `Settings` class commit c5e26e993ef1d71f838d03d4e5c9324ab3aad840 Author: Frank Elsinga Date: Thu Jan 18 21:04:44 2024 +0100 removed the deprecated logging functionality --- server/auth.js | 3 +- server/check-version.js | 8 ++-- server/client.js | 4 +- server/database.js | 28 ++++++------- server/jobs/clear-old-data.js | 8 ++-- server/model/monitor.js | 10 +++-- server/notification-providers/alertnow.js | 4 +- server/notification-providers/flashduty.js | 4 +- server/notification-providers/google-chat.js | 7 ++-- server/notification-providers/pagerduty.js | 4 +- server/notification-providers/pagertree.js | 4 +- server/notification-providers/rocket-chat.js | 4 +- server/notification-providers/slack.js | 11 +++-- server/notification-providers/splunk.js | 4 +- server/notification-providers/stackfield.js | 4 +- server/proxy.js | 8 ++-- server/routers/api-router.js | 4 +- server/server.js | 15 ++++--- .../cloudflared-socket-handler.js | 15 +++---- .../status-page-socket-handler.js | 7 ++-- server/util-server.js | 40 ------------------- src/util.ts | 9 ----- 22 files changed, 79 insertions(+), 126 deletions(-) diff --git a/server/auth.js b/server/auth.js index 597cf3d753..36316241c8 100644 --- a/server/auth.js +++ b/server/auth.js @@ -1,7 +1,6 @@ const basicAuth = require("express-basic-auth"); const passwordHash = require("./password-hash"); const { R } = require("redbean-node"); -const { setting } = require("./util-server"); const { log } = require("../src/util"); const { loginRateLimiter, apiRateLimiter } = require("./rate-limiter"); const { Settings } = require("./settings"); @@ -139,7 +138,7 @@ exports.basicAuth = async function (req, res, next) { challenge: true, }); - const disabledAuth = await setting("disableAuth"); + const disabledAuth = await Settings.get("disableAuth"); if (!disabledAuth) { middleware(req, res, next); diff --git a/server/check-version.js b/server/check-version.js index c6d5cfb923..154ebe3736 100644 --- a/server/check-version.js +++ b/server/check-version.js @@ -1,7 +1,7 @@ -const { setSetting, setting } = require("./util-server"); const axios = require("axios"); const compareVersions = require("compare-versions"); const { log } = require("../src/util"); +const { Settings } = require("./settings"); exports.version = require("../package.json").version; exports.latestVersion = null; @@ -14,7 +14,7 @@ let interval; exports.startInterval = () => { let check = async () => { - if (await setting("checkUpdate") === false) { + if (await Settings.get("checkUpdate") === false) { return; } @@ -28,7 +28,7 @@ exports.startInterval = () => { res.data.slow = "1000.0.0"; } - let checkBeta = await setting("checkBeta"); + let checkBeta = await Settings.get("checkBeta"); if (checkBeta && res.data.beta) { if (compareVersions.compare(res.data.beta, res.data.slow, ">")) { @@ -57,7 +57,7 @@ exports.startInterval = () => { * @returns {Promise} */ exports.enableCheckUpdate = async (value) => { - await setSetting("checkUpdate", value); + await Settings.set("checkUpdate", value); clearInterval(interval); diff --git a/server/client.js b/server/client.js index 72f0a4e8e2..6929f81aa9 100644 --- a/server/client.js +++ b/server/client.js @@ -6,8 +6,8 @@ const { R } = require("redbean-node"); const { UptimeKumaServer } = require("./uptime-kuma-server"); const server = UptimeKumaServer.getInstance(); const io = server.io; -const { setting } = require("./util-server"); const checkVersion = require("./check-version"); +const { Settings } = require("./settings"); const Database = require("./database"); /** @@ -158,8 +158,8 @@ async function sendInfo(socket, hideVersion = false) { version, latestVersion, isContainer, + primaryBaseURL: await Settings.get("primaryBaseURL"), dbType, - primaryBaseURL: await setting("primaryBaseURL"), serverTimezone: await server.getTimezone(), serverTimezoneOffset: server.getTimezoneOffset(), }); diff --git a/server/database.js b/server/database.js index 3374aff9e6..b23f56db38 100644 --- a/server/database.js +++ b/server/database.js @@ -1,11 +1,11 @@ const fs = require("fs"); const { R } = require("redbean-node"); -const { setSetting, setting } = require("./util-server"); const { log, sleep } = require("../src/util"); const knex = require("knex"); const path = require("path"); const { EmbeddedMariaDB } = require("./embedded-mariadb"); const mysql = require("mysql2/promise"); +const { Settings } = require("./settings"); /** * Database & App Data Folder @@ -420,7 +420,7 @@ class Database { * @deprecated */ static async patchSqlite() { - let version = parseInt(await setting("database_version")); + let version = parseInt(await Settings.get("database_version")); if (! version) { version = 0; @@ -445,7 +445,7 @@ class Database { log.info("db", `Patching ${sqlFile}`); await Database.importSQLFile(sqlFile); log.info("db", `Patched ${sqlFile}`); - await setSetting("database_version", i); + await Settings.set("database_version", i); } } catch (ex) { await Database.close(); @@ -471,7 +471,7 @@ class Database { */ static async patchSqlite2() { log.debug("db", "Database Patch 2.0 Process"); - let databasePatchedFiles = await setting("databasePatchedFiles"); + let databasePatchedFiles = await Settings.get("databasePatchedFiles"); if (! databasePatchedFiles) { databasePatchedFiles = {}; @@ -499,7 +499,7 @@ class Database { process.exit(1); } - await setSetting("databasePatchedFiles", databasePatchedFiles); + await Settings.set("databasePatchedFiles", databasePatchedFiles); } /** @@ -512,7 +512,7 @@ class Database { // Fix 1.13.0 empty slug bug await R.exec("UPDATE status_page SET slug = 'empty-slug-recover' WHERE TRIM(slug) = ''"); - let title = await setting("title"); + let title = await Settings.get("title"); if (title) { console.log("Migrating Status Page"); @@ -527,12 +527,12 @@ class Database { let statusPage = R.dispense("status_page"); statusPage.slug = "default"; statusPage.title = title; - statusPage.description = await setting("description"); - statusPage.icon = await setting("icon"); - statusPage.theme = await setting("statusPageTheme"); - statusPage.published = !!await setting("statusPagePublished"); - statusPage.search_engine_index = !!await setting("searchEngineIndex"); - statusPage.show_tags = !!await setting("statusPageTags"); + statusPage.description = await Settings.get("description"); + statusPage.icon = await Settings.get("icon"); + statusPage.theme = await Settings.get("statusPageTheme"); + statusPage.published = !!await Settings.get("statusPagePublished"); + statusPage.search_engine_index = !!await Settings.get("searchEngineIndex"); + statusPage.show_tags = !!await Settings.get("statusPageTags"); statusPage.password = null; if (!statusPage.title) { @@ -560,10 +560,10 @@ class Database { await R.exec("DELETE FROM setting WHERE type = 'statusPage'"); // Migrate Entry Page if it is status page - let entryPage = await setting("entryPage"); + let entryPage = await Settings.get("entryPage"); if (entryPage === "statusPage") { - await setSetting("entryPage", "statusPage-default", "general"); + await Settings.set("entryPage", "statusPage-default", "general"); } console.log("Migrating Status Page - Done"); diff --git a/server/jobs/clear-old-data.js b/server/jobs/clear-old-data.js index 248a4d409d..b3a1676dc5 100644 --- a/server/jobs/clear-old-data.js +++ b/server/jobs/clear-old-data.js @@ -1,7 +1,7 @@ const { R } = require("redbean-node"); const { log } = require("../../src/util"); -const { setSetting, setting } = require("../util-server"); const Database = require("../database"); +const { Settings } = require("../settings"); const DEFAULT_KEEP_PERIOD = 180; @@ -11,11 +11,11 @@ const DEFAULT_KEEP_PERIOD = 180; */ const clearOldData = async () => { - let period = await setting("keepDataPeriodDays"); + let period = await Settings.get("keepDataPeriodDays"); // Set Default Period if (period == null) { - await setSetting("keepDataPeriodDays", DEFAULT_KEEP_PERIOD, "general"); + await Settings.set("keepDataPeriodDays", DEFAULT_KEEP_PERIOD, "general"); period = DEFAULT_KEEP_PERIOD; } @@ -25,7 +25,7 @@ const clearOldData = async () => { parsedPeriod = parseInt(period); } catch (_) { log.warn("clearOldData", "Failed to parse setting, resetting to default.."); - await setSetting("keepDataPeriodDays", DEFAULT_KEEP_PERIOD, "general"); + await Settings.set("keepDataPeriodDays", DEFAULT_KEEP_PERIOD, "general"); parsedPeriod = DEFAULT_KEEP_PERIOD; } diff --git a/server/model/monitor.js b/server/model/monitor.js index b55e989180..4beeb00369 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -4,7 +4,7 @@ const { Prometheus } = require("../prometheus"); const { log, UP, DOWN, PENDING, MAINTENANCE, flipStatus, MAX_INTERVAL_SECOND, MIN_INTERVAL_SECOND, SQL_DATETIME_FORMAT, evaluateJsonQuery } = require("../../src/util"); -const { tcping, ping, checkCertificate, checkStatusCode, getTotalClientInRoom, setting, mssqlQuery, postgresQuery, mysqlQuery, setSetting, httpNtlm, radius, grpcQuery, +const { tcping, ping, checkCertificate, checkStatusCode, getTotalClientInRoom, mssqlQuery, postgresQuery, mysqlQuery, httpNtlm, radius, grpcQuery, redisPingAsync, kafkaProducerAsync, getOidcTokenClientCredentials, rootCertificatesFingerprints, axiosAbortSignal } = require("../util-server"); const { R } = require("redbean-node"); @@ -24,6 +24,7 @@ const { CookieJar } = require("tough-cookie"); const { HttpsCookieAgent } = require("http-cookie-agent/http"); const https = require("https"); const http = require("http"); +const { Settings } = require("../settings"); const rootCertificates = rootCertificatesFingerprints(); @@ -672,7 +673,7 @@ class Monitor extends BeanModel { } else if (this.type === "steam") { const steamApiUrl = "https://api.steampowered.com/IGameServersService/GetServerList/v1/"; - const steamAPIKey = await setting("steamAPIKey"); + const steamAPIKey = await Settings.get("steamAPIKey"); const filter = `addr\\${this.hostname}:${this.port}`; if (!steamAPIKey) { @@ -1379,11 +1380,12 @@ class Monitor extends BeanModel { return; } - let notifyDays = await setting("tlsExpiryNotifyDays"); + let notifyDays = await Settings.get("tlsExpiryNotifyDays"); if (notifyDays == null || !Array.isArray(notifyDays)) { // Reset Default - await setSetting("tlsExpiryNotifyDays", [ 7, 14, 21 ], "general"); + await Settings.set("tlsExpiryNotifyDays", [ 7, 14, 21 ], "general"); notifyDays = [ 7, 14, 21 ]; + await Settings.set("tlsExpiryNotifyDays", notifyDays, "general"); } if (Array.isArray(notifyDays)) { diff --git a/server/notification-providers/alertnow.js b/server/notification-providers/alertnow.js index 4257ca9cd1..ecc03e84bb 100644 --- a/server/notification-providers/alertnow.js +++ b/server/notification-providers/alertnow.js @@ -1,7 +1,7 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); -const { setting } = require("../util-server"); const { getMonitorRelativeURL, UP, DOWN } = require("../../src/util"); +const { Settings } = require("../settings"); class AlertNow extends NotificationProvider { name = "AlertNow"; @@ -29,7 +29,7 @@ class AlertNow extends NotificationProvider { textMsg += ` - ${msg}`; - const baseURL = await setting("primaryBaseURL"); + const baseURL = await Settings.get("primaryBaseURL"); if (baseURL && monitorJSON) { textMsg += ` >> ${baseURL + getMonitorRelativeURL(monitorJSON.id)}`; } diff --git a/server/notification-providers/flashduty.js b/server/notification-providers/flashduty.js index c340ed06f1..09ee8913aa 100644 --- a/server/notification-providers/flashduty.js +++ b/server/notification-providers/flashduty.js @@ -1,7 +1,7 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); const { UP, DOWN, getMonitorRelativeURL } = require("../../src/util"); -const { setting } = require("../util-server"); +const { Settings } = require("../settings"); const successMessage = "Sent Successfully."; class FlashDuty extends NotificationProvider { @@ -84,7 +84,7 @@ class FlashDuty extends NotificationProvider { } }; - const baseURL = await setting("primaryBaseURL"); + const baseURL = await Settings.get("primaryBaseURL"); if (baseURL && monitorInfo) { options.client = "Uptime Kuma"; options.client_url = baseURL + getMonitorRelativeURL(monitorInfo.id); diff --git a/server/notification-providers/google-chat.js b/server/notification-providers/google-chat.js index 0b72fea95f..afba8f6c7c 100644 --- a/server/notification-providers/google-chat.js +++ b/server/notification-providers/google-chat.js @@ -1,7 +1,7 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); -const { setting } = require("../util-server"); -const { getMonitorRelativeURL, UP } = require("../../src/util"); +const { getMonitorRelativeURL, DOWN, UP } = require("../../src/util"); +const { Settings } = require("../settings"); class GoogleChat extends NotificationProvider { name = "GoogleChat"; @@ -35,6 +35,7 @@ class GoogleChat extends NotificationProvider { }, ]; + // add time if available if (heartbeatJSON) { sectionWidgets.push({ @@ -45,7 +46,7 @@ class GoogleChat extends NotificationProvider { } // add button for monitor link if available - const baseURL = await setting("primaryBaseURL"); + const baseURL = await Settings.get("primaryBaseURL"); if (baseURL) { const urlPath = monitorJSON ? getMonitorRelativeURL(monitorJSON.id) : "/"; sectionWidgets.push({ diff --git a/server/notification-providers/pagerduty.js b/server/notification-providers/pagerduty.js index c60d782e76..7aa19bb4b2 100644 --- a/server/notification-providers/pagerduty.js +++ b/server/notification-providers/pagerduty.js @@ -1,7 +1,7 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); const { UP, DOWN, getMonitorRelativeURL } = require("../../src/util"); -const { setting } = require("../util-server"); +const { Settings } = require("../settings"); let successMessage = "Sent Successfully."; class PagerDuty extends NotificationProvider { @@ -95,7 +95,7 @@ class PagerDuty extends NotificationProvider { } }; - const baseURL = await setting("primaryBaseURL"); + const baseURL = await Settings.get("primaryBaseURL"); if (baseURL && monitorInfo) { options.client = "Uptime Kuma"; options.client_url = baseURL + getMonitorRelativeURL(monitorInfo.id); diff --git a/server/notification-providers/pagertree.js b/server/notification-providers/pagertree.js index c7a5338d1f..62f229ace1 100644 --- a/server/notification-providers/pagertree.js +++ b/server/notification-providers/pagertree.js @@ -1,7 +1,7 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); const { UP, DOWN, getMonitorRelativeURL } = require("../../src/util"); -const { setting } = require("../util-server"); +const { Settings } = require("../settings"); let successMessage = "Sent Successfully."; class PagerTree extends NotificationProvider { @@ -74,7 +74,7 @@ class PagerTree extends NotificationProvider { } }; - const baseURL = await setting("primaryBaseURL"); + const baseURL = await Settings.get("primaryBaseURL"); if (baseURL && monitorJSON) { options.client = "Uptime Kuma"; options.client_url = baseURL + getMonitorRelativeURL(monitorJSON.id); diff --git a/server/notification-providers/rocket-chat.js b/server/notification-providers/rocket-chat.js index 690e33a86e..174a94950b 100644 --- a/server/notification-providers/rocket-chat.js +++ b/server/notification-providers/rocket-chat.js @@ -1,8 +1,8 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); const Slack = require("./slack"); -const { setting } = require("../util-server"); const { getMonitorRelativeURL, DOWN } = require("../../src/util"); +const { Settings } = require("../settings"); class RocketChat extends NotificationProvider { name = "rocket.chat"; @@ -49,7 +49,7 @@ class RocketChat extends NotificationProvider { await Slack.deprecateURL(notification.rocketbutton); } - const baseURL = await setting("primaryBaseURL"); + const baseURL = await Settings.get("primaryBaseURL"); if (baseURL) { data.attachments[0].title_link = baseURL + getMonitorRelativeURL(monitorJSON.id); diff --git a/server/notification-providers/slack.js b/server/notification-providers/slack.js index 702256429c..b64bfe7ff9 100644 --- a/server/notification-providers/slack.js +++ b/server/notification-providers/slack.js @@ -1,26 +1,25 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); -const { setSettings, setting } = require("../util-server"); const { getMonitorRelativeURL, UP } = require("../../src/util"); +const { Settings } = require("../settings"); class Slack extends NotificationProvider { name = "slack"; /** * Deprecated property notification.slackbutton - * Set it as primary base url if this is not yet set. + * Set it as + ry base url if this is not yet set. * @deprecated * @param {string} url The primary base URL to use * @returns {Promise} */ static async deprecateURL(url) { - let currentPrimaryBaseURL = await setting("primaryBaseURL"); + let currentPrimaryBaseURL = await Settings.get("primaryBaseURL"); if (!currentPrimaryBaseURL) { console.log("Move the url to be the primary base URL"); - await setSettings("general", { - primaryBaseURL: url, - }); + await Settings.set("primaryBaseURL", url, "general"); } else { console.log("Already there, no need to move the primary base URL"); } diff --git a/server/notification-providers/splunk.js b/server/notification-providers/splunk.js index e07c51039b..ad4dc6b39b 100644 --- a/server/notification-providers/splunk.js +++ b/server/notification-providers/splunk.js @@ -1,7 +1,7 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); const { UP, DOWN, getMonitorRelativeURL } = require("../../src/util"); -const { setting } = require("../util-server"); +const { Settings } = require("../settings"); let successMessage = "Sent Successfully."; class Splunk extends NotificationProvider { @@ -95,7 +95,7 @@ class Splunk extends NotificationProvider { } }; - const baseURL = await setting("primaryBaseURL"); + const baseURL = await Settings.get("primaryBaseURL"); if (baseURL && monitorInfo) { options.client = "Uptime Kuma"; options.client_url = baseURL + getMonitorRelativeURL(monitorInfo.id); diff --git a/server/notification-providers/stackfield.js b/server/notification-providers/stackfield.js index 65a92459ab..e4e31a9ab7 100644 --- a/server/notification-providers/stackfield.js +++ b/server/notification-providers/stackfield.js @@ -1,7 +1,7 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); -const { setting } = require("../util-server"); const { getMonitorRelativeURL } = require("../../src/util"); +const { Settings } = require("../settings"); class Stackfield extends NotificationProvider { name = "stackfield"; @@ -23,7 +23,7 @@ class Stackfield extends NotificationProvider { textMsg += `\n${msg}`; - const baseURL = await setting("primaryBaseURL"); + const baseURL = await Settings.get("primaryBaseURL"); if (baseURL) { textMsg += `\n${baseURL + getMonitorRelativeURL(monitorJSON.id)}`; } diff --git a/server/proxy.js b/server/proxy.js index 3f3771ab98..3f1215b25d 100644 --- a/server/proxy.js +++ b/server/proxy.js @@ -2,7 +2,7 @@ const { R } = require("redbean-node"); const HttpProxyAgent = require("http-proxy-agent"); const HttpsProxyAgent = require("https-proxy-agent"); const SocksProxyAgent = require("socks-proxy-agent"); -const { debug } = require("../src/util"); +const { log } = require("../src/util"); const { UptimeKumaServer } = require("./uptime-kuma-server"); const { CookieJar } = require("tough-cookie"); const { createCookieAgent } = require("http-cookie-agent/http"); @@ -110,9 +110,9 @@ class Proxy { proxyOptions.auth = `${proxy.username}:${proxy.password}`; } - debug(`Proxy Options: ${JSON.stringify(proxyOptions)}`); - debug(`HTTP Agent Options: ${JSON.stringify(httpAgentOptions)}`); - debug(`HTTPS Agent Options: ${JSON.stringify(httpsAgentOptions)}`); + log.debug("update-proxy", `Proxy Options: ${JSON.stringify(proxyOptions)}`); + log.debug("update-proxy", `HTTP Agent Options: ${JSON.stringify(httpAgentOptions)}`); + log.debug("update-proxy", `HTTPS Agent Options: ${JSON.stringify(httpsAgentOptions)}`); switch (proxy.protocol) { case "http": diff --git a/server/routers/api-router.js b/server/routers/api-router.js index ed6db2cd1c..9e7c9348c9 100644 --- a/server/routers/api-router.js +++ b/server/routers/api-router.js @@ -1,6 +1,5 @@ let express = require("express"); const { - setting, allowDevAllOrigin, allowAllOrigin, percentageToColor, @@ -18,6 +17,7 @@ const { makeBadge } = require("badge-maker"); const { Prometheus } = require("../prometheus"); const Database = require("../database"); const { UptimeCalculator } = require("../uptime-calculator"); +const { Settings } = require("../settings"); let router = express.Router(); @@ -30,7 +30,7 @@ router.get("/api/entry-page", async (request, response) => { let result = { }; let hostname = request.hostname; - if ((await setting("trustProxy")) && request.headers["x-forwarded-host"]) { + if ((await Settings.get("trustProxy")) && request.headers["x-forwarded-host"]) { hostname = request.headers["x-forwarded-host"]; } diff --git a/server/server.js b/server/server.js index 1f27b3c433..48a98eaf5d 100644 --- a/server/server.js +++ b/server/server.js @@ -90,8 +90,7 @@ const Monitor = require("./model/monitor"); const User = require("./model/user"); log.debug("server", "Importing Settings"); -const { getSettings, setSettings, setting, initJWTSecret, checkLogin, doubleCheckPassword, shake256, SHAKE256_LENGTH, allowDevAllOrigin, -} = require("./util-server"); +const { initJWTSecret, checkLogin, doubleCheckPassword, shake256, SHAKE256_LENGTH, allowDevAllOrigin } = require("./util-server"); log.debug("server", "Importing Notification"); const { Notification } = require("./notification"); @@ -201,7 +200,7 @@ let needSetup = false; // Entry Page app.get("/", async (request, response) => { let hostname = request.hostname; - if (await setting("trustProxy")) { + if (await Settings.get("trustProxy")) { const proxy = request.headers["x-forwarded-host"]; if (proxy) { hostname = proxy; @@ -281,7 +280,7 @@ let needSetup = false; // Robots.txt app.get("/robots.txt", async (_request, response) => { let txt = "User-agent: *\nDisallow:"; - if (!await setting("searchEngineIndex")) { + if (!await Settings.get("searchEngineIndex")) { txt += " /"; } response.setHeader("Content-Type", "text/plain"); @@ -1325,7 +1324,7 @@ let needSetup = false; socket.on("getSettings", async (callback) => { try { checkLogin(socket); - const data = await getSettings("general"); + const data = await Settings.getSettings("general"); if (!data.serverTimezone) { data.serverTimezone = await server.getTimezone(); @@ -1353,7 +1352,7 @@ let needSetup = false; // Disabled Auth + Want to Enable Auth => No Check // Enabled Auth + Want to Disable Auth => Check!! // Enabled Auth + Want to Enable Auth => No Check - const currentDisabledAuth = await setting("disableAuth"); + const currentDisabledAuth = await Settings.get("disableAuth"); if (!currentDisabledAuth && data.disableAuth) { await doubleCheckPassword(socket, currentPassword); } @@ -1367,7 +1366,7 @@ let needSetup = false; const previousChromeExecutable = await Settings.get("chromeExecutable"); const previousNSCDStatus = await Settings.get("nscd"); - await setSettings("general", data); + await Settings.setSettings("general", data); server.entryPage = data.entryPage; // Also need to apply timezone globally @@ -1576,7 +1575,7 @@ let needSetup = false; // *************************** log.debug("auth", "check auto login"); - if (await setting("disableAuth")) { + if (await Settings.get("disableAuth")) { log.info("auth", "Disabled Auth: auto login to admin"); await afterLogin(socket, await R.findOne("user")); socket.emit("autoLogin"); diff --git a/server/socket-handlers/cloudflared-socket-handler.js b/server/socket-handlers/cloudflared-socket-handler.js index 809191fe85..0a8d06066a 100644 --- a/server/socket-handlers/cloudflared-socket-handler.js +++ b/server/socket-handlers/cloudflared-socket-handler.js @@ -1,7 +1,8 @@ -const { checkLogin, setSetting, setting, doubleCheckPassword } = require("../util-server"); +const { checkLogin, doubleCheckPassword } = require("../util-server"); const { CloudflaredTunnel } = require("node-cloudflared-tunnel"); const { UptimeKumaServer } = require("../uptime-kuma-server"); const { log } = require("../../src/util"); +const { Settings } = require("../settings"); const io = UptimeKumaServer.getInstance().io; const prefix = "cloudflared_"; @@ -40,7 +41,7 @@ module.exports.cloudflaredSocketHandler = (socket) => { socket.join("cloudflared"); io.to(socket.userID).emit(prefix + "installed", cloudflared.checkInstalled()); io.to(socket.userID).emit(prefix + "running", cloudflared.running); - io.to(socket.userID).emit(prefix + "token", await setting("cloudflaredTunnelToken")); + io.to(socket.userID).emit(prefix + "token", await Settings.get("cloudflaredTunnelToken")); } catch (error) { } }); @@ -55,7 +56,7 @@ module.exports.cloudflaredSocketHandler = (socket) => { try { checkLogin(socket); if (token && typeof token === "string") { - await setSetting("cloudflaredTunnelToken", token); + await Settings.set("cloudflaredTunnelToken", token); cloudflared.token = token; } else { cloudflared.token = null; @@ -67,7 +68,7 @@ module.exports.cloudflaredSocketHandler = (socket) => { socket.on(prefix + "stop", async (currentPassword, callback) => { try { checkLogin(socket); - const disabledAuth = await setting("disableAuth"); + const disabledAuth = await Settings.get("disableAuth"); if (!disabledAuth) { await doubleCheckPassword(socket, currentPassword); } @@ -83,7 +84,7 @@ module.exports.cloudflaredSocketHandler = (socket) => { socket.on(prefix + "removeToken", async () => { try { checkLogin(socket); - await setSetting("cloudflaredTunnelToken", ""); + await Settings.set("cloudflaredTunnelToken", ""); } catch (error) { } }); @@ -96,10 +97,10 @@ module.exports.cloudflaredSocketHandler = (socket) => { */ module.exports.autoStart = async (token) => { if (!token) { - token = await setting("cloudflaredTunnelToken"); + token = await Settings.get("cloudflaredTunnelToken"); } else { // Override the current token via args or env var - await setSetting("cloudflaredTunnelToken", token); + await Settings.set("cloudflaredTunnelToken", token); console.log("Use cloudflared token from args or env var"); } diff --git a/server/socket-handlers/status-page-socket-handler.js b/server/socket-handlers/status-page-socket-handler.js index 0804da15dd..c11a4d2b31 100644 --- a/server/socket-handlers/status-page-socket-handler.js +++ b/server/socket-handlers/status-page-socket-handler.js @@ -1,5 +1,5 @@ const { R } = require("redbean-node"); -const { checkLogin, setSetting } = require("../util-server"); +const { checkLogin } = require("../util-server"); const dayjs = require("dayjs"); const { log } = require("../../src/util"); const ImageDataURI = require("../image-data-uri"); @@ -7,6 +7,7 @@ const Database = require("../database"); const apicache = require("../modules/apicache"); const StatusPage = require("../model/status_page"); const { UptimeKumaServer } = require("../uptime-kuma-server"); +const { Settings } = require("../settings"); /** * Socket handlers for status page @@ -233,7 +234,7 @@ module.exports.statusPageSocketHandler = (socket) => { // Also change entry page to new slug if it is the default one, and slug is changed. if (server.entryPage === "statusPage-" + slug && statusPage.slug !== slug) { server.entryPage = "statusPage-" + statusPage.slug; - await setSetting("entryPage", server.entryPage, "general"); + await Settings.set("entryPage", server.entryPage, "general"); } apicache.clear(); @@ -313,7 +314,7 @@ module.exports.statusPageSocketHandler = (socket) => { // Reset entry page if it is the default one. if (server.entryPage === "statusPage-" + slug) { server.entryPage = "dashboard"; - await setSetting("entryPage", server.entryPage, "general"); + await Settings.set("entryPage", server.entryPage, "general"); } // No need to delete records from `status_page_cname`, because it has cascade foreign key. diff --git a/server/util-server.js b/server/util-server.js index 5ebc62ac56..37fee63222 100644 --- a/server/util-server.js +++ b/server/util-server.js @@ -521,46 +521,6 @@ exports.redisPingAsync = function (dsn, rejectUnauthorized) { }); }; -/** - * Retrieve value of setting based on key - * @param {string} key Key of setting to retrieve - * @returns {Promise} Value - * @deprecated Use await Settings.get(key) - */ -exports.setting = async function (key) { - return await Settings.get(key); -}; - -/** - * Sets the specified setting to specified value - * @param {string} key Key of setting to set - * @param {any} value Value to set to - * @param {?string} type Type of setting - * @returns {Promise} - */ -exports.setSetting = async function (key, value, type = null) { - await Settings.set(key, value, type); -}; - -/** - * Get settings based on type - * @param {string} type The type of setting - * @returns {Promise} Settings of requested type - */ -exports.getSettings = async function (type) { - return await Settings.getSettings(type); -}; - -/** - * Set settings based on type - * @param {string} type Type of settings to set - * @param {object} data Values of settings - * @returns {Promise} - */ -exports.setSettings = async function (type, data) { - await Settings.setSettings(type, data); -}; - // ssl-checker by @dyaa //https://github.com/dyaa/ssl-checker/blob/master/src/index.ts diff --git a/src/util.ts b/src/util.ts index efc8f3a898..6acebd8102 100644 --- a/src/util.ts +++ b/src/util.ts @@ -156,15 +156,6 @@ export function ucfirst(str: string) { return firstLetter.toUpperCase() + str.substr(1); } -/** - * @deprecated Use log.debug (https://github.com/louislam/uptime-kuma/pull/910) - * @param msg Message to write - * @returns {void} - */ -export function debug(msg: unknown) { - log.log("", msg, "debug"); -} - class Logger { /** From 448c8acda8faa874c1d9edc4a0d30604e7581928 Mon Sep 17 00:00:00 2001 From: Cassandra Beelen Date: Thu, 19 Sep 2024 09:39:57 +0200 Subject: [PATCH 2/7] chore: unified our logging infrastructure to only use `log.XYZ` Co-authored-by: Frank Elsinga Closes: #4392 Squashed commit of the following: commit 75c4c35da2af5bcf04c6c24aa155c68136baa1c1 Merge: 14e3c3c7 dd758903 Author: Frank Elsinga Date: Fri Sep 13 22:46:21 2024 +0800 Merge branch 'master' into unified-logging-infrastructure commit 14e3c3c7c1a438ea993139e4dea95ddd80f9d47d Merge: d622dfbb c919d2c9 Author: Frank Elsinga Date: Mon Jun 3 16:00:56 2024 +0200 Merge branch 'master' into unified-logging-infrastructure commit d622dfbb5773a41d9cd1113006a09dc492860455 Author: Frank Elsinga Date: Thu Jan 18 22:31:10 2024 +0100 unified our logging infrastructure --- server/database.js | 6 +- server/modules/apicache/apicache.js | 61 +++++++------------ .../real-browser-monitor-type.js | 5 +- server/notification-providers/slack.js | 5 +- server/server.js | 2 +- .../socket-handlers/api-key-socket-handler.js | 2 +- .../cloudflared-socket-handler.js | 4 +- .../maintenance-socket-handler.js | 8 +-- .../status-page-socket-handler.js | 2 +- src/util.ts | 26 ++++---- 10 files changed, 53 insertions(+), 68 deletions(-) diff --git a/server/database.js b/server/database.js index b23f56db38..46e6ecaf3d 100644 --- a/server/database.js +++ b/server/database.js @@ -515,12 +515,12 @@ class Database { let title = await Settings.get("title"); if (title) { - console.log("Migrating Status Page"); + log.info("database", "Migrating Status Page"); let statusPageCheck = await R.findOne("status_page", " slug = 'default' "); if (statusPageCheck !== null) { - console.log("Migrating Status Page - Skip, default slug record is already existing"); + log.info("database", "Migrating Status Page - Skip, default slug record is already existing"); return; } @@ -566,7 +566,7 @@ class Database { await Settings.set("entryPage", "statusPage-default", "general"); } - console.log("Migrating Status Page - Done"); + log.info("database", "Migrating Status Page - Done"); } } diff --git a/server/modules/apicache/apicache.js b/server/modules/apicache/apicache.js index 41930b24d0..89f2f1e165 100644 --- a/server/modules/apicache/apicache.js +++ b/server/modules/apicache/apicache.js @@ -1,5 +1,6 @@ let url = require("url"); let MemoryCache = require("./memory-cache"); +const { log } = require("../../../src/util"); let t = { ms: 1, @@ -90,24 +91,6 @@ function ApiCache() { instances.push(this); this.id = instances.length; - /** - * Logs a message to the console if the `DEBUG` environment variable is set. - * @param {string} a The first argument to log. - * @param {string} b The second argument to log. - * @param {string} c The third argument to log. - * @param {string} d The fourth argument to log, and so on... (optional) - * - * Generated by Trelent - */ - function debug(a, b, c, d) { - let arr = ["\x1b[36m[apicache]\x1b[0m", a, b, c, d].filter(function (arg) { - return arg !== undefined; - }); - let debugEnv = process.env.DEBUG && process.env.DEBUG.split(",").indexOf("apicache") !== -1; - - return (globalOptions.debug || debugEnv) && console.log.apply(null, arr); - } - /** * Returns true if the given request and response should be logged. * @param {Object} request The HTTP request object. @@ -146,7 +129,7 @@ function ApiCache() { let groupName = req.apicacheGroup; if (groupName) { - debug("group detected \"" + groupName + "\""); + log.debug("apicache", `group detected "${groupName}"`); let group = (index.groups[groupName] = index.groups[groupName] || []); group.unshift(key); } @@ -212,7 +195,7 @@ function ApiCache() { redis.hset(key, "duration", duration); redis.expire(key, duration / 1000, expireCallback || function () {}); } catch (err) { - debug("[apicache] error in redis.hset()"); + log.debug("apicache", `error in redis.hset(): ${err}`); } } else { memCache.add(key, value, duration, expireCallback); @@ -320,10 +303,10 @@ function ApiCache() { // display log entry let elapsed = new Date() - req.apicacheTimer; - debug("adding cache entry for \"" + key + "\" @ " + strDuration, logDuration(elapsed)); - debug("_apicache.headers: ", res._apicache.headers); - debug("res.getHeaders(): ", getSafeHeaders(res)); - debug("cacheObject: ", cacheObject); + log.debug("apicache", `adding cache entry for "${key}" @ ${strDuration} ${logDuration(elapsed)}`); + log.debug("apicache", `_apicache.headers: ${res._apicache.headers}`); + log.debug("apicache", `res.getHeaders(): ${getSafeHeaders(res)}`); + log.debug("apicache", `cacheObject: ${cacheObject}`); } } @@ -402,10 +385,10 @@ function ApiCache() { let redis = globalOptions.redisClient; if (group) { - debug("clearing group \"" + target + "\""); + log.debug("apicache", `clearing group "${target}"`); group.forEach(function (key) { - debug("clearing cached entry for \"" + key + "\""); + log.debug("apicache", `clearing cached entry for "${key}"`); clearTimeout(timers[key]); delete timers[key]; if (!globalOptions.redisClient) { @@ -414,7 +397,7 @@ function ApiCache() { try { redis.del(key); } catch (err) { - console.log("[apicache] error in redis.del(\"" + key + "\")"); + log.info("apicache", "error in redis.del(\"" + key + "\")"); } } index.all = index.all.filter(doesntMatch(key)); @@ -422,7 +405,7 @@ function ApiCache() { delete index.groups[target]; } else if (target) { - debug("clearing " + (isAutomatic ? "expired" : "cached") + " entry for \"" + target + "\""); + log.debug("apicache", `clearing ${isAutomatic ? "expired" : "cached"} entry for "${target}"`); clearTimeout(timers[target]); delete timers[target]; // clear actual cached entry @@ -432,7 +415,7 @@ function ApiCache() { try { redis.del(target); } catch (err) { - console.log("[apicache] error in redis.del(\"" + target + "\")"); + log.error("apicache", "error in redis.del(\"" + target + "\")"); } } @@ -449,7 +432,7 @@ function ApiCache() { } }); } else { - debug("clearing entire index"); + log.debug("apicache", "clearing entire index"); if (!redis) { memCache.clear(); @@ -461,7 +444,7 @@ function ApiCache() { try { redis.del(key); } catch (err) { - console.log("[apicache] error in redis.del(\"" + key + "\")"); + log.error("apicache", `error in redis.del("${key}"): ${err}`); } }); } @@ -528,7 +511,7 @@ function ApiCache() { /** * Get index of a group - * @param {string} group + * @param {string} group * @returns {number} */ this.getIndex = function (group) { @@ -543,9 +526,9 @@ function ApiCache() { * Express middleware * @param {(string|number)} strDuration Duration to cache responses * for. - * @param {function(Object, Object):boolean} middlewareToggle + * @param {function(Object, Object):boolean} middlewareToggle * @param {Object} localOptions Options for APICache - * @returns + * @returns */ this.middleware = function cache(strDuration, middlewareToggle, localOptions) { let duration = instance.getDuration(strDuration); @@ -752,7 +735,7 @@ function ApiCache() { */ let cache = function (req, res, next) { function bypass() { - debug("bypass detected, skipping cache."); + log.debug("apicache", "bypass detected, skipping cache."); return next(); } @@ -805,7 +788,7 @@ function ApiCache() { // send if cache hit from memory-cache if (cached) { let elapsed = new Date() - req.apicacheTimer; - debug("sending cached (memory-cache) version of", key, logDuration(elapsed)); + log.debug("apicache", `sending cached (memory-cache) version of ${key} ${logDuration(elapsed)}`); perf.hit(key); return sendCachedResponse(req, res, cached, middlewareToggle, next, duration); @@ -817,7 +800,7 @@ function ApiCache() { redis.hgetall(key, function (err, obj) { if (!err && obj && obj.response) { let elapsed = new Date() - req.apicacheTimer; - debug("sending cached (redis) version of", key, logDuration(elapsed)); + log.debug("apicache", "sending cached (redis) version of "+ key+" "+ logDuration(elapsed)); perf.hit(key); return sendCachedResponse( @@ -859,7 +842,7 @@ function ApiCache() { /** * Process options - * @param {Object} options + * @param {Object} options * @returns {Object} */ this.options = function (options) { @@ -873,7 +856,7 @@ function ApiCache() { } if (globalOptions.trackPerformance) { - debug("WARNING: using trackPerformance flag can cause high memory usage!"); + log.debug("apicache", "WARNING: using trackPerformance flag can cause high memory usage!"); } return this; diff --git a/server/monitor-types/real-browser-monitor-type.js b/server/monitor-types/real-browser-monitor-type.js index f1219af18d..ce3abcb2d1 100644 --- a/server/monitor-types/real-browser-monitor-type.js +++ b/server/monitor-types/real-browser-monitor-type.js @@ -63,7 +63,7 @@ if (process.platform === "win32") { * @returns {Promise} The executable is allowed? */ async function isAllowedChromeExecutable(executablePath) { - console.log(config.args); + log.info("Chromium", config.args); if (config.args["allow-all-chrome-exec"] || process.env.UPTIME_KUMA_ALLOW_ALL_CHROME_EXEC === "1") { return true; } @@ -102,7 +102,8 @@ async function getBrowser() { */ async function getRemoteBrowser(remoteBrowserID, userId) { let remoteBrowser = await RemoteBrowser.get(remoteBrowserID, userId); - log.debug("MONITOR", `Using remote browser: ${remoteBrowser.name} (${remoteBrowser.id})`); + log.debug("Chromium", `Using remote browser: ${remoteBrowser.name} (${remoteBrowser.id})`); + browser = chromium.connect(remoteBrowser.url); browser = await chromium.connect(remoteBrowser.url); return browser; } diff --git a/server/notification-providers/slack.js b/server/notification-providers/slack.js index b64bfe7ff9..b16878b675 100644 --- a/server/notification-providers/slack.js +++ b/server/notification-providers/slack.js @@ -2,6 +2,7 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); const { getMonitorRelativeURL, UP } = require("../../src/util"); const { Settings } = require("../settings"); +const { log } = require("../../src/util"); class Slack extends NotificationProvider { name = "slack"; @@ -18,10 +19,10 @@ class Slack extends NotificationProvider { let currentPrimaryBaseURL = await Settings.get("primaryBaseURL"); if (!currentPrimaryBaseURL) { - console.log("Move the url to be the primary base URL"); + log.error("notification", "Move the url to be the primary base URL"); await Settings.set("primaryBaseURL", url, "general"); } else { - console.log("Already there, no need to move the primary base URL"); + log.debug("notification", "Already there, no need to move the primary base URL"); } } diff --git a/server/server.js b/server/server.js index 48a98eaf5d..d040d6e87c 100644 --- a/server/server.js +++ b/server/server.js @@ -1462,7 +1462,7 @@ let needSetup = false; }); } catch (e) { - console.error(e); + log.error("server", e); callback({ ok: false, diff --git a/server/socket-handlers/api-key-socket-handler.js b/server/socket-handlers/api-key-socket-handler.js index f76b909918..1394f8044a 100644 --- a/server/socket-handlers/api-key-socket-handler.js +++ b/server/socket-handlers/api-key-socket-handler.js @@ -60,7 +60,7 @@ module.exports.apiKeySocketHandler = (socket) => { ok: true, }); } catch (e) { - console.error(e); + log.error("apikeys", e); callback({ ok: false, msg: e.message, diff --git a/server/socket-handlers/cloudflared-socket-handler.js b/server/socket-handlers/cloudflared-socket-handler.js index 0a8d06066a..1cd0c53d00 100644 --- a/server/socket-handlers/cloudflared-socket-handler.js +++ b/server/socket-handlers/cloudflared-socket-handler.js @@ -101,11 +101,11 @@ module.exports.autoStart = async (token) => { } else { // Override the current token via args or env var await Settings.set("cloudflaredTunnelToken", token); - console.log("Use cloudflared token from args or env var"); + log.info("cloudflare", "Use cloudflared token from args or env var"); } if (token) { - console.log("Start cloudflared"); + log.info("cloudflare", "Start cloudflared"); cloudflared.token = token; cloudflared.start(); } diff --git a/server/socket-handlers/maintenance-socket-handler.js b/server/socket-handlers/maintenance-socket-handler.js index 7de13fe57a..201014c226 100644 --- a/server/socket-handlers/maintenance-socket-handler.js +++ b/server/socket-handlers/maintenance-socket-handler.js @@ -67,7 +67,7 @@ module.exports.maintenanceSocketHandler = (socket) => { }); } catch (e) { - console.error(e); + log.error("maintenance", e); callback({ ok: false, msg: e.message, @@ -177,7 +177,7 @@ module.exports.maintenanceSocketHandler = (socket) => { ok: true, }); } catch (e) { - console.error(e); + log.error("maintenance", e); callback({ ok: false, msg: e.message, @@ -201,7 +201,7 @@ module.exports.maintenanceSocketHandler = (socket) => { }); } catch (e) { - console.error(e); + log.error("maintenance", e); callback({ ok: false, msg: e.message, @@ -225,7 +225,7 @@ module.exports.maintenanceSocketHandler = (socket) => { }); } catch (e) { - console.error(e); + log.error("maintenance", e); callback({ ok: false, msg: e.message, diff --git a/server/socket-handlers/status-page-socket-handler.js b/server/socket-handlers/status-page-socket-handler.js index c11a4d2b31..cf0accc23a 100644 --- a/server/socket-handlers/status-page-socket-handler.js +++ b/server/socket-handlers/status-page-socket-handler.js @@ -292,7 +292,7 @@ module.exports.statusPageSocketHandler = (socket) => { }); } catch (error) { - console.error(error); + log.error("socket", error); callback({ ok: false, msg: error.message, diff --git a/src/util.ts b/src/util.ts index 6acebd8102..804df1156e 100644 --- a/src/util.ts +++ b/src/util.ts @@ -197,12 +197,13 @@ class Logger { /** * Write a message to the log + * @private * @param module The module the log comes from * @param msg Message to write - * @param level Log level. One of INFO, WARN, ERROR, DEBUG or can be customized. + * @param level {"INFO"|"WARN"|"ERROR"|"DEBUG"} Log level * @returns {void} */ - log(module: string, msg: any, level: string) { + log(module: string, msg: unknown, level: "INFO"|"WARN"|"ERROR"|"DEBUG"): void { if (level === "DEBUG" && !isDev) { return; } @@ -212,7 +213,6 @@ class Logger { } module = module.toUpperCase(); - level = level.toUpperCase(); let now; if (dayjs.tz) { @@ -299,8 +299,8 @@ class Logger { * @param msg Message to write * @returns {void} */ - info(module: string, msg: unknown) { - this.log(module, msg, "info"); + info(module: string, msg: string): void { + this.log(module, msg, "INFO"); } /** @@ -309,8 +309,8 @@ class Logger { * @param msg Message to write * @returns {void} */ - warn(module: string, msg: unknown) { - this.log(module, msg, "warn"); + warn(module: string, msg: string): void { + this.log(module, msg, "WARN"); } /** @@ -319,8 +319,8 @@ class Logger { * @param msg Message to write * @returns {void} */ - error(module: string, msg: unknown) { - this.log(module, msg, "error"); + error(module: string, msg: string): void { + this.log(module, msg, "ERROR"); } /** @@ -329,8 +329,8 @@ class Logger { * @param msg Message to write * @returns {void} */ - debug(module: string, msg: unknown) { - this.log(module, msg, "debug"); + debug(module: string, msg: string): void { + this.log(module, msg, "DEBUG"); } /** @@ -347,7 +347,7 @@ class Logger { finalMessage = `${msg}: ${exception}`; } - this.log(module, finalMessage, "error"); + this.log(module, finalMessage, "ERROR"); } } @@ -391,7 +391,7 @@ export class TimeLogger { * @param name Name of monitor * @returns {void} */ - print(name: string) { + print(name: string): void { if (isDev && process.env.TIMELOGGER === "1") { console.log(name + ": " + (dayjs().valueOf() - this.startTime) + "ms"); } From 3e922be39cba2eba05ca814183c60def93e6ae2f Mon Sep 17 00:00:00 2001 From: Cassandra Beelen Date: Thu, 19 Sep 2024 09:56:47 +0200 Subject: [PATCH 3/7] feat(utils): implement structured (JSON) logging Includes a slight refactor in the console logging section, to achieve an unformatted output and reduce complexity. Resolves: #5107 --- src/util.ts | 114 +++++++++++++++++++++++++++------------------------- 1 file changed, 59 insertions(+), 55 deletions(-) diff --git a/src/util.ts b/src/util.ts index 804df1156e..accfe5d00b 100644 --- a/src/util.ts +++ b/src/util.ts @@ -212,8 +212,6 @@ class Logger { return; } - module = module.toUpperCase(); - let now; if (dayjs.tz) { now = dayjs.tz(new Date()).format(); @@ -221,75 +219,81 @@ class Logger { now = dayjs().format(); } + const structuredLogging = process.env.UPTIME_KUMA_LOG_FORMAT === "json"; + const levelColor = consoleLevelColors[level]; const moduleColor = consoleModuleColors[intHash(module, consoleModuleColors.length)]; - let timePart: string; - let modulePart: string; - let levelPart: string; - let msgPart: string; + let timePart: string = now; + let modulePart: string = module; + let levelPart: string = level; + let msgPart: unknown = msg; + + if (!structuredLogging) { + // Console rendering: + module = module.toUpperCase(); + + if (isNode) { + // Add console colors + switch (level) { + case "DEBUG": + timePart = CONSOLE_STYLE_FgGray + now + CONSOLE_STYLE_Reset; + break; + default: + timePart = CONSOLE_STYLE_FgCyan + now + CONSOLE_STYLE_Reset; + break; + } - if (isNode) { - // Add console colors - switch (level) { - case "DEBUG": - timePart = CONSOLE_STYLE_FgGray + now + CONSOLE_STYLE_Reset; - break; - default: - timePart = CONSOLE_STYLE_FgCyan + now + CONSOLE_STYLE_Reset; - break; + modulePart = "[" + moduleColor + module + CONSOLE_STYLE_Reset + "]"; + + levelPart = levelColor + `${level}:` + CONSOLE_STYLE_Reset; + + switch (level) { + case "ERROR": + if (typeof msg === "string") { + msgPart = CONSOLE_STYLE_FgRed + msg + CONSOLE_STYLE_Reset; + } + break; + case "DEBUG": + if (typeof msg === "string") { + msgPart = CONSOLE_STYLE_FgGray + msg + CONSOLE_STYLE_Reset; + } + break; + } + } else { + // No console colors + timePart = now; + modulePart = `[${module}]`; + levelPart = `${level}:`; } - modulePart = "[" + moduleColor + module + CONSOLE_STYLE_Reset + "]"; - - levelPart = levelColor + `${level}:` + CONSOLE_STYLE_Reset; - + // Write to console switch (level) { case "ERROR": - if (typeof msg === "string") { - msgPart = CONSOLE_STYLE_FgRed + msg + CONSOLE_STYLE_Reset; - } else { - msgPart = msg; - } + console.error(timePart, modulePart, levelPart, msgPart); + break; + case "WARN": + console.warn(timePart, modulePart, levelPart, msgPart); + break; + case "INFO": + console.info(timePart, modulePart, levelPart, msgPart); break; case "DEBUG": - if (typeof msg === "string") { - msgPart = CONSOLE_STYLE_FgGray + msg + CONSOLE_STYLE_Reset; - } else { - msgPart = msg; + if (isDev) { + console.debug(timePart, modulePart, levelPart, msgPart); } break; default: - msgPart = msg; + console.log(timePart, modulePart, levelPart, msgPart); break; } } else { - // No console colors - timePart = now; - modulePart = `[${module}]`; - levelPart = `${level}:`; - msgPart = msg; - } - - // Write to console - switch (level) { - case "ERROR": - console.error(timePart, modulePart, levelPart, msgPart); - break; - case "WARN": - console.warn(timePart, modulePart, levelPart, msgPart); - break; - case "INFO": - console.info(timePart, modulePart, levelPart, msgPart); - break; - case "DEBUG": - if (isDev) { - console.debug(timePart, modulePart, levelPart, msgPart); - } - break; - default: - console.log(timePart, modulePart, levelPart, msgPart); - break; + console.log(JSON.stringify({ + time: timePart, + module: modulePart, + level: levelPart, + msg: typeof msg === "string" ? msg : JSON.stringify(msg), + })) } } From 929dde0adee09b60dcbc4e18d4f715d03497fd97 Mon Sep 17 00:00:00 2001 From: Cassandra Beelen Date: Thu, 19 Sep 2024 10:17:43 +0200 Subject: [PATCH 4/7] build: recompile utils.js --- src/util.js | 143 +++++++++++++++++++++++++++++----------------------- 1 file changed, 79 insertions(+), 64 deletions(-) diff --git a/src/util.js b/src/util.js index c88d04968e..c073bb971a 100644 --- a/src/util.js +++ b/src/util.js @@ -8,17 +8,34 @@ // Backend uses the compiled file util.js // Frontend uses util.ts */ +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; var _a; Object.defineProperty(exports, "__esModule", { value: true }); exports.sleep = exports.flipStatus = exports.badgeConstants = exports.CONSOLE_STYLE_BgGray = exports.CONSOLE_STYLE_BgWhite = exports.CONSOLE_STYLE_BgCyan = exports.CONSOLE_STYLE_BgMagenta = exports.CONSOLE_STYLE_BgBlue = exports.CONSOLE_STYLE_BgYellow = exports.CONSOLE_STYLE_BgGreen = exports.CONSOLE_STYLE_BgRed = exports.CONSOLE_STYLE_BgBlack = exports.CONSOLE_STYLE_FgPink = exports.CONSOLE_STYLE_FgBrown = exports.CONSOLE_STYLE_FgViolet = exports.CONSOLE_STYLE_FgLightBlue = exports.CONSOLE_STYLE_FgLightGreen = exports.CONSOLE_STYLE_FgOrange = exports.CONSOLE_STYLE_FgGray = exports.CONSOLE_STYLE_FgWhite = exports.CONSOLE_STYLE_FgCyan = exports.CONSOLE_STYLE_FgMagenta = exports.CONSOLE_STYLE_FgBlue = exports.CONSOLE_STYLE_FgYellow = exports.CONSOLE_STYLE_FgGreen = exports.CONSOLE_STYLE_FgRed = exports.CONSOLE_STYLE_FgBlack = exports.CONSOLE_STYLE_Hidden = exports.CONSOLE_STYLE_Reverse = exports.CONSOLE_STYLE_Blink = exports.CONSOLE_STYLE_Underscore = exports.CONSOLE_STYLE_Dim = exports.CONSOLE_STYLE_Bright = exports.CONSOLE_STYLE_Reset = exports.MIN_INTERVAL_SECOND = exports.MAX_INTERVAL_SECOND = exports.SQL_DATETIME_FORMAT_WITHOUT_SECOND = exports.SQL_DATETIME_FORMAT = exports.SQL_DATE_FORMAT = exports.STATUS_PAGE_MAINTENANCE = exports.STATUS_PAGE_PARTIAL_DOWN = exports.STATUS_PAGE_ALL_UP = exports.STATUS_PAGE_ALL_DOWN = exports.MAINTENANCE = exports.PENDING = exports.UP = exports.DOWN = exports.appName = exports.isNode = exports.isDev = void 0; -exports.evaluateJsonQuery = exports.intHash = exports.localToUTC = exports.utcToLocal = exports.utcToISODateTime = exports.isoToUTCDateTime = exports.parseTimeFromTimeObject = exports.parseTimeObject = exports.getMaintenanceRelativeURL = exports.getMonitorRelativeURL = exports.genSecret = exports.getCryptoRandomInt = exports.getRandomInt = exports.getRandomArbitrary = exports.TimeLogger = exports.polyfill = exports.log = exports.debug = exports.ucfirst = void 0; -exports.intHash = exports.localToUTC = exports.utcToLocal = exports.utcToISODateTime = exports.isoToUTCDateTime = exports.parseTimeFromTimeObject = exports.parseTimeObject = exports.getMaintenanceRelativeURL = exports.getMonitorRelativeURL = exports.genSecret = exports.getCryptoRandomInt = exports.getRandomInt = exports.getRandomArbitrary = exports.TimeLogger = exports.polyfill = exports.log = exports.debug = exports.ucfirst = void 0; +exports.evaluateJsonQuery = exports.intHash = exports.localToUTC = exports.utcToLocal = exports.utcToISODateTime = exports.isoToUTCDateTime = exports.parseTimeFromTimeObject = exports.parseTimeObject = exports.getMaintenanceRelativeURL = exports.getMonitorRelativeURL = exports.genSecret = exports.getCryptoRandomInt = exports.getRandomInt = exports.getRandomArbitrary = exports.TimeLogger = exports.polyfill = exports.log = exports.ucfirst = void 0; const dayjs_1 = __importDefault(require("dayjs")); -const dayjs = require("dayjs"); -const jsonata = require("jsonata"); +const jsonata = __importStar(require("jsonata")); exports.isDev = process.env.NODE_ENV === "development"; exports.isNode = typeof process !== "undefined" && ((_a = process === null || process === void 0 ? void 0 : process.versions) === null || _a === void 0 ? void 0 : _a.node); exports.appName = "Uptime Kuma"; @@ -124,10 +141,6 @@ function ucfirst(str) { return firstLetter.toUpperCase() + str.substr(1); } exports.ucfirst = ucfirst; -function debug(msg) { - exports.log.log("", msg, "debug"); -} -exports.debug = debug; class Logger { constructor() { this.hideLog = { @@ -155,8 +168,6 @@ class Logger { if (this.hideLog[level] && this.hideLog[level].includes(module.toLowerCase())) { return; } - module = module.toUpperCase(); - level = level.toUpperCase(); let now; if (dayjs_1.default.tz) { now = dayjs_1.default.tz(new Date()).format(); @@ -164,89 +175,93 @@ class Logger { else { now = (0, dayjs_1.default)().format(); } + const structuredLogging = process.env.UPTIME_KUMA_LOG_FORMAT === "json"; const levelColor = consoleLevelColors[level]; const moduleColor = consoleModuleColors[intHash(module, consoleModuleColors.length)]; - let timePart; - let modulePart; - let levelPart; - let msgPart; - if (exports.isNode) { - switch (level) { - case "DEBUG": - timePart = exports.CONSOLE_STYLE_FgGray + now + exports.CONSOLE_STYLE_Reset; - break; - default: - timePart = exports.CONSOLE_STYLE_FgCyan + now + exports.CONSOLE_STYLE_Reset; - break; + let timePart = now; + let modulePart = module; + let levelPart = level; + let msgPart = msg; + if (!structuredLogging) { + module = module.toUpperCase(); + if (exports.isNode) { + switch (level) { + case "DEBUG": + timePart = exports.CONSOLE_STYLE_FgGray + now + exports.CONSOLE_STYLE_Reset; + break; + default: + timePart = exports.CONSOLE_STYLE_FgCyan + now + exports.CONSOLE_STYLE_Reset; + break; + } + modulePart = "[" + moduleColor + module + exports.CONSOLE_STYLE_Reset + "]"; + levelPart = levelColor + `${level}:` + exports.CONSOLE_STYLE_Reset; + switch (level) { + case "ERROR": + if (typeof msg === "string") { + msgPart = exports.CONSOLE_STYLE_FgRed + msg + exports.CONSOLE_STYLE_Reset; + } + break; + case "DEBUG": + if (typeof msg === "string") { + msgPart = exports.CONSOLE_STYLE_FgGray + msg + exports.CONSOLE_STYLE_Reset; + } + break; + default: + break; + } + } + else { + timePart = now; + modulePart = `[${module}]`; + levelPart = `${level}:`; } - modulePart = "[" + moduleColor + module + exports.CONSOLE_STYLE_Reset + "]"; - levelPart = levelColor + `${level}:` + exports.CONSOLE_STYLE_Reset; switch (level) { case "ERROR": - if (typeof msg === "string") { - msgPart = exports.CONSOLE_STYLE_FgRed + msg + exports.CONSOLE_STYLE_Reset; - } - else { - msgPart = msg; - } + console.error(timePart, modulePart, levelPart, msgPart); + break; + case "WARN": + console.warn(timePart, modulePart, levelPart, msgPart); + break; + case "INFO": + console.info(timePart, modulePart, levelPart, msgPart); break; case "DEBUG": - if (typeof msg === "string") { - msgPart = exports.CONSOLE_STYLE_FgGray + msg + exports.CONSOLE_STYLE_Reset; - } - else { - msgPart = msg; + if (exports.isDev) { + console.debug(timePart, modulePart, levelPart, msgPart); } break; default: - msgPart = msg; + console.log(timePart, modulePart, levelPart, msgPart); break; } } else { - timePart = now; - modulePart = `[${module}]`; - levelPart = `${level}:`; - msgPart = msg; - } - switch (level) { - case "ERROR": - console.error(timePart, modulePart, levelPart, msgPart); - break; - case "WARN": - console.warn(timePart, modulePart, levelPart, msgPart); - break; - case "INFO": - console.info(timePart, modulePart, levelPart, msgPart); - break; - case "DEBUG": - if (exports.isDev) { - console.debug(timePart, modulePart, levelPart, msgPart); - } - break; - default: - console.log(timePart, modulePart, levelPart, msgPart); - break; + console.log(JSON.stringify({ + time: timePart, + module: modulePart, + level: levelPart, + msg: typeof msg === "string" ? msg : JSON.stringify(msg), + })); } } info(module, msg) { - this.log(module, msg, "info"); + this.log(module, msg, "INFO"); } warn(module, msg) { - this.log(module, msg, "warn"); + this.log(module, msg, "WARN"); } error(module, msg) { - this.log(module, msg, "error"); + this.log(module, msg, "ERROR"); } debug(module, msg) { - this.log(module, msg, "debug"); + this.log(module, msg, "DEBUG"); } exception(module, exception, msg) { let finalMessage = exception; if (msg) { finalMessage = `${msg}: ${exception}`; } - this.log(module, finalMessage, "error"); + this.log(module, finalMessage, "ERROR"); } } exports.log = new Logger(); From 57fd7b124b25f0ecb285886f855fb3b192e1939f Mon Sep 17 00:00:00 2001 From: Cassandra Beelen Date: Thu, 19 Sep 2024 10:30:29 +0200 Subject: [PATCH 5/7] fix(eslint): minor linter complaints & a typo --- server/notification-providers/google-chat.js | 3 +-- server/notification-providers/slack.js | 5 ++--- server/util-server.js | 1 - 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/server/notification-providers/google-chat.js b/server/notification-providers/google-chat.js index afba8f6c7c..e683a2070f 100644 --- a/server/notification-providers/google-chat.js +++ b/server/notification-providers/google-chat.js @@ -1,6 +1,6 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); -const { getMonitorRelativeURL, DOWN, UP } = require("../../src/util"); +const { getMonitorRelativeURL, UP } = require("../../src/util"); const { Settings } = require("../settings"); class GoogleChat extends NotificationProvider { @@ -35,7 +35,6 @@ class GoogleChat extends NotificationProvider { }, ]; - // add time if available if (heartbeatJSON) { sectionWidgets.push({ diff --git a/server/notification-providers/slack.js b/server/notification-providers/slack.js index b16878b675..98ed1a908d 100644 --- a/server/notification-providers/slack.js +++ b/server/notification-providers/slack.js @@ -9,8 +9,7 @@ class Slack extends NotificationProvider { /** * Deprecated property notification.slackbutton - * Set it as - ry base url if this is not yet set. + * Set it as primary base url if this is not yet set. * @deprecated * @param {string} url The primary base URL to use * @returns {Promise} @@ -136,7 +135,7 @@ class Slack extends NotificationProvider { return okMsg; } - const baseURL = await setting("primaryBaseURL"); + const baseURL = await Settings.get("primaryBaseURL"); const title = "Uptime Kuma Alert"; let data = { diff --git a/server/util-server.js b/server/util-server.js index 37fee63222..f4a4a67fe4 100644 --- a/server/util-server.js +++ b/server/util-server.js @@ -12,7 +12,6 @@ const { Client } = require("pg"); const postgresConParse = require("pg-connection-string").parse; const mysql = require("mysql2"); const { NtlmClient } = require("./modules/axios-ntlm/lib/ntlmClient.js"); -const { Settings } = require("./settings"); const grpc = require("@grpc/grpc-js"); const protojs = require("protobufjs"); const radiusClient = require("node-radius-client"); From e249a0b97d39673389799ec0b66f0b9fd873990c Mon Sep 17 00:00:00 2001 From: Cassandra Beelen Date: Thu, 19 Sep 2024 11:37:30 +0200 Subject: [PATCH 6/7] fix(apicache): log line object serialization Resolves the following trace: Trace: TypeError: Cannot convert object to primitive value at res.end (/uptime-kuma/server/modules/apicache/apicache.js:308:64) at ServerResponse.send (/uptime-kuma/node_modules/express/lib/response.js:233:10) at ServerResponse.json (/uptime-kuma/node_modules/express/lib/response.js:279:15) at module.exports.sendHttpError (/uptime-kuma/server/util-server.js:806:25) at /uptime-kuma/server/routers/status-page-router.js:58:9 at process.unexpectedErrorHandler (/uptime-kuma/server/server.js:1858:13) at process.emit (node:events:519:28) at emitUnhandledRejection (node:internal/process/promises:250:13) at throwUnhandledRejectionsMode (node:internal/process/promises:385:19) at processPromiseRejections (node:internal/process/promises:470:17) at process.processTicksAndRejections (node:internal/process/task_queues:96:32) --- server/modules/apicache/apicache.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/modules/apicache/apicache.js b/server/modules/apicache/apicache.js index 89f2f1e165..804fa93eda 100644 --- a/server/modules/apicache/apicache.js +++ b/server/modules/apicache/apicache.js @@ -304,9 +304,9 @@ function ApiCache() { // display log entry let elapsed = new Date() - req.apicacheTimer; log.debug("apicache", `adding cache entry for "${key}" @ ${strDuration} ${logDuration(elapsed)}`); - log.debug("apicache", `_apicache.headers: ${res._apicache.headers}`); - log.debug("apicache", `res.getHeaders(): ${getSafeHeaders(res)}`); - log.debug("apicache", `cacheObject: ${cacheObject}`); + log.debug("apicache", `_apicache.headers: ${JSON.stringify(res._apicache.headers)}`); + log.debug("apicache", `res.getHeaders(): ${JSON.stringify(getSafeHeaders(res))}`); + log.debug("apicache", `cacheObject: ${JSON.stringify(cacheObject)}`); } } From 36613bf04bf2f4bd5cf5f192ed45349734fe03b5 Mon Sep 17 00:00:00 2001 From: Cassandra Beelen Date: Tue, 24 Sep 2024 09:39:27 +0200 Subject: [PATCH 7/7] refactor(utils): address code review feedback * & recompile utils.js --- src/util.js | 97 ++++++++++++++++++++++----------------------- src/util.ts | 110 ++++++++++++++++++++++++++-------------------------- 2 files changed, 100 insertions(+), 107 deletions(-) diff --git a/src/util.js b/src/util.js index c073bb971a..8b2c2b9d77 100644 --- a/src/util.js +++ b/src/util.js @@ -175,73 +175,68 @@ class Logger { else { now = (0, dayjs_1.default)().format(); } - const structuredLogging = process.env.UPTIME_KUMA_LOG_FORMAT === "json"; const levelColor = consoleLevelColors[level]; const moduleColor = consoleModuleColors[intHash(module, consoleModuleColors.length)]; let timePart = now; let modulePart = module; let levelPart = level; let msgPart = msg; - if (!structuredLogging) { - module = module.toUpperCase(); - if (exports.isNode) { - switch (level) { - case "DEBUG": - timePart = exports.CONSOLE_STYLE_FgGray + now + exports.CONSOLE_STYLE_Reset; - break; - default: - timePart = exports.CONSOLE_STYLE_FgCyan + now + exports.CONSOLE_STYLE_Reset; - break; - } - modulePart = "[" + moduleColor + module + exports.CONSOLE_STYLE_Reset + "]"; - levelPart = levelColor + `${level}:` + exports.CONSOLE_STYLE_Reset; - switch (level) { - case "ERROR": - if (typeof msg === "string") { - msgPart = exports.CONSOLE_STYLE_FgRed + msg + exports.CONSOLE_STYLE_Reset; - } - break; - case "DEBUG": - if (typeof msg === "string") { - msgPart = exports.CONSOLE_STYLE_FgGray + msg + exports.CONSOLE_STYLE_Reset; - } - break; - default: - break; - } - } - else { - timePart = now; - modulePart = `[${module}]`; - levelPart = `${level}:`; - } + if (process.env.UPTIME_KUMA_LOG_FORMAT === "json") { + console.log(JSON.stringify({ + time: timePart, + module: modulePart, + level: levelPart, + msg: typeof msg === "string" ? msg : JSON.stringify(msg), + })); + return; + } + module = module.toUpperCase(); + if (exports.isNode) { switch (level) { - case "ERROR": - console.error(timePart, modulePart, levelPart, msgPart); + case "DEBUG": + timePart = exports.CONSOLE_STYLE_FgGray + now + exports.CONSOLE_STYLE_Reset; break; - case "WARN": - console.warn(timePart, modulePart, levelPart, msgPart); + default: + timePart = exports.CONSOLE_STYLE_FgCyan + now + exports.CONSOLE_STYLE_Reset; break; - case "INFO": - console.info(timePart, modulePart, levelPart, msgPart); + } + modulePart = "[" + moduleColor + module + exports.CONSOLE_STYLE_Reset + "]"; + levelPart = levelColor + `${level}:` + exports.CONSOLE_STYLE_Reset; + switch (level) { + case "ERROR": + if (typeof msg === "string") { + msgPart = exports.CONSOLE_STYLE_FgRed + msg + exports.CONSOLE_STYLE_Reset; + } break; case "DEBUG": - if (exports.isDev) { - console.debug(timePart, modulePart, levelPart, msgPart); + if (typeof msg === "string") { + msgPart = exports.CONSOLE_STYLE_FgGray + msg + exports.CONSOLE_STYLE_Reset; } break; - default: - console.log(timePart, modulePart, levelPart, msgPart); - break; } } else { - console.log(JSON.stringify({ - time: timePart, - module: modulePart, - level: levelPart, - msg: typeof msg === "string" ? msg : JSON.stringify(msg), - })); + modulePart = `[${module}]`; + levelPart = `${level}:`; + } + switch (level) { + case "ERROR": + console.error(timePart, modulePart, levelPart, msgPart); + break; + case "WARN": + console.warn(timePart, modulePart, levelPart, msgPart); + break; + case "INFO": + console.info(timePart, modulePart, levelPart, msgPart); + break; + case "DEBUG": + if (exports.isDev) { + console.debug(timePart, modulePart, levelPart, msgPart); + } + break; + default: + console.log(timePart, modulePart, levelPart, msgPart); + break; } } info(module, msg) { diff --git a/src/util.ts b/src/util.ts index accfe5d00b..fa71a48fa6 100644 --- a/src/util.ts +++ b/src/util.ts @@ -219,8 +219,6 @@ class Logger { now = dayjs().format(); } - const structuredLogging = process.env.UPTIME_KUMA_LOG_FORMAT === "json"; - const levelColor = consoleLevelColors[level]; const moduleColor = consoleModuleColors[intHash(module, consoleModuleColors.length)]; @@ -229,71 +227,71 @@ class Logger { let levelPart: string = level; let msgPart: unknown = msg; - if (!structuredLogging) { - // Console rendering: - module = module.toUpperCase(); - - if (isNode) { - // Add console colors - switch (level) { - case "DEBUG": - timePart = CONSOLE_STYLE_FgGray + now + CONSOLE_STYLE_Reset; - break; - default: - timePart = CONSOLE_STYLE_FgCyan + now + CONSOLE_STYLE_Reset; - break; - } + if (process.env.UPTIME_KUMA_LOG_FORMAT === "json") { + console.log(JSON.stringify({ + time: timePart, + module: modulePart, + level: levelPart, + msg: typeof msg === "string" ? msg : JSON.stringify(msg), + })); + return; + } - modulePart = "[" + moduleColor + module + CONSOLE_STYLE_Reset + "]"; - - levelPart = levelColor + `${level}:` + CONSOLE_STYLE_Reset; - - switch (level) { - case "ERROR": - if (typeof msg === "string") { - msgPart = CONSOLE_STYLE_FgRed + msg + CONSOLE_STYLE_Reset; - } - break; - case "DEBUG": - if (typeof msg === "string") { - msgPart = CONSOLE_STYLE_FgGray + msg + CONSOLE_STYLE_Reset; - } - break; - } - } else { - // No console colors - timePart = now; - modulePart = `[${module}]`; - levelPart = `${level}:`; - } + // Console rendering: + module = module.toUpperCase(); - // Write to console + if (isNode) { + // Add console colors switch (level) { - case "ERROR": - console.error(timePart, modulePart, levelPart, msgPart); + case "DEBUG": + timePart = CONSOLE_STYLE_FgGray + now + CONSOLE_STYLE_Reset; break; - case "WARN": - console.warn(timePart, modulePart, levelPart, msgPart); + default: + timePart = CONSOLE_STYLE_FgCyan + now + CONSOLE_STYLE_Reset; break; - case "INFO": - console.info(timePart, modulePart, levelPart, msgPart); + } + + modulePart = "[" + moduleColor + module + CONSOLE_STYLE_Reset + "]"; + + levelPart = levelColor + `${level}:` + CONSOLE_STYLE_Reset; + + switch (level) { + case "ERROR": + if (typeof msg === "string") { + msgPart = CONSOLE_STYLE_FgRed + msg + CONSOLE_STYLE_Reset; + } break; case "DEBUG": - if (isDev) { - console.debug(timePart, modulePart, levelPart, msgPart); + if (typeof msg === "string") { + msgPart = CONSOLE_STYLE_FgGray + msg + CONSOLE_STYLE_Reset; } break; - default: - console.log(timePart, modulePart, levelPart, msgPart); - break; } } else { - console.log(JSON.stringify({ - time: timePart, - module: modulePart, - level: levelPart, - msg: typeof msg === "string" ? msg : JSON.stringify(msg), - })) + // No console colors + modulePart = `[${module}]`; + levelPart = `${level}:`; + } + + // Write to console + switch (level) { + case "ERROR": + console.error(timePart, modulePart, levelPart, msgPart); + break; + case "WARN": + console.warn(timePart, modulePart, levelPart, msgPart); + break; + case "INFO": + console.info(timePart, modulePart, levelPart, msgPart); + break; + case "DEBUG": + if (isDev) { + console.debug(timePart, modulePart, levelPart, msgPart); + } + break; + default: + console.log(timePart, modulePart, levelPart, msgPart); + break; } }