這多是外刊君推出的 Node.js 系列教程的第一篇。javascript
log4js 是 Node.js 日誌處理中的首屈一指的模塊。比起console
或者 TJ 的 debug 有其優點,尤爲針對投入生產的 Node.js 項目來講下面這些是不可少的:前端
本文將會給你一個 log4js 的全面介紹,讓你能夠在項目中得心應手的使用 log4js,開發調試容易,線上更好地監控或排查問題。java
下面這三行代碼爲你展現了 log4js 最簡單的用法:node
// file: simplest.js
var log4js = require('log4js');
var logger = log4js.getLogger();
logger.debug("Time:", new Date());複製代碼
調用 .getLogger()
能夠得到 log4js 的 Logger
實例,這個實例的用法與 console
是一致的,能夠調用.debug
(也有 .info
、.error
等方法)來輸出日誌。git
運行 node simplest.js
,輸出以下:github
$node simplest.js
[2016-08-21 00:01:24.852] [DEBUG] [default] - Time: 2016-08-20T16:01:24.852Z複製代碼
Time: 2016-08-20T16:01:24.852Z
是咱們想要輸出的內容,前面的包含說明符 [2016-08-21 00:01:24.852] [DEBUG] [default]
後文再表。express
使用起來是否是也很簡單,好了,在咱們深刻到 log4js 高級用法以前,咱們先來熟悉一下幾個 log4js 中的概念。數組
這個理解起來不難,就是日誌的分級。日誌有了分級,log4js 才能更好地爲咱們展現日誌(不一樣級別的日誌在控制檯中採用不一樣的顏色,好比 error
一般是紅色的),在生產能夠有選擇的落盤日誌,好比避免一些屬於.debug
才用的敏感信息被泄露出來。bash
log4js 的日誌分爲九個等級,各個級別的名字和權重以下:服務器
{
ALL: new Level(Number.MIN_VALUE, "ALL"),
TRACE: new Level(5000, "TRACE"),
DEBUG: new Level(10000, "DEBUG"),
INFO: new Level(20000, "INFO"),
WARN: new Level(30000, "WARN"),
ERROR: new Level(40000, "ERROR"),
FATAL: new Level(50000, "FATAL"),
MARK: new Level(9007199254740992, "MARK"), // 2^53
OFF: new Level(Number.MAX_VALUE, "OFF")
}複製代碼
上個圖:
ALL OFF
這兩個等級並不會直接在業務代碼中使用。剩下的七個即分別對應 Logger
實例的七個方法,.trace .debug .info ...
。也就是說,你在調用這些方法的時候,就至關於爲這些日誌定了級。所以,以前的 [2016-08-21 00:01:24.852] [DEBUG] [default] - Time: 2016-08-20T16:01:24.852Z
中的 DEBUG
既是這條日誌的級別。
log4js 還有一個概念就是 category(類型),你能夠設置一個 Logger
實例的類型,按照另一個維度來區分日誌:
// file: set-catetory.js
var log4js = require('log4js');
var logger = log4js.getLogger('example');
logger.debug("Time:", new Date());複製代碼
在經過 getLogger
獲取 Logger
實例時,惟一能夠傳的一個參數就是 loggerCategory(如 'example'
),經過這個參數來指定 Logger
實例屬於哪一個類別。這與 TJ 的 debug 是同樣的:
var debug = require('debug')('worker');
setInterval(function(){
debug('doing some work');
}, 1000);複製代碼
在 debug 中 'worker'
,一樣也是爲日誌分類。好了,回來運行 node set-catetory.js
:
[2016-08-21 01:16:00.212] [DEBUG] example - Time: 2016-08-20T17:16:00.212Z複製代碼
與以前的 [2016-08-21 00:01:24.852] [DEBUG] [default] - Time: 2016-08-20T16:01:24.852Z
惟一不一樣的地方就在於,[default]
變成了 example
。
那類別有什麼用呢,它比級別更爲靈活,爲日誌了提供了第二個區分的維度,例如,你能夠爲每一個文件設置不一樣的 category,好比在 set-catetory.js 中:
// file: set-catetory.js
var log4js = require('log4js');
var logger = log4js.getLogger('set-catetory.js');
logger.debug("Time:", new Date());複製代碼
就能夠從日誌 [2016-08-21 01:24:07.332] [DEBUG] set-catetory.js - Time: 2016-08-20T17:24:07.331Z
看出,這條日誌來自於 set-catetory.js
文件。又或者針對不一樣的 node package 使用不一樣的 category,這樣能夠區分日誌來源於哪一個模塊。
好了,如今日誌有了級別和類別,解決了日誌在入口處定級和分類問題,而在 log4js 中,日誌的出口問題(即日誌輸出到哪裏)就由 Appender 來解決。
下面是 log4js 內部默認的 appender 設置:
// log4js.js
defaultConfig = {
appenders: [{
type: "console"
}]
}複製代碼
能夠看到,在沒有對 log4js 進行任何配置的時候,默認將日誌都輸出到了控制檯。
咱們能夠經過log4js.configure
來設置咱們想要的 appender。
// file: custom-appender.js
var log4js = require('log4js');
log4js.configure({
appenders: [{
type: 'file',
filename: 'default.log'
}]
})
var logger = log4js.getLogger('custom-appender');
logger.debug("Time:", new Date());複製代碼
在上例中,咱們將日誌輸出到了文件中,運行代碼,log4js 在當前目錄建立了一個名爲 default.log
文件,[2016-08-21 08:43:21.272] [DEBUG] custom-appender - Time: 2016-08-21T00:43:21.272Z
輸出到了該文件中。
Console 和 File 都是 log4js 提供的 appender,除此以外還有:
default-2016-08-21.log
,明天輸出到 default-2016-08-22.log
;咱們能夠調整 appender 的配置,對日誌的級別和類別進行過濾:
// file: level-and-category.js
var log4js = require('log4js');
log4js.configure({
appenders: [{
type: 'logLevelFilter',
level: 'DEBUG',
category: 'category1',
appender: {
type: 'file',
filename: 'default.log'
}
}]
})
var logger1 = log4js.getLogger('category1');
var logger2 = log4js.getLogger('category2');
logger1.debug("Time:", new Date());
logger1.trace("Time:", new Date());
logger2.debug("Time:", new Date());複製代碼
運行,在 default.log
中增長了一條日誌:
[2016-08-21 10:08:21.630] [DEBUG] category1 - Time: 2016-08-21T02:08:21.629Z複製代碼
來看一下代碼:
logLevelFilter
和 level
來對日誌的級別進行過濾,全部權重大於或者等於DEBUG
的日誌將會輸出。這也是以前提到的日誌級別權重的意義;category
來選擇要輸出日誌的類別,category2
下面的日誌被過濾掉了,該配置也接受一個數組,例如 ['category1', 'category2']
,這樣配置兩個類別的日誌都將輸出到文件中。Layout 是 log4js 提供的高級功能,經過 layout 咱們能夠自定義每一條輸出日誌的格式。log4js 內置了四中類型的格式:
一個 pattern
的例子:
// file: layout-pattern.js
var log4js = require('log4js');
log4js.configure({
appenders: [{
type: 'console',
layout: {
type: 'pattern',
pattern: '[%r] [%[%5.5p%]] - %m%n'
}
}]
})
var logger = log4js.getLogger('layout-pattern');
logger.debug("Time:", new Date());複製代碼
%r %p $m $n
是 log4js 內置的包含說明符,能夠藉此來輸出一些 meta 的信息,更多細節,能夠參考 log4js 的文檔。
一張圖再來講明一下,Logger、Appender 和 Layout 的定位。
爲了方便查問題,在生產環境中每每會記錄應用請求進出的日誌。那使用 log4js 怎麼實現呢,直接上代碼:
// file: server.js
var log4js = require('log4js');
var express = require('express');
log4js.configure({
appenders: [{
type: 'DateFile',
filename: 'access.log',
pattern: '-yyyy-MM-dd.log',
alwaysIncludePattern: true,
category: 'access'
}]
});
var app = express();
app.use(log4js.connectLogger(log4js.getLogger('access'), { level: log4js.levels.INFO }));
app.get('/', function(req,res) {
res.send('前端外刊評論');
});
app.listen(5000);複製代碼
看看咱們作了哪些事情:
access
的日誌,輸出到一個滾動的文件中;log4js.getLogger('access')
獲取一個類別爲 access
的 Logger 實例,傳遞給 log4js.connectLogger
中間件,這個中間件收集訪問信息,經過這個實例打出。啓動服務器,訪問 http://localhost:5000,你會發現目錄中多了一個名爲 access.log-2016-08-21.log
的文件,裏面有兩條日誌:
[2016-08-21 14:34:04.752] [INFO] access - ::1 - - "GET / HTTP/1.1" 200 18 "" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36"
[2016-08-21 14:34:05.002] [INFO] access - ::1 - - "GET /favicon.ico HTTP/1.1" 404 24 "http://localhost:5000/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36"複製代碼
經過 log4js 日誌的分類和appender功能,咱們把訪問日誌輸出到了一個滾動更新的文件之中。
本文爲你們全面地介紹了 log4js 的用法,與 console
或者簡單的日誌工具相比,log4js 使用起來更復雜,固然功能更強大,適合生產級應用的使用。若是你們有興趣的話,請留言告訴外刊君,接下來可能爲你們介紹如何在 Node 應用中作配置管理。