/metalogger

Node.js logging for grown-ups: a versatile logging wrapper that leaves you the choice, but removes the pain. Inspired by Apache Commons Logging

Primary LanguageJavaScriptMIT LicenseMIT

Build Status NPM Version

What is MetaLogger?

Metalogger is a versatile logging library for Node.js that provides following features:

  1. Granular, Linux Syslog-compatible logging levels.
  2. Pluggable logging infrastructure (implemented: winston, ain2 (syslog), npmlog, log.js, util-based logging, loggly, sumologic).
  3. Timestamps for all log messages
  4. Filename and line-numbers for all log messages!
  5. Granular logging control: alter global logging threshhold for specific files.
  6. Application-development-friendly configuration

If you already use Winston and think you don't need Metalogger, you should know that Metalogger can use Winston as a transport layer, and still provide all the additional great features on top of it.

Why Should You Use it?

Well, being able to see the filename and line number where logs were fired is awesome! But also:

TL;DR: NodejsReactions Animated Gif

If you are familiar with Apache Commons Logging then you know why Node.js needs Metalogger, if not: keep reading.

Node.js is famous for its modular architecture. However, every module developer can have his or her own preference to which logging library they prefer to use. This can lead to one of the following non-ideal scenarios:

  1. No logging in the released code (typically what you see in most modules, currently)
  2. Logging using the most simplistic tools that don't support varying logging levels
  3. Chaos, when each module does extensive logging, but using completely differing libraries.

Other platforms have solved the problem of logging in elegant ways. Metalogger is an attempt to integrate that experience into Node.js and achieve seamless logging experience.

The metalogger module is a very lightweight bridge/wrapper for a number of popular logging implementations:

Usage of Metalogger is not limited to just standalone modules. Full-blown Node applications will also benefit from using Metalogger to ensure that a switch-over to a different logging implementation won't be a hassle, if and when needed.

Installation and Initialization

Install:

> npm install metalogger

The util logging bridge relies on the built-in node util; for any other logging type, you must install the underlying logger manually. Metalogger does not require these unless you specify them.

> npm install --save ain2
# or
> npm install --save loggly
# etc

Using with Winston:

Make sure NODE_LOGGER_PLUGIN environmental variable is set to winston.

// with built-in winston config:
var log = require('metalogger')();
log.error("user:", user);

// Using pre-configured winston config:
var winstonLogger = new winston.Logger ({ transports: options.transports });
var log = require('metalogger')(null, null, winstonLogger);
log.error("request:", request);

Initialization:

var log = require('metalogger')(); // preferred. Read further.
// or if you need more verbose syntax:
var log = require('metalogger')(plugin, level);

Where the arguments of the initialization are:

  1. plugin: short name of the implemented logging plugin. Current implementations include: ('ain2', 'util', 'npmlog', 'log', 'loggly', 'sumologic'). If you skip this value or pass null, it will default to the value of the environmental variable NODE_LOGGER_PLUGIN

    Full current list can be checked, at runtime, by issuing:

      log.loggers();
  2. level: name of the default threshold logging level. If you skip this value or pass null, it will default to the value of the environmental variable NODE_LOGGER_LEVEL

    Current list of allowed level names can be retrieved by issuing:

      log.levels();
    

    As of this writing the list of the supported levels mirrors that of syslog (and log.js) and is as follows (in decreasing criticality):

  • emergency system is unusable
  • alert action must be taken immediately
  • critical the system is in critical condition
  • error error condition
  • warning warning condition
  • notice a normal but significant condition
  • info a purely informational message
  • debug messages to debug an application

Filename and Line Number Display

For increased debugging comfort Metalogger automatically displays the filename and line number where a log message is fired at. This is typically very handy in development. If you wish to disable this in production, however set the environment variable NODE_LOGGER_SHOWLINES to 0 or any value that is not 1.

Usage

The great value of metalogger is in unifying (to the level that it makes sense) the usage of various loggers. Even though the first three implemented loggers (util, npmlog, log) are quite different, metalogger manages to bridge these differences.

As a best practice, you shouldn't set plugin and/or level values when initializing metalogger from your re-usable modules. If not set, these values will default to NODE_LOGGER_PLUGIN and NODE_LOGGER_LEVEL environmental variables, allowing the main application to control desired logging universally.

Initialize metalogger, in your modules, as follows:

  var log = require('metalogger')();

after which you can use one of the following syntaxes, regardless of the underlying logging plugin.

Simple Syntax:

In the simple syntax, you can just pass some message (or a javascript object, which will be properly expanded/serialized):

log.info(message);

Using a caption:

Captioned syntax is very useful for debugging object. You can provide the title for the object in caption and pass your Javascript object as the second argument. Metalogger will automatically expend the object for you and display it as a JSON representation.

log.debug("User object:", user);

Advanced Syntax

In the advanced syntax, you can use caption (first argument), format (second argument) and unlimited number of value-arguments to construct a complex expressions:

log.debug("Caption: ", "Formatted sequence is string: %s, number: %d, number2: %d", somestring, somenumber, othernumber);

the format syntax follows the semantics of util.format

Granular Logging

Global logging level can be overriden on a per-file basis. This can be extremely useful when you are debugging or developing a specific module and want to use granular logging for it, but want to turn off the noise from the rest of the modules.

To override global logging level for a specific file, you set an environment variable as follows:

Let's assume you would like to turn logging level to 'debug' for a file: `lib/models/user.js', you set an environmental variable as follows (example for Linux):

export NODE_LOGGER_LEVEL_lib_models_user_js='debug'

Please note that since Linux shell doesn't allow dots or slashes in a variable name, you have to replace those with underscores.

Path to file must be indicated from the current folder of the node process.

Production Configuration

Suggested production configuration for Metalogger is as follows:

export NODE_LOGGER_LEVEL='notice'
export NODE_LOGGER_GRANULARLEVELS=0

which will set default logging level at notice, and turn off granular level processing for better performance.

If you are really concerned about performance you can also turn off 'show lines` feaure with:

export NODE_LOGGER_SHOWLINES=0

it is typically not necessary however, since unless you're logging a lot, the overhead of showing filelines in the log is not high (typically: small fraction of a millisecond) and in most cases it could be quite useful to be able to see where error logs occured even in production, for debugging purposes.

Syslog Configuration

You can control syslog configuration for AIN2 using the following environmental variables:

  • NODE_LOGGER_SYSLOG_FACILITY
  • NODE_LOGGER_SYSLOG_APPNAME