log object in log4javascript

4k Views Asked by At

I want to log objects using log4javascript. For example consider the following code:

function LogObject() {
var blah = {
    one: 42,
    two: "486"
};
logger.Info(blah);

Assuming that logger is instance of log4javascript logger that is properly set up:

var logger = log4javascript.getLogger("InternalLogger");
var ajaxAppender = new log4javascript.AjaxAppender(url),
jsonLayout = new log4javascript.JsonLayout(false, false);
ajaxAppender.setLayout(jsonLayout);
ajaxAppender.addHeader("Content-Type", "application/json");
logger.addAppender(ajaxAppender);

I am expecting the result to the following: request payload contains array of messages first of which is my object serialized into JSON. What I see is array of messages first of which has string "Object object" (like toString() method was invoked). How can I achieve that?

3

There are 3 best solutions below

3
On BEST ANSWER

JsonLayout formats the logging event (which includes log level, timestamp and logger name in addition to the log message(s)) as JSON rather than the log message, which is pretty much assumed to be a string. The reason for this is to avoid a dependency on a JSON library for older browsers; generating JSON for the simple, known data that JsonLayout deals with is no problem without a JSON library but handling arbitrary objects definitely requires one.

The workaround I'd suggest is simply to format the message before you pass it to the logging call:

logger.info( JSON.stringify(blah) );
0
On

We were following @Tim Down's suggestion

logger.info( JSON.stringify(blah) );

But we had performance issues since the JSON.stringify happens before logger.info is called, therefore it will always happen even if the logging level is set to ignore this log.

In order to work around this I wrote a new lazy layout so that the stringification only happens if the log is actually output. In order to be more flexible it also alows passing a function, in which case it outputs the result of running said function.

Usage:

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"; };
2
On

Question is somewhat dated, but a simple google search turned up this question and there seems to be a build-in way to log objects:

var log = log4javascript.getDefaultLogger(); log.info("log following object",{ data:5, text:"bla" });

output

12:49:43 INFO - log following object { data: 5, text: bla }