Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best practice to let users inject a logger into nodejs modules

I wrote this module for nodejs that can be used to dispatch events from anywhere via sockjs to the clients.

Now I'd like to include some configurable logging mechanisms.

At the moment, I'm adding winston as a dependency, require it as a logger in each class and use logger.error, logger.warn, ...

#logger.js
var logger = require('winston');
module.exports=logger;

and

#myClass
var logger = require("./logger");
logger.error("Something went wrong")

Now, how can I make the logger be replaceable by a custom logger or have the user configure the log level from OUTSIDE my module?

They should of course not have to touch the module code to change the logger but be able to create the logger with loglevel and my module should use it, if available.

Any receommendations on how to do that?

Or is a hard dependency on "winston" ok and have the log level be configurable via npm-config?

like image 349
Xosofox Avatar asked Mar 11 '14 20:03

Xosofox


1 Answers

Well I suggest to not include Winston at all. Winston is kinda huge and contains a lot of nice features that your users might not use, and I believe that your module should be small enough that the user will always use all it's features. If there's a case that they don't wanna use the built-in logger, well it's not small enough I guess. With that said, a module logging stuff when needed for debugging is helpful.

If you wanna have way for the developer using your module to debug your module with logs, then I suggest you to have a debug mode that can be turned on/off.

You could use something like this to help you: https://www.npmjs.org/package/debug

And if the user wants to integrate their own logging system, I suggest you to have a way that they could pass your module a logging function. Something like this(let's call your module rock-the-sock:

var rockTheSock = require('rock-the-sock');
var rockTheSock.logger = function (level, message, metadata) {
    console.log('level :', level, message, metadata); // TODO: Integrate winston
};
rockTheSock.startRocking();

And then in your module you would have a default logger, which can overriden as shown above.

socket.io is a nice example of how it's done(though you don't really need the configure method, that's just bells and whistles):

Here's how you would override socket.io default logger: https://github.com/LearnBoost/Socket.IO/wiki/Configuring-Socket.IO

Where as the logger is implemented this way: https://github.com/LearnBoost/Socket.IO/blob/0.9.14/lib/logger.js

And if ever something goes wrong, try to throw the error, or emit an 'error' event or call the callback with the error(do whichever applicable). Silently logging it, is not a good idea. If you are reporting it, then let the user code handle it. Maybe the error was expected(you have no idea in what crazy ways people use your modules!).

like image 80
Farid Nouri Neshat Avatar answered Oct 11 '22 07:10

Farid Nouri Neshat