I write Node.js libraries, and I want logging. Why is this so problematic?
Note, I am despairing about how library authors log stuff not how application builders decide on a logging framework.
Hopefully this document can become a spec or feature list for code I will write some day.
I maintain package foo
and I depend on log4js. Bob maintains package bar
and depends on winston. Charlie maintains package baz
and depends on minilog.
My downstream user writes an application which depends on foo
, baz
, and bar
plus npmlog.
This is crazy. The result, in the best case is a tedious application. How can the developer activate debug logging across the board? It's bedlam! In practice Bob, Charlie, and I get many bug reports about something which should be invisible yet ubiquitious, like air.
My half feature list / half whining list:
- I must not depend on some package
- The whole anti-pattern is too many logging cooks. I am deeply skeptical that another package will help.
- I want a technique or a custom, not a package. At least not yet.
- I want to document how I work and my user can hook me into their own logger. That's fine for now.
- I want the
console.*
API.info()
,.warn()
and.error()
. That's fine.- This includes
util.format()
support. I love Winston's structured logs bututil.format()
is more compatible with the world.
- I want to be silent by default. Principle of least surprise.
- It should be pretty easy for my user to get at my logs.
- Maybe I emit a
"console"
event and my user can replace my.info()
,.warn()
, etc. functions? - Maybe I have a
.console()
function and my user just runsfoo.console(console);
to get my output on the screen
- Maybe I emit a
Perhaps in the future, but not yet
- Command-line or environment variables to trivially enable/disable my log visibility, severity cut-off, etc.
- The well-known concept of a log "namespace". My user can hook into
"networking"
logs but ignore"caching"
logs. - Optimized execution in the case where a log message will go nowhere
- Some good solution to the missing
console.debug()
. From bitter experience, I now insist on being 100%console.*
compatible. But there is no debugging level! I will probably just use.trace()
and die a little bit inside. - Be easy to hook into me into logging frameworks (Winston, log4js, npmlog, whatever else)
I think the solution is for libs to emit "log" events, which you can then decide to either print or ignore or send to a db or whatever. I've been planning to eventually make npmlog work this way by default, and only actually print stuff if you set a loglevel on it explicitly.
Then I could easily do something like:
where "level" is one of
['error', 'warn', 'info', 'debug']
or something.Of course, then it's up to all of us in the node logging universe to conform to this API. I'd certainly be happy to accept pull reqs to make npmlog conform to something like this. I'm not too attached to the specifics of the API.
It's worth noting that all the popular loggers seem to have some concept of "levels" which is super handy. It's great to do stuff like
log.warn()
orlog.info()
and then at run-time be able to turn the dial up or down.