diff --git a/lib/logger.js b/lib/logger.js index 3db4243..f1da46b 100644 --- a/lib/logger.js +++ b/lib/logger.js @@ -8,10 +8,32 @@ const categories = require('./categories'); const configuration = require('./configuration'); const stackReg = /at (?:(.+)\s+\()?(?:(.+?):(\d+)(?::(\d+))?|([^)]+))\)?/; +/** + * The top entry is the Error + */ +const baseCallStackSkip = 1; +/** + * The _log function is 3 levels deep, we need to skip those to make it to the callSite + */ +const defaultErrorCallStackSkip = 3; -function defaultParseCallStack(data, skipIdx = 4) { +/** + * + * @param {Error} data + * @param {number} skipIdx + * @returns {import('../types/log4js').CallStack | null} + */ +function defaultParseCallStack( + data, + skipIdx = defaultErrorCallStackSkip + baseCallStackSkip +) { try { const stacklines = data.stack.split('\n').slice(skipIdx); + if (!stacklines.length) { + // There's no stack in this stack + // Should we try a previous index if skipIdx was set? + return null; + } const lineMatch = stackReg.exec(stacklines[0]); /* istanbul ignore else: failsafe */ if (lineMatch && lineMatch.length === 6) { @@ -71,6 +93,7 @@ class Logger { } this.category = name; this.context = {}; + /** @private */ this.parseCallStack = defaultParseCallStack; debug(`Logger created (${this.category}, ${this.level})`); } @@ -123,12 +146,28 @@ class Logger { _log(level, data) { debug(`sending log data (${level}) to appenders`); + let callStack; + if (this.useCallStack) { + try { + if (data[0] instanceof Error) { + callStack = this.parseCallStack(data[0], baseCallStackSkip); + } + } catch (_err) { + // Ignore Error + } + callStack = + callStack || + this.parseCallStack( + new Error(), + defaultErrorCallStackSkip + baseCallStackSkip + ); + } const loggingEvent = new LoggingEvent( this.category, level, data, this.context, - this.useCallStack && this.parseCallStack(new Error()) + callStack ); clustering.send(loggingEvent); }