Node.js Log Frame selection comparison: Winston
Bunyan
Bunyan (by Trent Mick) is another log framework worth considering, with a slightly different approach to structuring, machine readability being treated with emphasis.
As a result, Bunyan per row of log records is actually an output of json.stringify.installation (Installation)NPM Install Bunyan
use (Usage)var bunyan= require (' Bunyan ');
var Log=bunyan.createlogger ({name: ' MyApp '});
Log.info (' Hi ');
Log.warn ({lang: ' fr '}, ' Au revoir ');
Output:
{"Name": "MyApp", "hostname": "Pwony-2", "pid": 12616, "Level": "The msg": "Hi", "Time": "2014-05-26t17:58:32.835z", "V": 0 }
{"Name": "MyApp", "hostname": "Pwony-2", "pid": 12616, "level": "Lang": "Fr", "msg": "Au revoir", "Time": "2014-05-26t17 : 58:32.837z ", V": 0}
You can see that the log output by default is Bunyan to people, but it is more compatible with the data processing format of modern computers and eliminates the need for additional formatting when outputting to other stores.
But we humans, the information in this format is still inconvenient to read, and there is a Bunyan command-line tool to handle JSON data in a standard command-line input mode. Here is an example of an output after Bunyan pipeline processing:
Node Example.js |bunyan
Produces the following output:
[2014-05-26T18:03:40.820Z] info:myapp/13372 on pwony-2: Hi
[2014-05-26t18:03:40.824z] Warn:myapp/13372on Pwony-2:au Revoir (LANG=FR)
The main benefit of this is that the development environment does not need to be reconfigured, as long as the output is passed to the Bunyan pipeline processing.
JSONA key difference between Bunyan and Winston is that Bunyan can handle complex context environments and objects. And look at the example above:
Log.warn ({lang: ' fr '}, ' Au revoir ');
{"Name": "MyApp", "hostname": "Pwony-2", "pid": 12616, "level": "Lang": "Fr", "msg": "Au revoir", "Time": "2014-05-26t17 : 58:32.837z ", V": 0}
You can see that Bunyan has merged the language parameters into the log results. And look at this:
Log.info (user, ' registered ');
Log.info ({user:user}, ' registered ');
Which produces:
{"Name": "MyApp", "hostname": "Pwony-2", "pid": 14837, "level": "username": "Alex", "email": "... @gmail. com", "MSG": " Registered "," Time ":" 2014-05-26t18:27:43.530z "," V ": 0}
{"Name": "MyApp", "hostname": "Pwony-2", "pid": 14912, "level": "User": {"username": "Alex", "email": "... @gmail. com"} , "MSG": "Registered", "Time": "2014-05-26t18:28:19.874z", "V": 0}
After processing through the Punyan pipeline:
[2014-05-26t18:28:42.455z] info:myapp/14943 on Pwony-2: Registered (username=alex,email= ... @gmail. com)
[2014-05-26t18:28:42.457z] Info:myapp/14943on pwony-2:registered
user:{
"username": "Alex",
"Email": "@gmail. com"
}
The beauty of this approach is evident when we use the loggers (child).
Sub-log (child loggers)Bunyan has a concept of a sub log, which allows you to specify a log instance for a child component of your application. In other words, creating a new log instance allows you to process additional fields.
Sub-log through Log.child (...) Method is created. This provides a great convenience for recording system, request, and component logs for different scopes of simple functions.
Suppose you want to put the request ID in all the logs in the scope of the request so that you can bind the log associations together.
varbunyan= require (' Bunyan ');
var log = Bunyan.createlogger ({name: ' MyApp '});
App.use (function (req, res,next) {
Req.log=log.child ({reqid:uuid ()});
Next ();
});
App.get ('/', function (req, res) {
Req.log.info ({User: ...});
});
The Req.log log instance will always pass its context to the Log.child () function and merge with all subsequent calls, and the output is as follows:
{"Name": "MyApp", "hostname": "Pwony-2", "pid": 14837, "level": "Reqid": "Xxxx-xx-xxxx", "User": "... @gmail. com", " Time ":" 2014-05-26t18:27:43.530z "," V ": 0}
Serializer (serializers)Bunyan has two problems formatting the entire object:
1 circular Reference (circular references). Winston is smarter here and will detect the recurrence.
2 Redundant data (unwanted noises). I think the object is the first in the Bunyan, so it is easy to form a habit of dump the object directly into the log.
To deal with these two problems, Bunyan has the concept of a serializer, which is essentially a transformation function that converts an object to a partial field's output format:
function Reqserializer (req) {
return{
Method:req.method,
Url:req.url,
Headers:req.headers
}
}
var log = Bunyan.createlogger ({name: ' MyApp ', Serializers:{req:reqserializer}});
Log.info ({req:req});
This will only record the method, URL, and header fields of the request that we are interested in.
Stream (Streams)The concept of Bunyan flow is the same as the transport (transporters) concept in Winston – sending your logs to some places to display and store.
Bunyan uses a writable flow interface with some additional attributes.
A Bunyan logger instance has one or more streams that specify the flow options:
var Log=bunyan.createlogger ({
Name: "Foo",
streams:[
{
Stream:process.stderr,
Level: "Debug"
},
...
]
}); How to choose Winston and Bunyan are very mature two frameworks, Winston have a strong community support, and Bunyan makes the further system analysis of the log very convenient. The key factor in how the two systems are chosen is "can be easily integrated with your application system".
by Iefreer-founder of techbrood.com