We followed @Tim Down's suggestion
logger.info( JSON.stringify(blah) );
But we had performance issues, since JSON.stringify happens before logger.info is logger.info , so it will always happen even if the logging level is set to ignore this log.
To get around this, I wrote a new lazy layout so that streaming only happens if the log is actually displayed. To be more flexible, it can also pass a function, in which case it outputs the result of the specified function.
Application:
logger.trace("Received ", widget, " which has ", () => countFrimbles(widget), ' frimbles');
Implementation:
function LazyFormatLayout() { } LazyFormatLayout.prototype = new log4javascript.Layout(); LazyFormatLayout.prototype.format = function (loggingEvent) { var time = loggingEvent.timeStamp.toTimeString().split(/\s/)[0]; var head = time + ' ' + loggingEvent.logger.name + ' [' + loggingEvent.level.name + '] - '; var body = loggingEvent.messages.map(function (arg) { try { switch (typeof (arg)) { case 'function': return arg(); case 'object': return JSON.stringify(arg); } } catch (e) { return '<<error while logging: ' + e.stack + '>>'; } return arg; }).join(''); if (!loggingEvent.exception) return head + body; return head + body + ' ==> Exception: ' + loggingEvent.exception.stack; } LazyFormatLayout.prototype.ignoresThrowable = function () { return false; }; LazyFormatLayout.prototype.toString = function () { return "LazyFormatLayout"; };
Motti source share