Search code examples
javascriptnode.jslog4js-node

How to call class method with variable args


I am creating a few NPM modules, which will be used in other modules of my large project. My main project configures and uses log4js NPM to do the logging. I also need to write some logs within the NPM modules for debugging / informational purposes.

However, I want to use the logger initialized by the main module. So, the main module passes the logger instance either by creating a global variable such as 'global.logger', or by explicitly passing during the require() call.

I want to build in a little intelligence within the NPM modules, so that they can write logs, if global.logger is initialized, or if the 'logger' var was initialized by the require() call. If the NPM module is used without a logger being defined, it will still work, but only that no logs will be printed.

To achieve this, I ended up with a couple of approaches like this.

Approach I: Write logs by checking if logger was defined.

if (logger) logger.info('Initializing npm module...');
...
if (logger) logger.info('Connecting to db...');
...
if (logger) logger.info('Fetching records...');


Approach II - Wrapper function

since approach I looks clumsy, with an if check each time, I ended up writing a wrapper fn that does the check and writes log, like this:

function log(level, msg) {
  if (!global.logger) return;
  level = level.toLowerCase();
  var args = Array.prototype.splice.call(arguments, 2);
  switch(level) {
    case 'info': global.logger.info.apply(global.logger, args);break;
    case 'trace': global.logger.trace.apply(global.logger, msg, args);break;
    case 'debug': global.logger.debug.apply(global.logger, msg, args);break;
    case 'warning': global.logger.warning(global.logger, msg, args);break;
    case 'error': global.logger.error(global.logger, msg, args);break;
    case 'fatal': global.logger.fatal(global.logger, msg, args);break;
    default: throw "Stupid error!";
  }
}

And, this wrapper would be called this way..

log("info", "Initializing Authorizer module...");

Even thought this approach works, but its still a lot of code in the wrapper function. I am sure, there could be a better way, but I am not getting it. Any help in this regard is highly appreciated.


Solution

  • If I'm understanding your question, you are trying to avoid conditionally checking for logger. If you want to extend/overwrite logging functionality I'd overwrite console.log.

      var logHandle = console.log;
      console.log = function(msg) {
        // do something with msg.
        logHandle(msg);
      }
    

    Two benefits to this. 1. console.log is familiar with node/js developers. 2. If console.log is called before your logger overwrites it, the fallback is the default behavior.