From 10fd51498c5214d9a73b2cc1cc8c8d66ac9a78ce Mon Sep 17 00:00:00 2001 From: Lars Kiesow Date: Thu, 5 Jan 2023 19:06:36 +0100 Subject: [PATCH] Add Source to Logging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Audiobookshelf logs sometimes contain information about the source of the log statement, but sometimes they don't This really depends on developers adding these information to the log messages. But even then, the information is usually just a hint about the module logging this, like `[Db]` or [Watcher]`, and finding the exact line can be hard. This patch automatically adds the source of the log statement to the logs. This means if someone calls `Logger.info(…)` in line `22` of `foo.js`, the log statement will contain this file and line: ``` [2023-01-05 19:04:12[ (LogManager.js:85:18) DEBUG: Daily Log file found 2023-01-05.txt [2023-01-05 19:04:12] (LogManager.js:59:12) INFO: [LogManager] Init current daily log filename: 2023-01-05.txt ``` This should make it much easier to identify the code where the log statement originated from. Long-term, this also means that we can probably remove the manually set identifiers contained in the log messages, like the `[LogManager]` in the example above. --- server/Logger.js | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/server/Logger.js b/server/Logger.js index 2bdce9ac..1cf53074 100644 --- a/server/Logger.js +++ b/server/Logger.js @@ -22,6 +22,14 @@ class Logger { return 'UNKNOWN' } + get source() { + try { + throw new Error(); + } catch (error) { + return error.stack.split('\n')[3].replace(/^.*\/([^/]*:[0-9]*:[[0-9]*)\)*/, '$1') + } + } + getLogLevelString(level) { for (const key in LogLevel) { if (LogLevel[key] === level) { @@ -55,6 +63,7 @@ class Logger { handleLog(level, args) { const logObj = { timestamp: this.timestamp, + source: this.source, message: args.join(' '), levelName: this.getLogLevelString(level), level @@ -78,41 +87,41 @@ class Logger { trace(...args) { if (this.logLevel > LogLevel.TRACE) return - console.trace(`[${this.timestamp}] TRACE:`, ...args) + console.trace(`[${this.timestamp}[ (${this.source}) TRACE:`, ...args) this.handleLog(LogLevel.TRACE, args) } debug(...args) { if (this.logLevel > LogLevel.DEBUG) return - console.debug(`[${this.timestamp}] DEBUG:`, ...args) + console.debug(`[${this.timestamp}[ (${this.source}) DEBUG:`, ...args) this.handleLog(LogLevel.DEBUG, args) } info(...args) { if (this.logLevel > LogLevel.INFO) return - console.info(`[${this.timestamp}] INFO:`, ...args) + console.info(`[${this.timestamp}] (${this.source}) INFO:`, ...args) this.handleLog(LogLevel.INFO, args) } warn(...args) { if (this.logLevel > LogLevel.WARN) return - console.warn(`[${this.timestamp}] WARN:`, ...args) + console.warn(`[${this.timestamp}] (${this.source}) WARN:`, ...args) this.handleLog(LogLevel.WARN, args) } error(...args) { if (this.logLevel > LogLevel.ERROR) return - console.error(`[${this.timestamp}] ERROR:`, ...args) + console.error(`[${this.timestamp}] (${this.source}) ERROR:`, ...args) this.handleLog(LogLevel.ERROR, args) } fatal(...args) { - console.error(`[${this.timestamp}] FATAL:`, ...args) + console.error(`[${this.timestamp}] (${this.source}) FATAL:`, ...args) this.handleLog(LogLevel.FATAL, args) } note(...args) { - console.log(`[${this.timestamp}] NOTE:`, ...args) + console.log(`[${this.timestamp}] (${this.source}) NOTE:`, ...args) this.handleLog(LogLevel.NOTE, args) } }