Common logging for node, express application -- best practice?

bunyan, express, javascript, logging, node.js

Solution

Singleton pattern in nodejs - is it needed? Actually, singleton is perhaps not needed in Node's environment. All you need to do is to create a logger in a separate file say, logger.js:

var bunyan = require("bunyan"); // Bunyan dependency
var logger = bunyan.createLogger({name: "myLogger"});

module.exports = logger;

Then, retrieve this logger from another module:

var logger = require("./logger");
logger.info("Anything you like");

Problem

I'm working on an node.js application with several dozen modules and using bunyan for logging (JSON output, multiple configurable streams). I've been looking for good examples of how to implement a instance across all the modules, but haven't seen what appears to be a really clean example I can learn from. Below illustrates an approach that works, but seems quite inelegant (ugly) to me. I'm new to node & commonjs javascript in general, so looking for recommendations on how to improve it. module: ./lib/logger ``` // load config file (would like this to be passed in to the constructor) nconf.file({ file: fileConfig}); var logSetting = nconf.get('log'); // instantiate the logger var Bunyan = require('bunyan'); var log = new Bunyan({ name: logSetting.name, streams : [ { stream : process.stdout, level : logSetting.stdoutLevel}, { path : logSetting.logfile, level : logSetting.logfileLevel} ], serializers : Bunyan.stdSerializers }); function Logger() { }; Logger.prototype.info = function info(e) { log.info(e) }; Logger.prototype.debug = function debug(e) { log.debug(e) }; Logger.prototype.trace = function trace(e) { log.trace(e) }; Logger.prototype.error = function error(e) { log.error(e) }; Logger.prototype.warn = function warn(e) { log.warn(e) }; module.exports = Logger; ``` module: main app ``` // create the logger var logger = require('./lib/logger) var log = new logger(); // note: would like to pass in options --> new logger(options) module: any project module using logger // open the logger (new, rely on singleton...) var logger = require('./lib/logger'); var log = new logger(); ``` or view the gist any recommendations? EDIT: I've modified the constructor, making the singleton pattern explicit (rather than implicit as part of the 'require' behaviour. ``` var log = null; function Logger(option) { // make the singleton pattern explicit if (!Logger.log) { Logger.log = this; } return Logger.log; }; ``` and then changed the initialization to take an options parameter ``` // initialize the logger Logger.prototype.init = function init(options) { log = new Bunyan({ name: options.name, streams : [ { stream : process.stdout, level : options.stdoutLevel}, { path : options.logfile, level : options.logfileLevel} ], serializers : Bunyan.stdSerializers }); }; ```

Original source

Related problems