node package manager
Share your code. npm Orgs help your team discover, share, and reuse code. Create a free org »



Hierarchical logger system for winston with configurable data flows, inspired by Python logging facility.



First, you instantiate the LeoWinston container object: the service object which allows you to access all loggers you create with it.

var LeoWinston = require('leo-winston').LeoWinston;
var leo = new LeoWinston({
    levels: { silly: 0, debug: 1, verbose: 2, info: 3, warn: 4, error: 5 },
    decorate: true,
    propagate: true

The following LeoWinston container options are available:

  • levels: Log levels to use for all loggers. Default: uses winston's npm levels;

  • decorate: Boolean: Whether to decorate each message with the logger name. Default: true

  • propagate: Boolean: Use log messages propagation?

    When propagation is enabled, messages bubble up to parent loggers

    When a message is logged with the 'a.b.c.d' logger, it will propagate to loggers 'a.b.c', 'a.b', 'a', and finally, 'root'.

Define loggers

You define loggers with the following method:

LeoWinston.add(name, options):Logger

  • name: String: The name of the logger to add.

    In order to use propagation, use '.'-notation to qualify logger names.

  • options: Object?: Logger options object:

    • propagate: Boolean: Whether messages from this logger propagate further. Default: true

      When a logger is created with propagate: false, it will consume the messages without passing them on.

    • transports: Object: Winston transports configuration. See: Working with transports.

It's required that you have a single logger named 'root': this topmost logger catches messages from all registered loggers (unless they explicitly define propagation: false).

leo.add('root', {
    transports: {
        console: { level: 'silly', silent: false, colorize: true, timestamp: true }
leo.add('http', { // will pass the messages on to 'root' 
    transports: {
        file: { // log HTTP requests to a file 
            level: 'silly', silent: false, colorize: false, timestamp: true,
            filename: '/tmp/tmp/root.log', json: false
leo.add('http.users', {}); // no logging, just propagate for now 
leo.add('http.requests', {
    propagate: false, // don't propagate 
    transports: { // log to console 
        console: { level: 'silly', silent: false, colorize: true }

It's wise to keep logger options in a config file: this way you'll have flexible app configurations.


After you've configured your loggers, use the following method to get a logger:


If the logger was not defined, it's created as a no-op logger. When propagation is enabled, its messages propagate to the 'root' logger.

Wielding a logger, use it like a normal Winston logger:

var logger = leo.get('http.users');
logger.log('info', 'message'); // (level, message[, meta][, callback]) 
// Each log level gets a corresponding method 

Propagation Concepts

  1. When anything is logged to logger 'A.B.C.D', the message propagates up to loggers 'A.B.C', 'A.B', 'A' and 'root'
  2. If any of the intermediate loggers does not exist - no problem: the message proceeds going up through the chain
  3. If any logger is configured with propagation: false, the message propagation stops on it.


Handling Uncaught Exceptions

// Assuming your 'root' logger is configured correctly 
process.on('uncaughtException', function (err) {
    leo.get('error').error(err + "\n" + err.stack);