Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Javascript

JavaScript Logging

5.00/5 (3 votes)
13 Mar 2014CPOL1 min read 9.3K  
A simple JavaScript logger, supporting multiple appenders (console & service)

When "Capturing client-side JavaScript errors" showed up in the "adopt" section in the ThoughtWorks Technology Radar, I was reminded that I couldn't find a JavaScript logger which met my requirements, when I wrote my first JavaScript heavy web application (in 2011). Since the ones I looked at back then are still the top hits on Google (log4js & log4javascript), I guess there might still be a need for custom solutions. However, if one of them fits your needs, you should probably not roll your own...

I had basically two requirements:

  • Multiple appenders (console & web service)
  • Fine granular configuration

I implemented a logger "module" (no fancy and module, just the plain revealing module pattern), a console appender module and a service appender module.

The logger offers the usual log methods, checks if the corresponding level is enabled and then forwards the calls to the registered appenders:

JavaScript
isLogLevelEnabled = function (logLevel) { 
    return app.config.logger['is' + logLevel + 'Enabled'] === true;     
},
debug = function (message, category) {
    log(category, "Debug", message);
},
// ...
error = function (message, category) {
    log(category, "Error", message);
},
log = function (category, logLevel, message) {
    if (isLogLevelEnabled(logLevel)) {
        for (var i = 0; i < appenders.length; i++) {
                appenders[i].log(category, logLevel, message);
        }
    }
},

The service appender checks again if the log level is enabled (specifically for the service appender, so you can log different level with different appenders). It also allows you to enable logging for specific users by setting a cookie. This could be handy when you need to debug an issue of a specific user.

JavaScript
var log = function (category, logLevel, message) {
    if (isLogLevelEnabled(logLevel) || isUserEnabled()) {
        var logData = { 'category': category, 'logLevel': logLevel, 'message': message };
        $.post(app.config.serviceAppender.logServiceUrl, logData);
    }
},
    isLogLevelEnabled = function (logLevel) {
        return app.config.serviceAppender['is' + logLevel + 'Enabled'] === true;
    },
    isUserEnabled = function () {
        return typeof (app.config.serviceAppender.allowServiceLoggingByCookie) !== 'undefined' &&
            app.config.serviceAppender.allowServiceLoggingByCookie === true &&
                $.cookie("enableServiceLogging") === "true";
    };

The config is set by defining the app.config object, which you probably want to load from a database or some other storage you can edit without deploying your site.

JavaScript
window.app.config = {};
window.app.config.logger = { isDebugEnabled: false, isInfoEnabled: true, 
    isWarnEnabled: true, isErrorEnabled: true };
window.app.config.serviceAppender = {
    allowServiceLoggingByCookie: true, logServiceUrl: '@Url.Content("~/api/log")',
    isDebugEnabled: false, isInfoEnabled: false, 
    isWarnEnabled: true, isErrorEnabled: true
};
window.app.config.consoleAppender = {
    isDebugEnabled: false, isInfoEnabled: true,
    isWarnEnabled: true, isErrorEnabled: true
};

You can check out the sample project. It is a F5-ready ASP.NET MVC application, although nothing about the logger is .NET specific.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)