Overriding console.log in Node.js, and other thoughts about logging in Node apps

How should Node.js programs best do logging?  When that question came up in the node users mailing list, Tim Caswell answered to just use console.log, and if you want to send the log to somewhere other than stdout then to override the function.  That makes the Java programmer recoil with "eeew, overriding a system function is wrong" but hey we're in a JavaScript environment.  This sort of thing is par for the course in JavaScript.  So, how do you go about doing this?

The first interesting thing I found looking for wasn't an answer to this question, but instead an interesting behavior of console.log.  If the object being logged has a ".inspect" function, console.log uses that inspect function to get the string to be logged.  See http://ditesh.gathani.org/blog/2011/07/console-log-ing-objects/

An interesting answer is on Quora, and there is an NPM module to implement the answer (see https://github.com/jonseymour/node-idiomatic-stdio).  The answer is:

console.log=(function() {
  var orig=console.log;
  return function() {
    try {
      var tmp=process.stdout;
      process.stdout=process.stderr;
      orig.apply(console, arguments);
    } finally {
      process.stdout=tmp;
    }
  };
})();  

console.info=(function() {
  var orig=console.info;
  return function() {
    try {
      var tmp=process.stdout;
      process.stdout=process.stderr;
      orig.apply(console, arguments);
    } finally {
      process.stdout=tmp;
    }
  }; 
})();

http://www.quora.com/What-is-the-standard-idiom-for-rebinding-console-log-with-stderr-in-node-js

The console-trace module (https://github.com/LearnBoost/console-trace) implements another method of overriding console.log.  This is the core piece of code (https://github.com/LearnBoost/console-trace/blob/master/console-trace.js):


/**


* Overrides the console methods.


*/


;['error', 'log', 'info', 'warn', 'trace'].forEach(function (name) {


  var fn = console[name];


  console[name] = function () {


    if (console._trace || console.traceOptions.always) {


      if (Buffer.isBuffer(arguments[0])) {


        arguments[0] = arguments[0].inspect()


      } else if (typeof arguments[0] === 'object') {


        arguments[0] = JSON.stringify(arguments[0], null, ' ');


      }


      var pad = (arguments[0] && !console.traceOptions.right || !isatty ? ' ' : '');


      arguments[0] = console.traceFormat(__stack[1], name) + pad + arguments[0];


    }


    console._trace = false;


    return fn.apply(this, arguments);


  }


});

The crafity-log4js module looks like an interesting option to console.log.  One thing I don't like about Tim Caswell's console.log suggestion is the long-standing practice of different log levels (warn, info, error, fail, etc) and doing different things with the log message based on the log level.  There are libraries for other languages like log4j or log4js that implements the common practice that programmers have found useful elsewhere.  I'd think the logging needs of Node.js programmers writing web applications would be similar to the logging needs of JavaEE programmers?  In any case see:  https://npmjs.org/package/crafity-log4js

This github gist shows how to do this in a browser: