mirror of
				https://github.com/louislam/uptime-kuma.git
				synced 2025-10-31 19:39:20 +08:00 
			
		
		
		
	Merge pull request #875 from tarun7singh/master
Added MQTT Monitor type
This commit is contained in:
		
							
								
								
									
										16
									
								
								db/patch-added-mqtt-monitor.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								db/patch-added-mqtt-monitor.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| -- You should not modify if this have pushed to Github, unless it does serious wrong with the db. | ||||
| BEGIN TRANSACTION; | ||||
|  | ||||
| ALTER TABLE monitor | ||||
| 	ADD mqtt_topic TEXT; | ||||
|  | ||||
| ALTER TABLE monitor | ||||
| 	ADD mqtt_success_message VARCHAR(255); | ||||
|  | ||||
| ALTER TABLE monitor | ||||
| 	ADD mqtt_username VARCHAR(255); | ||||
|  | ||||
| ALTER TABLE monitor | ||||
| 	ADD mqtt_password VARCHAR(255); | ||||
|  | ||||
| COMMIT; | ||||
							
								
								
									
										50
									
								
								extra/simple-mqtt-server.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								extra/simple-mqtt-server.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| const { log } = require("../src/util"); | ||||
|  | ||||
| const mqttUsername = "louis1"; | ||||
| const mqttPassword = "!@#$LLam"; | ||||
|  | ||||
| class SimpleMqttServer { | ||||
|     aedes = require("aedes")(); | ||||
|     server = require("net").createServer(this.aedes.handle); | ||||
|  | ||||
|     constructor(port) { | ||||
|         this.port = port; | ||||
|     } | ||||
|  | ||||
|     start() { | ||||
|         this.server.listen(this.port, () => { | ||||
|             console.log("server started and listening on port ", this.port); | ||||
|         }); | ||||
|     } | ||||
| } | ||||
|  | ||||
| let server1 = new SimpleMqttServer(10000); | ||||
|  | ||||
| server1.aedes.authenticate = function (client, username, password, callback) { | ||||
|     if (username && password) { | ||||
|         console.log(password.toString("utf-8")); | ||||
|         callback(null, username === mqttUsername && password.toString("utf-8") === mqttPassword); | ||||
|     } else { | ||||
|         callback(null, false); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| server1.aedes.on("subscribe", (subscriptions, client) => { | ||||
|     console.log(subscriptions); | ||||
|  | ||||
|     for (let s of subscriptions) { | ||||
|         if (s.topic === "test") { | ||||
|             server1.aedes.publish({ | ||||
|                 topic: "test", | ||||
|                 payload: Buffer.from("ok"), | ||||
|             }, (error) => { | ||||
|                 if (error) { | ||||
|                     log.error("mqtt_server", error); | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| }); | ||||
|  | ||||
| server1.start(); | ||||
							
								
								
									
										708
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										708
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -49,6 +49,7 @@ | ||||
|         "test-install-script-ubuntu1604": "npm run compile-install-script && docker build --progress plain -f test/test_install_script/ubuntu1604.dockerfile .", | ||||
|         "test-nodejs16": "docker build --progress plain -f test/ubuntu-nodejs16.dockerfile .", | ||||
|         "simple-dns-server": "node extra/simple-dns-server.js", | ||||
|         "simple-mqtt-server": "node extra/simple-mqtt-server.js", | ||||
|         "update-language-files-with-base-lang": "cd extra/update-language-files && node index.js %npm_config_base_lang% && eslint ../../src/languages/**.js --fix", | ||||
|         "update-language-files": "cd extra/update-language-files && node index.js && eslint ../../src/languages/**.js --fix", | ||||
|         "ncu-patch": "npm-check-updates -u -t patch", | ||||
| @@ -86,6 +87,7 @@ | ||||
|         "jsonwebtoken": "~8.5.1", | ||||
|         "jwt-decode": "^3.1.2", | ||||
|         "limiter": "^2.1.0", | ||||
|         "mqtt": "^4.2.8", | ||||
|         "node-cloudflared-tunnel": "~1.0.9", | ||||
|         "nodemailer": "~6.6.5", | ||||
|         "notp": "~2.0.3", | ||||
| @@ -126,6 +128,7 @@ | ||||
|         "@vitejs/plugin-legacy": "~1.6.4", | ||||
|         "@vitejs/plugin-vue": "~1.9.4", | ||||
|         "@vue/compiler-sfc": "~3.2.31", | ||||
|         "aedes": "^0.46.3", | ||||
|         "babel-plugin-rewire": "~1.2.0", | ||||
|         "core-js": "~3.18.3", | ||||
|         "cross-env": "~7.0.3", | ||||
|   | ||||
| @@ -57,6 +57,7 @@ class Database { | ||||
|         "patch-proxy.sql": true, | ||||
|         "patch-monitor-expiry-notification.sql": true, | ||||
|         "patch-status-page-footer-css.sql": true, | ||||
|         "patch-added-mqtt-monitor.sql": true, | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -7,7 +7,7 @@ dayjs.extend(timezone); | ||||
| const axios = require("axios"); | ||||
| const { Prometheus } = require("../prometheus"); | ||||
| const { log, UP, DOWN, PENDING, flipStatus, TimeLogger } = require("../../src/util"); | ||||
| const { tcping, ping, dnsResolve, checkCertificate, checkStatusCode, getTotalClientInRoom, setting, errorLog } = require("../util-server"); | ||||
| const { tcping, ping, dnsResolve, checkCertificate, checkStatusCode, getTotalClientInRoom, setting, errorLog, mqttAsync } = require("../util-server"); | ||||
| const { R } = require("redbean-node"); | ||||
| const { BeanModel } = require("redbean-node/dist/bean-model"); | ||||
| const { Notification } = require("../notification"); | ||||
| @@ -81,6 +81,10 @@ class Monitor extends BeanModel { | ||||
|             proxyId: this.proxy_id, | ||||
|             notificationIDList, | ||||
|             tags: tags, | ||||
|             mqttUsername: this.mqttUsername, | ||||
|             mqttPassword: this.mqttPassword, | ||||
|             mqttTopic: this.mqttTopic, | ||||
|             mqttSuccessMessage: this.mqttSuccessMessage | ||||
|         }; | ||||
|  | ||||
|         if (includeSensitiveData) { | ||||
| @@ -159,7 +163,7 @@ class Monitor extends BeanModel { | ||||
|             // undefined if not https | ||||
|             let tlsInfo = undefined; | ||||
|  | ||||
|             if (! previousBeat) { | ||||
|             if (!previousBeat) { | ||||
|                 previousBeat = await R.findOne("heartbeat", " monitor_id = ? ORDER BY time DESC", [ | ||||
|                     this.id, | ||||
|                 ]); | ||||
| @@ -177,7 +181,7 @@ class Monitor extends BeanModel { | ||||
|             } | ||||
|  | ||||
|             // Duration | ||||
|             if (! isFirstBeat) { | ||||
|             if (!isFirstBeat) { | ||||
|                 bean.duration = dayjs(bean.time).diff(dayjs(previousBeat.time), "second"); | ||||
|             } else { | ||||
|                 bean.duration = 0; | ||||
| @@ -382,7 +386,7 @@ class Monitor extends BeanModel { | ||||
|                         }, | ||||
|                         httpsAgent: new https.Agent({ | ||||
|                             maxCachedSessions: 0,      // Use Custom agent to disable session reuse (https://github.com/nodejs/node/issues/3940) | ||||
|                             rejectUnauthorized: ! this.getIgnoreTls(), | ||||
|                             rejectUnauthorized: !this.getIgnoreTls(), | ||||
|                         }), | ||||
|                         maxRedirects: this.maxredirects, | ||||
|                         validateStatus: (status) => { | ||||
| @@ -404,7 +408,14 @@ class Monitor extends BeanModel { | ||||
|                     } else { | ||||
|                         throw new Error("Server not found on Steam"); | ||||
|                     } | ||||
|  | ||||
|                 } else if (this.type === "mqtt") { | ||||
|                     bean.msg = await mqttAsync(this.hostname, this.mqttTopic, this.mqttSuccessMessage, { | ||||
|                         port: this.port, | ||||
|                         username: this.mqttUsername, | ||||
|                         password: this.mqttPassword, | ||||
|                         interval: this.interval, | ||||
|                     }); | ||||
|                     bean.status = UP; | ||||
|                 } else { | ||||
|                     bean.msg = "Unknown Monitor Type"; | ||||
|                     bean.status = PENDING; | ||||
| @@ -683,7 +694,7 @@ class Monitor extends BeanModel { | ||||
|  | ||||
|         } else { | ||||
|             // Handle new monitor with only one beat, because the beat's duration = 0 | ||||
|             let status = parseInt(await R.getCell("SELECT `status` FROM heartbeat WHERE monitor_id = ?", [ monitorID ])); | ||||
|             let status = parseInt(await R.getCell("SELECT `status` FROM heartbeat WHERE monitor_id = ?", [monitorID])); | ||||
|  | ||||
|             if (status === UP) { | ||||
|                 uptime = 1; | ||||
|   | ||||
| @@ -720,6 +720,9 @@ try { | ||||
|                 bean.dns_resolve_server = monitor.dns_resolve_server; | ||||
|                 bean.pushToken = monitor.pushToken; | ||||
|                 bean.proxyId = Number.isInteger(monitor.proxyId) ? monitor.proxyId : null; | ||||
|                 bean.mqttUsername = monitor.mqttUsername; | ||||
|                 bean.mqttTopic = monitor.mqttTopic; | ||||
|                 bean.mqttSuccessMessage = monitor.mqttSuccessMessage; | ||||
|  | ||||
|                 await R.store(bean); | ||||
|  | ||||
|   | ||||
| @@ -9,6 +9,7 @@ const iconv = require("iconv-lite"); | ||||
| const chardet = require("chardet"); | ||||
| const fs = require("fs"); | ||||
| const nodeJsUtil = require("util"); | ||||
| const mqtt = require("mqtt"); | ||||
|  | ||||
| // From ping-lite | ||||
| exports.WIN = /^win/.test(process.platform); | ||||
| @@ -26,7 +27,7 @@ exports.initJWTSecret = async () => { | ||||
|         "jwtSecret", | ||||
|     ]); | ||||
|  | ||||
|     if (! jwtSecretBean) { | ||||
|     if (!jwtSecretBean) { | ||||
|         jwtSecretBean = R.dispense("setting"); | ||||
|         jwtSecretBean.key = "jwtSecret"; | ||||
|     } | ||||
| @@ -88,6 +89,63 @@ exports.pingAsync = function (hostname, ipv6 = false) { | ||||
|     }); | ||||
| }; | ||||
|  | ||||
| exports.mqttAsync = function (hostname, topic, okMessage, options = {}) { | ||||
|     return new Promise((resolve, reject) => { | ||||
|         const { port, username, password, interval = 20 } = options; | ||||
|  | ||||
|         // Adds MQTT protocol to the hostname if not already present | ||||
|         if (!/^(?:http|mqtt)s?:\/\//.test(hostname)) { | ||||
|             hostname = "mqtt://" + hostname; | ||||
|         } | ||||
|  | ||||
|         const timeoutID = setTimeout(() => { | ||||
|             log.debug("mqtt", "MQTT timeout triggered"); | ||||
|             client.end(); | ||||
|             reject(new Error("Timeout")); | ||||
|         }, interval * 1000 * 0.8); | ||||
|  | ||||
|         log.debug("mqtt", "MQTT connecting"); | ||||
|  | ||||
|         let client = mqtt.connect(hostname, { | ||||
|             port, | ||||
|             username, | ||||
|             password | ||||
|         }); | ||||
|  | ||||
|         client.on("connect", () => { | ||||
|             log.debug("mqtt", "MQTT connected"); | ||||
|  | ||||
|             try { | ||||
|                 log.debug("mqtt", "MQTT subscribe topic"); | ||||
|                 client.subscribe(topic); | ||||
|             } catch (e) { | ||||
|                 client.end(); | ||||
|                 clearTimeout(timeoutID); | ||||
|                 reject(new Error("Cannot subscribe topic")); | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         client.on("error", (error) => { | ||||
|             client.end(); | ||||
|             clearTimeout(timeoutID); | ||||
|             reject(error); | ||||
|         }); | ||||
|  | ||||
|         client.on("message", (messageTopic, message) => { | ||||
|             if (messageTopic == topic) { | ||||
|                 client.end(); | ||||
|                 clearTimeout(timeoutID); | ||||
|                 if (message.toString() === okMessage) { | ||||
|                     resolve(`Topic: ${messageTopic}; Message: ${message.toString()}`); | ||||
|                 } else { | ||||
|                     reject(new Error(`Error; Topic: ${messageTopic}; Message: ${message.toString()}`)); | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|     }); | ||||
| }; | ||||
|  | ||||
| exports.dnsResolve = function (hostname, resolverServer, rrtype) { | ||||
|     const resolver = new Resolver(); | ||||
|     resolver.setServers([ resolverServer ]); | ||||
| @@ -206,7 +264,7 @@ const parseCertificateInfo = function (info) { | ||||
|     const existingList = {}; | ||||
|  | ||||
|     while (link) { | ||||
|         log.debug("util", `[${i}] ${link.fingerprint}`); | ||||
|         log.debug("cert", `[${i}] ${link.fingerprint}`); | ||||
|  | ||||
|         if (!link.valid_from || !link.valid_to) { | ||||
|             break; | ||||
| @@ -221,7 +279,7 @@ const parseCertificateInfo = function (info) { | ||||
|         if (link.issuerCertificate == null) { | ||||
|             break; | ||||
|         } else if (link.issuerCertificate.fingerprint in existingList) { | ||||
|             log.debug("util", `[Last] ${link.issuerCertificate.fingerprint}`); | ||||
|             log.debug("cert", `[Last] ${link.issuerCertificate.fingerprint}`); | ||||
|             link.issuerCertificate = null; | ||||
|             break; | ||||
|         } else { | ||||
| @@ -242,7 +300,7 @@ exports.checkCertificate = function (res) { | ||||
|     const info = res.request.res.socket.getPeerCertificate(true); | ||||
|     const valid = res.request.res.socket.authorized || false; | ||||
|  | ||||
|     log.debug("util", "Parsing Certificate Info"); | ||||
|     log.debug("cert", "Parsing Certificate Info"); | ||||
|     const parsedInfo = parseCertificateInfo(info); | ||||
|  | ||||
|     return { | ||||
| @@ -284,13 +342,13 @@ exports.getTotalClientInRoom = (io, roomName) => { | ||||
|  | ||||
|     const sockets = io.sockets; | ||||
|  | ||||
|     if (! sockets) { | ||||
|     if (!sockets) { | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     const adapter = sockets.adapter; | ||||
|  | ||||
|     if (! adapter) { | ||||
|     if (!adapter) { | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
| @@ -315,7 +373,7 @@ exports.allowAllOrigin = (res) => { | ||||
| }; | ||||
|  | ||||
| exports.checkLogin = (socket) => { | ||||
|     if (! socket.userID) { | ||||
|     if (!socket.userID) { | ||||
|         throw new Error("You are not logged in."); | ||||
|     } | ||||
| }; | ||||
|   | ||||
| @@ -309,6 +309,10 @@ export default { | ||||
|     "One record": "One record", | ||||
|     steamApiKeyDescription: "For monitoring a Steam Game Server you need a Steam Web-API key. You can register your API key here: ", | ||||
|     "Current User": "Current User", | ||||
|     topic: "Topic", | ||||
|     topicExplanation: "MQTT topic to monitor", | ||||
|     successMessage: "Success Message", | ||||
|     successMessageExplanation: "MQTT message that will be considered as success", | ||||
|     recent: "Recent", | ||||
|     Done: "Done", | ||||
|     Info: "Info", | ||||
|   | ||||
| @@ -32,6 +32,9 @@ | ||||
|                                     <option value="steam"> | ||||
|                                         Steam Game Server | ||||
|                                     </option> | ||||
|                                     <option value="mqtt"> | ||||
|                                         MQTT | ||||
|                                     </option> | ||||
|                                 </select> | ||||
|                             </div> | ||||
|  | ||||
| @@ -67,15 +70,15 @@ | ||||
|                             </div> | ||||
|  | ||||
|                             <!-- Hostname --> | ||||
|                             <!-- TCP Port / Ping / DNS / Steam only --> | ||||
|                             <div v-if="monitor.type === 'port' || monitor.type === 'ping' || monitor.type === 'dns' || monitor.type === 'steam'" class="my-3"> | ||||
|                             <!-- TCP Port / Ping / DNS / Steam / MQTT only --> | ||||
|                             <div v-if="monitor.type === 'port' || monitor.type === 'ping' || monitor.type === 'dns' || monitor.type === 'steam' || monitor.type === 'mqtt'" class="my-3"> | ||||
|                                 <label for="hostname" class="form-label">{{ $t("Hostname") }}</label> | ||||
|                                 <input id="hostname" v-model="monitor.hostname" type="text" class="form-control" :pattern="`${ipRegexPattern}|${hostnameRegexPattern}`" required> | ||||
|                             </div> | ||||
|  | ||||
|                             <!-- Port --> | ||||
|                             <!-- For TCP Port / Steam Type --> | ||||
|                             <div v-if="monitor.type === 'port' || monitor.type === 'steam'" class="my-3"> | ||||
|                             <!-- For TCP Port / Steam / MQTT Type --> | ||||
|                             <div v-if="monitor.type === 'port' || monitor.type === 'steam' || monitor.type === 'mqtt'" class="my-3"> | ||||
|                                 <label for="port" class="form-label">{{ $t("Port") }}</label> | ||||
|                                 <input id="port" v-model="monitor.port" type="number" class="form-control" required min="0" max="65535" step="1"> | ||||
|                             </div> | ||||
| @@ -115,6 +118,36 @@ | ||||
|                                 </div> | ||||
|                             </template> | ||||
|  | ||||
|                             <!-- MQTT --> | ||||
|                             <!-- For MQTT Type --> | ||||
|                             <template v-if="monitor.type === 'mqtt'"> | ||||
|                                 <div class="my-3"> | ||||
|                                     <label for="mqttUsername" class="form-label">MQTT {{ $t("Username") }}</label> | ||||
|                                     <input id="mqttUsername" v-model="monitor.mqttUsername" type="text" class="form-control"> | ||||
|                                 </div> | ||||
|  | ||||
|                                 <div class="my-3"> | ||||
|                                     <label for="mqttPassword" class="form-label">MQTT {{ $t("Password") }}</label> | ||||
|                                     <input id="mqttPassword" v-model="monitor.mqttPassword" type="password" class="form-control"> | ||||
|                                 </div> | ||||
|  | ||||
|                                 <div class="my-3"> | ||||
|                                     <label for="mqttTopic" class="form-label">MQTT {{ $t("Topic") }}</label> | ||||
|                                     <input id="mqttTopic" v-model="monitor.mqttTopic" type="text" class="form-control" required> | ||||
|                                     <div class="form-text"> | ||||
|                                         {{ $t("topicExplanation") }} | ||||
|                                     </div> | ||||
|                                 </div> | ||||
|  | ||||
|                                 <div class="my-3"> | ||||
|                                     <label for="mqttSuccessMessage" class="form-label">MQTT {{ $t("successMessage") }}</label> | ||||
|                                     <input id="mqttSuccessMessage" v-model="monitor.mqttSuccessMessage" type="text" class="form-control" required> | ||||
|                                     <div class="form-text"> | ||||
|                                         {{ $t("successMessageExplanation") }} | ||||
|                                     </div> | ||||
|                                 </div> | ||||
|                             </template> | ||||
|  | ||||
|                             <!-- Interval --> | ||||
|                             <div class="my-3"> | ||||
|                                 <label for="interval" class="form-label">{{ $t("Heartbeat Interval") }} ({{ $t("checkEverySecond", [ monitor.interval ]) }})</label> | ||||
| @@ -139,7 +172,7 @@ | ||||
|  | ||||
|                             <h2 v-if="monitor.type !== 'push'" class="mt-5 mb-2">{{ $t("Advanced") }}</h2> | ||||
|  | ||||
|                             <div class="my-3 form-check"> | ||||
|                             <div v-if="monitor.type === 'http' || monitor.type === 'keyword' " class="my-3 form-check"> | ||||
|                                 <input id="expiry-notification" v-model="monitor.expiryNotification" class="form-check-input" type="checkbox"> | ||||
|                                 <label class="form-check-label" for="expiry-notification"> | ||||
|                                     {{ $t("Domain Name Expiry Notification") }} | ||||
| @@ -492,6 +525,10 @@ export default { | ||||
|                     dns_resolve_type: "A", | ||||
|                     dns_resolve_server: "1.1.1.1", | ||||
|                     proxyId: null, | ||||
|                     mqttUsername: "", | ||||
|                     mqttPassword: "", | ||||
|                     mqttTopic: "", | ||||
|                     mqttSuccessMessage: "", | ||||
|                 }; | ||||
|  | ||||
|                 if (this.$root.proxyList && !this.monitor.proxyId) { | ||||
|   | ||||
							
								
								
									
										32
									
								
								src/util.js
									
									
									
									
									
								
							
							
						
						
									
										32
									
								
								src/util.js
									
									
									
									
									
								
							| @@ -54,7 +54,39 @@ function debug(msg) { | ||||
| } | ||||
| exports.debug = debug; | ||||
| class Logger { | ||||
|     constructor() { | ||||
|         /** | ||||
|          * UPTIME_KUMA_HIDE_LOG=debug_monitor,info_monitor | ||||
|          * | ||||
|          * Example: | ||||
|          *  [ | ||||
|          *     "debug_monitor",          // Hide all logs that level is debug and the module is monitor | ||||
|          *     "info_monitor", | ||||
|          *  ] | ||||
|          */ | ||||
|         this.hideLog = { | ||||
|             info: [], | ||||
|             warn: [], | ||||
|             error: [], | ||||
|             debug: [], | ||||
|         }; | ||||
|         if (typeof process !== "undefined" && process.env.UPTIME_KUMA_HIDE_LOG) { | ||||
|             let list = process.env.UPTIME_KUMA_HIDE_LOG.split(",").map(v => v.toLowerCase()); | ||||
|             for (let pair of list) { | ||||
|                 // split first "_" only | ||||
|                 let values = pair.split(/_(.*)/s); | ||||
|                 if (values.length >= 2) { | ||||
|                     this.hideLog[values[0]].push(values[1]); | ||||
|                 } | ||||
|             } | ||||
|             this.debug("server", "UPTIME_KUMA_HIDE_LOG is set"); | ||||
|             this.debug("server", this.hideLog); | ||||
|         } | ||||
|     } | ||||
|     log(module, msg, level) { | ||||
|         if (this.hideLog[level] && this.hideLog[level].includes(module)) { | ||||
|             return; | ||||
|         } | ||||
|         module = module.toUpperCase(); | ||||
|         level = level.toUpperCase(); | ||||
|         const now = new Date().toISOString(); | ||||
|   | ||||
							
								
								
									
										39
									
								
								src/util.ts
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								src/util.ts
									
									
									
									
									
								
							| @@ -59,7 +59,46 @@ export function debug(msg: any) { | ||||
| } | ||||
|  | ||||
| class Logger { | ||||
|  | ||||
|     /** | ||||
|      * UPTIME_KUMA_HIDE_LOG=debug_monitor,info_monitor | ||||
|      * | ||||
|      * Example: | ||||
|      *  [ | ||||
|      *     "debug_monitor",          // Hide all logs that level is debug and the module is monitor | ||||
|      *     "info_monitor", | ||||
|      *  ] | ||||
|      */ | ||||
|     hideLog : any = { | ||||
|         info: [], | ||||
|         warn: [], | ||||
|         error: [], | ||||
|         debug: [], | ||||
|     }; | ||||
|  | ||||
|     constructor() { | ||||
|         if (typeof process !== "undefined" && process.env.UPTIME_KUMA_HIDE_LOG) { | ||||
|             let list = process.env.UPTIME_KUMA_HIDE_LOG.split(",").map(v => v.toLowerCase()); | ||||
|  | ||||
|             for (let pair of list) { | ||||
|                 // split first "_" only | ||||
|                 let values = pair.split(/_(.*)/s); | ||||
|  | ||||
|                 if (values.length >= 2) { | ||||
|                     this.hideLog[values[0]].push(values[1]); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             this.debug("server", "UPTIME_KUMA_HIDE_LOG is set"); | ||||
|             this.debug("server", this.hideLog); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     log(module: string, msg: any, level: string) { | ||||
|         if (this.hideLog[level] && this.hideLog[level].includes(module)) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         module = module.toUpperCase(); | ||||
|         level = level.toUpperCase(); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user