I am writing a node.js application and using bunyan for logging. what i would like to do is to create one instance of the bunyan logger in the initialization of my app and from now on i want every module that will require the logger will get the same instance with the same configuration options.
// index.js var logger = require('./app/utils/logger'); var config = require('./app/config'); config.init().then(function(configData) { // create the logger instance once var log = logger({ name: 'appLogger' level: configData['log.level'], src: process.env.NODE_ENV === 'development', streams: [{ path: path.resolve(configData['log.file']), type: 'file' }] }); log.info('logger created'); }).catch(function(err) { console.log(err) });
now i want that every module in my app will get the same logger instance:
// foo.js var log = require('./app/utils/logger'); log.info('this should be logged in the file that was defined in index.js');
what is the recommended design pattern that i should implement in the logger module?
// logger.js var bunyan = require('bunyan'); // bunyan.createLogger(options) // what should be here?
Advertisement
Answer
You can have your logger act as both a constructor function as well as the logger singleton off of which to hang your info(), debug(), warn() and error() methods.
// logger.js var bunyan = require('bunyan'); // bunyan.createLogger(options) var name, level, src, streams; var logger = function(params){ name = params.name; level = params.level; src = params.src; streams = params.streams; logger.info = function(msg){ console.log("writing to " + streams.path); }; // logger.debug = ... return logger; }; module.exports = logger;
Notice how the info() and other methods aren’t created until you’ve actually called the logger function. The logger() function doesn’t actually create the singleton logger — it just creates the functions that hang off it.