A couple months ago, I was blagging on about logging libraries in nodejs. After pointing out how annoying it is to use logging libraries with 3rd party modules, I declared that all modules should simply use
console.log(), and let applications hijack the console. Then, I looked around the npms, and couldn’t find an excellent example of a logging library that embraced that idea.
So, clearly, that meant I needed to write my own. It’s called intel. Why another logging library? Well duh, cause this one is better.
Loggers get names
Before nodejs, I came from Pythonia. Over yonder, they have an excellent logging module as part of the standard library. It’s glorious. It uses hierarchal named loggers. Winston, the library we currently use in Persona, while being perfectly awesome, doesn’t have support for this. It does allow you to define Containers and Categories, but it’s not as powerful as I’d like.
Specifically, intel adds 2 noteworthy features to Loggers: hierarchy and humane setup.
Loggers use an hierarchy based on their names. Logger
foo.baris a child of
foo. So is
foo.bar.baz. When a logger receives a log message, after handling itself, it passes the message up to its parents.
For instance, you could decide that all log messages from
fooshould go to the terminal. However, your
foo/bar.jsmodule has some critical code you want to keep tabs on. You could add a handler to the
foo.barlogger that sends all messages of
WARNand greater to email. After that handler,
foo.barwill hand the message to its parent
foo, and also send it to the terminal
Of the other libraries I could fine that supported multiple named loggers, they all required that you instantiate the loggers with all options ahead of time. This adds more friction having a named logger per module in your app. Instead, intel makes it super easy for you get a new named logger.
var logger = intel.getLogger('foo.bar.baz.quux');
You don’t have to have added any handlers to your newly minted logger. It will just pass the messages right up to it’s parents. The messages will still keep the name of the originating logger, though.
Named loggers allow for really powerful yet easy-to-use logging. Combined with a little bit of configuration, and it’s all magical. You can setup a couple root loggers, with various levels pumping messages to various handlers (Console, File, Email, Database, etc). You can see an example in the docs.
Infiltrating the console
The motivating reason I started intel was to do exactly this. I want my apps to have the power to configure logging just the way I want, and I want all my dependencies to play along with my logging rules. So, after you setup your loggers and handlers, you can inject intel into the global
console object, and watch as any dependencies that use
console.log follow your rules, and automatically get assigned the correct names.
intel.console(); intel.getLogger('patrol.node_modules.express').setLevel(intel.WARN); // in express.js console.log('new request'); // automatically gets assigned to patrol.node_modules.express logger.
I’m starting by a 0.1 release of intel. Any bugs or feature requests can filed in the issue tracker. I don’t want intel to be one of those libraries that is forever sub-1.0. After some use in the wild, with bugs being fixed and possibly APIs being made better, I’d like to get to a 1.0 soon.
So, try swapping out your current logger for intel. Name some loggers. You’ll come around.