1. 程式人生 > >Node.js日誌框架選型比較:Bunyan

Node.js日誌框架選型比較:Bunyan

npm 上下文環境 函數 -a ise -m 方式 情況 產生

前一篇Node.js日誌框架選型比較:Winston

Bunyan

Bunyan(by Trent Mick)是另外一個值得考慮的日誌框架,以稍微不同的方式處理結構化,機器可讀性被重點對待。

其結果是,bunyan每行日誌記錄實際上就是JSON.stringify的一個輸出。

安裝(Installation)
npm install bunyan
使用(Usage)
var bunyan= require(‘bunyan‘);
var log=bunyan.createLogger({name:‘myapp‘});
log.info(‘hi‘);
log.warn({lang:‘fr‘}, ‘au revoir‘);
輸出:
{"name":"myapp","hostname":"pwony-2","pid":12616,"level":30,"msg":"hi","time":"2014-05-26T17:58:32.835Z","v":0}
{"name":"myapp","hostname":"pwony-2","pid":12616,"level":40,"lang":"fr","msg":"au revoir","time":"2014-05-26T17:58:32.837Z","v":0}
你能夠看到Bunyan缺省情況下的日誌輸出對人而言可讀性不好,可是更加符合現代計算機的數據處理格式,在輸出到其它儲存時無需額外的格式化。
只是我們人類,這樣的格式的信息還是不方便閱讀,有一個bunyan命令行工具以標準命令行輸入方式處理JSON數據。以下是一個輸出經過bunyan管道處理後的樣例:
node example.js |bunyan
產生以下輸出:
[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)
這樣做的主要優點是不須要對開發環境進行又一次配置,僅僅要把輸出傳遞給bunyan管道處理就可以。
JSON
Bunyan和Winston之間一個關鍵的差別是Bunyan能夠處理復雜的上下文環境和對象。再看上面的樣例:
log.warn({lang: ‘fr‘},‘au revoir‘);
{"name":"myapp","hostname":"pwony-2","pid":12616,"level":40,"lang":"fr","msg":"au revoir","time":"2014-05-26T17:58:32.837Z","v":0}
你能夠看到bunyan把語言參數合並進了日誌結果。再看看以下這個:
log.info(user, ‘registered‘);
log.info({user:user},‘registered‘);
Which produces:
{"name":"myapp","hostname":"pwony-2","pid":14837,"level":30,"username":"alex","email":"[email protected]","msg":"registered","time":"2014-05-26T18:27:43.530Z","v":0}
{"name":"myapp","hostname":"pwony-2","pid":14912,"level":30,"user":{"username":"alex","email":"[email protected]"},"msg":"registered","time":"2014-05-26T18:28:19.874Z","v":0}
通過punyan管道處理後:
[2014-05-26T18:28:42.455Z] INFO: myapp/14943 on pwony-2: registered (username=alex,[email protected])
[2014-05-26T18:28:42.457Z] INFO: myapp/14943on pwony-2:registered
user:{
"username": "alex",
"email":"[email protected]"
}
當我們使用子日誌(Child Loggers)時,這樣的處理方式的美妙之處將表露無遺。
子日誌(Child Loggers)
Bunyan有一個子日誌的概念,這同意為你的應用程序的某個子組件指定日誌實例。

也即是。創建一個新的日誌實例使得能夠處理額外的字段。


子日誌通過log.child(...)方法創建。這為記錄系統、請求以及簡單函數這些不同作用域的組件日誌帶來極大的方便。
如果你想把請求ID記入該請求範圍內的全部日誌中,這樣你能夠把這些日誌關聯綁定在一起。


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:...});
});
req.log日誌實例將總是把它的上下文傳遞給log.child()函數並和全部興許調用合並,輸出例如以下:
{"name":"myapp","hostname":"pwony-2","pid":14837,"level":30,"reqId":"XXXX-XX-XXXX","user":"[email protected]","time":"2014-05-26T18:27:43.530Z","v":0}

序列化器(Serializers)
Bunyan在格式化整個對象時有兩個問題:
1循環引用(Circular references)。Winston在這裏更聰明些,會檢測發生的循環情況。
2多余的數據(Unwanted noises). 我認為在Bunyan中對象是第一位的。所以非常easy形成習慣把對象直接dump到日誌中。
為了處理這兩個問題,Bunyan有一個序列化器的概念,基本上就是一些轉換函數,把對象轉換為部分字段的輸出格式:
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});
這樣就僅僅記錄我們感興趣的請求的方法、url和頭部字段。


流(Streams)
Bunyan流的概念和Winston中的傳輸(transporters)概念一樣 – 發送您的日誌到一些地方用來顯示和存儲。
Bunyan使用具有一些額外屬性的可寫流接口。


一個Bunyan日誌記錄器實例擁有1個或多個指定流選項的流:
var log=bunyan.createLogger({
name: "foo",
streams:[
{
stream: process.stderr,
level: "debug"
},
...
]

});

怎樣選擇

Winston和Bunyan都是非常成熟的兩個框架,Winston有一個強大的社區支持,而Bunyan使得日誌的進一步系統分析處理非常方便。兩個系統怎樣選擇的關鍵因素是“是否能和你的應用系統方便的集成”

by iefreer - founder of techbrood.com

Node.js日誌框架選型比較:Bunyan