I’ve already pushed intel 0.2 out the door, after a week of tweaking and massaging it into Persona repos. Here’s the changelog, explanation after:
- [new] Filters
- [new] Handler timeout option
- [new] pid included in LogRecord
- [new] use JSON with intel.config()
- [changed] Promises are now LazyPromises
- [changed] printf is now a small, internal, much faster implementation
- [removed] node v0.6 support
There was already a fair amount of filtering possible in v0.1, by combining log levels and named loggers. However, it became apparent that you’d want to also be able to filter messages on arbitrary details, and there wasn’t a super easy way to do that. Now you can. Here’s an example filter:
This filter means that the handler will only receive messages that include the string “user” in the message text.
config with JSON
class property of Handlers and Filters accepts a String, which will be used to
require the class. Intel’s handlers are available like this:
I set up some benchmarks to see just much power intel sucks up, and then cried a little. Clearly, comparing speed to the basic
console.log was an exercise meant for trolls, but I also compared against winston. Removing some Array.forEachs, using a light-weight printf, and using LazyPromises made intel faster than winston (woot!).
Specifically, Promises were the biggest slow down. They’re awesome control structures, but boy are they slow. Since most people won’t ever want them anyways, it would suck if everyone had to pay their compute cost. So, log methods now return a proxy with a getter for
then is accessed the first time, the Promises are constructed, and handed to the caller. You only pay the cost on the few times you really want their convenience.
As always, file bugs or feature requests at the issuer tracker. I’m still aiming to be able to call intel at v1.0 soon, so any feedback will help shape this into an excellent go-to logging library.
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.