Metalogger is a versatile logging library for Node.js that provides following features:
- Granular, Linux Syslog-compatible logging levels.
- Pluggable logging infrastructure (implemented: winston, ain2 (syslog), npmlog, log.js, util-based logging, loggly, sumologic).
- Timestamps for all log messages
- Filename and line-numbers for all log messages!
- Granular logging control: alter global logging threshhold for specific files.
- 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.
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:
- No logging in the released code (typically what you see in most modules, currently)
- Logging using the most simplistic tools that don't support varying logging levels
- 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.
> 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
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);
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:
-
plugin
: short name of the implemented logging plugin. Current implementations include: ('ain2', 'util', 'npmlog', 'log', 'loggly', 'sumologic'). If you skip this value or passnull
, it will default to the value of the environmental variable NODE_LOGGER_PLUGINFull current list can be checked, at runtime, by issuing:
log.loggers();
-
level
: name of the default threshold logging level. If you skip this value or passnull
, it will default to the value of the environmental variable NODE_LOGGER_LEVELCurrent 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
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.
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.
In the simple syntax, you can just pass some message (or a javascript object, which will be properly expanded/serialized):
log.info(message);
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);
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
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.
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.
You can control syslog configuration for AIN2 using the following environmental variables:
NODE_LOGGER_SYSLOG_FACILITY
NODE_LOGGER_SYSLOG_APPNAME