diff --git a/lib/winston/logger.js b/lib/winston/logger.js index 1bf03240a..130a8aba1 100755 --- a/lib/winston/logger.js +++ b/lib/winston/logger.js @@ -14,6 +14,8 @@ var events = require('events'), exception = require('./exception'), Stream = require('stream').Stream; +const formatRegExp = /%[sdj%]/g; + // // ### function Logger (options) // #### @options {Object} Options for this instance. @@ -118,9 +120,9 @@ Logger.prototype.log = function (level) { // // logger.info('No interpolation symbols', 'ok', 'why', { meta: 'is-this' }); // - var callback = typeof args[args.length - 1] === 'function' ? args.pop() : null, - meta = typeof args[args.length - 1] === 'object' && Object.prototype.toString.call(args[args.length - 1]) !== '[object RegExp]' ? args.pop() : {}, - msg = util.format.apply(null, args); + var callback = typeof args[args.length - 1] === 'function' + ? args.pop() + : null; // // Handle errors appropriately. @@ -157,6 +159,21 @@ Logger.prototype.log = function (level) { return; } + // + // Determining what is `meta` and what are arguments for string interpolation + // turns out to be VERY tricky. e.g. in the cases like this: + // + // logger.info('No interpolation symbols', 'ok', 'why', { meta: 'is-this' }); + // + var metaType = Object.prototype.toString.call(args[args.length - 1]), + fmtMatch = args[0].match && args[0].match(formatRegExp), + isFormat = fmtMatch && fmtMatch.length, + validMeta = !isFormat + ? metaType === '[object Object]' || metaType === '[object Error]' || metaType === '[object Array]' + : metaType === '[object Object]', + meta = validMeta ? args.pop() : {}, + msg = util.format.apply(null, args); + // // Respond to the callback. //