morgan是express預設的日志中間件,也可以脫離express,作為node.js的日志元件單獨使用。本文由淺入深,内容主要包括:
morgan使用入門例子
如何将日志儲存到本地檔案
核心api使用說明及例子
進階使用:1、日志分割 2、将日志寫入資料庫
源碼剖析:morgan的日志格式以及預編譯
首先,初始化項目。
然後,在<code>basic.js</code>中添加如下代碼。
morgan支援stream配置項,可以通過它來實作将日志落地的效果,代碼如下:
morgan的api非常少,使用頻率最高的就是<code>morgan()</code>,作用是傳回一個express日志中間件。
參數說明如下:
options:可選,配置項,包含<code>stream(常用)</code>、<code>skip</code>、<code>immediate</code>。
stream:日志的輸出流配置,預設是<code>process.stdout</code>。
immediate:布爾值,預設是false。當為true時,一收到請求,就記錄日志;如果為false,則在請求傳回後,再記錄日志。
首先搞清楚morgan中的兩個概念:format 跟 token。非常簡單:
format:日志格式,本質是代表日志格式的字元串,比如 <code>:method :url :status :res[content-length] - :response-time ms</code>。
token:format的組成部分,比如上面的<code>:method</code>、<code>:url</code>即使所謂的token。
搞清楚format、token的差別後,就可以看下morgan中,關于自定義日志格式的關鍵api。
非常簡單,首先通過<code>morgan.format()</code>定義名為<code>joke</code>的日志格式,然後通過<code>morgan('joke')</code>調用即可。
我們來看下運作結果
代碼如下,通過<code>morgan.token()</code>自定義token,然後将自定義的token,加入自定義的format中即可。
一個線上應用,如果所有的日志都落地到同一個本地檔案,時間久了,檔案會變得非常大,既影響性能,又不便于檢視。這時候,就需要用到日志分割了。
借助<code>file-stream-rotator</code>插件,可以輕松完成日志分割的工作。除了<code>file-stream-rotator</code>相關的配置代碼,其餘跟之前的例子差不多,這裡不贅述。
有的時候,我們會有這樣的需求,将通路日志寫入資料庫。這種需求常見于需要實時查詢統計的日志系統。
在morgan裡該如何實作呢?從文檔上,并沒有看到适合的擴充接口。于是查閱了下<code>morgan</code>的源碼,發現實作起來非常簡單。
回顧下之前日志寫入本地檔案的例子,最關鍵的兩行代碼如下。通過<code>stream</code>指定日志的輸出流。
在<code>morgan</code>内部,大緻實作是這樣的(簡化後)。
于是,可以用比較取巧的方式來實作目的:聲明一個帶<code>write</code>方法的對象,并作為<code>stream</code>配置傳入。
morgan的代碼非常簡潔,從設計上來說,morgan的生命周期包含:
token定義 --> 日志格式定義 -> 日志格式預編譯 --> 請求達到/傳回 --> 寫日志
其中,token定義、日志格式定義前面已經講到,這裡就隻講下 日志格式預編譯 的細節。
跟模闆引擎預編譯一樣,日志格式預編譯,也是為了提升性能。源碼如下,最關鍵的代碼就是<code>compile(fmt)</code>。
<code>compile()</code>方法的實作細節這裡不贅述,着重看下<code>compile(fmt)</code>傳回的内容:
運作上面程式,輸出内容如下,其中<code>tokens</code>其實就是<code>morgan</code>。
看下<code>morgan.token()</code>的定義,就很清晰了