mido
mido

Reputation: 25054

How to make console.log configurable

In my web-app( heavy on client side, light on server side), while in development, I need to do a lot of debugging, console.log is very helpful, but ideally in production, there must not be any debug message shown, so I am planning to add the below code:

window.production = false;  // set to true when in production mode.

if(window.production){    
    window.log = function(){};
}else{
    window.log = function(){
        console.log.apply(console, arguments);
    };
}    
//then replace all console.log(a, b, c, ...) into window.log(a, b, c, ...) in my code.

is this a good way to make debugging configurable, or must I just make a grunt that removes all console.log lines for production?

Upvotes: 2

Views: 1256

Answers (2)

Grant Watters
Grant Watters

Reputation: 670

So if your only end goal is to not show debug messages in production you have a huge amount of options to choose from! You should also decide if the following are important to you:

  1. Being able to perform other work outside of your log statement that also should not run in production.
  2. Minimizing file size in production and not shipping logging code.
  3. Multiple log levels, or different logging groups.
  4. The ability to turn these logging levels or groups on/off in production.
  5. Minimizing the amount that you have to type for each log statement.

At a very basic level simply calling

if (window.console && window.console.log)
{
    window.log = console.log.bind(console); // function devnull() { };
}
else
{
    window.log = function() { };
}

log('This is a log!');

will be enough to allow you to turn logging on/off. This would fulfill goal (5) in the list above and works quite well.

An alternate solution which works well with minifiers like uglify which can remove dead code would be to surround your logging statements with something like (you may not want to pollute the global namespace however):

window.LogLevels =
{
    Off:        0x00000000,
    Error:      0x00000001,
    Warning:    0x00000002,
    Timing:     0x00000004,
    Data:       0x00000008,
    Status:     0x00000010,
    ...
    Verbose:    0x04000000,
};

window.LogLevel = LogLevels.Error | LogLevels.Warning;

window.ShouldLog = function(mask)
{
    return ((window.LogLevel & mask) === mask);
};

if (ShouldLog(LogLEvels.Error)) { log('This is an error!'); }

This would satisfy condition (1), (3), and (4) and sets you up to solve (2) as well at the cost of (5).

Coupled with a pre-defined DEBUG constant (or similar), in your build step you can replace the log statements with a regex:

productionCode = debugCode.replace(/ShouldLog\(((?!LogLevels\.Error|LogLevels\.Warning)[^)]*)\)/g, 'DEBUG');

This would completely remove non-error and non-warning level logging in your code and satisfy (2). You don't really want people peeking at your logs right.. plus better perf! :)

Bonus If you want to get extra funky, you can use the following (at least in Chrome) to get a stack trace for each logging statement in your console. No more 'why did this log get hit'!

window.log = function ()
{
    console.groupCollapsed.apply(console, arguments);
    var stack = new Error().stack.split('\n');
    for(var i = 2; i < stack.length; i ++)
    {
        // Trim and remove 'at ';
        console.log('%c' + stack[i].trim().substring(3), 'padding-left: 10px; color: #777');
    }
    console.groupEnd();
};

Upvotes: 4

nha
nha

Reputation: 18005

If you are using build tools like Gulp.js or Grunt.js, then there are modules to do that :

Upvotes: 0

Related Questions