diff --git a/lib/LoggingEvent.js b/lib/LoggingEvent.js index 7172679..2fc176d 100644 --- a/lib/LoggingEvent.js +++ b/lib/LoggingEvent.js @@ -14,13 +14,21 @@ class LoggingEvent { * @param {Array} data objects to log * @author Seth Chisamore */ - constructor(categoryName, level, data, context) { + constructor(categoryName, level, data, context, location) { this.startTime = new Date(); this.categoryName = categoryName; this.data = data; this.level = level; this.context = Object.assign({}, context); this.pid = process.pid; + + if (location) { + this.functionName = location.functionName; + this.fileName = location.fileName; + this.lineNumber = location.lineNumber; + this.columnNumber = location.columnNumber; + this.stack = location.stack; + } } serialise() { diff --git a/lib/layouts.js b/lib/layouts.js index 7b9989b..ebcdf47 100644 --- a/lib/layouts.js +++ b/lib/layouts.js @@ -98,6 +98,10 @@ function dummyLayout(loggingEvent) { * - %% % * - %n newline * - %z pid + * - %f filename + * - %l line number + * - %o column postion + * - %s callcstack * - %x{} add dynamic tokens to your log. Tokens are specified in the tokens parameter * - %X{} add dynamic tokens to your log. Tokens are specified in logger context * You can use %[ and %] to define a colored block. @@ -119,7 +123,7 @@ function dummyLayout(loggingEvent) { */ function patternLayout(pattern, tokens) { const TTCC_CONVERSION_PATTERN = '%r %p %c - %m%n'; - const regex = /%(-?[0-9]+)?(\.?[0-9]+)?([[\]cdhmnprzxXy%])(\{([^}]+)\})?|([^%]+)/; + const regex = /%(-?[0-9]+)?(\.?[0-9]+)?([[\]cdhmnprzxXyflos%])(\{([^}]+)\})?|([^%]+)/; pattern = pattern || TTCC_CONVERSION_PATTERN; @@ -215,6 +219,22 @@ function patternLayout(pattern, tokens) { return null; } + function fileName(loggingEvent) { + return loggingEvent.fileName || ''; + } + + function lineNumber(loggingEvent) { + return loggingEvent.lineNumber || ''; + } + + function columnNumber(loggingEvent) { + return loggingEvent.columnNumber || ''; + } + + function callStack(loggingEvent) { + return loggingEvent.stack || ''; + } + /* eslint quote-props:0 */ const replacers = { 'c': categoryName, @@ -230,7 +250,11 @@ function patternLayout(pattern, tokens) { 'z': pid, '%': percent, 'x': userDefined, - 'X': contextDefined + 'X': contextDefined, + 'f': fileName, + 'l': lineNumber, + 'o': columnNumber, + 's': callStack, }; function replaceToken(conversionCharacter, loggingEvent, specifier) { diff --git a/lib/logger.js b/lib/logger.js index 55bdedf..f9cce2c 100644 --- a/lib/logger.js +++ b/lib/logger.js @@ -9,6 +9,22 @@ const clustering = require('./clustering'); const categories = require('./categories'); const configuration = require('./configuration'); +const stackReg = /at (?:(.+)\s+\()?(?:(.+?):(\d+)(?::(\d+))?|([^)]+))\)?/; +function parseStack(data, skipIdx = 4) { + const stacklines = data.stack.split('\n').slice(skipIdx); + const lineMatch = stackReg.exec(stacklines[0]); + if (lineMatch && lineMatch.length === 6) { + return { + functionName: lineMatch[1], + fileName: lineMatch[2], + lineNumber: parseInt(lineMatch[3], 10), + columnNumber: parseInt(lineMatch[4], 10), + stack: stacklines.join('\n'), + }; + } + return null; +} + /** * Logger to log messages. * use {@see log4js#getLogger(String)} to get an instance. @@ -29,6 +45,8 @@ class Logger { this.category = name; this.context = {}; debug(`Logger created (${this.category}, ${this.level})`); + + this._useStack = false; } get level() { @@ -52,7 +70,13 @@ class Logger { _log(level, data) { debug(`sending log data (${level}) to appenders`); - const loggingEvent = new LoggingEvent(this.category, level, data, this.context); + let loggingEvent = null; + if (this._useStack) { + const location = parseStack(new Error()); + loggingEvent = new LoggingEvent(this.category, level, data, this.context, location); + } else { + loggingEvent = new LoggingEvent(this.category, level, data, this.context); + } clustering.send(loggingEvent); } @@ -67,6 +91,11 @@ class Logger { clearContext() { this.context = {}; } + + enabelCallStack(bool = true) { + this._useStack = (bool === true); + return this; + } } function addLevelMethods(target) {