本文主要梳理了目前我們團隊在nodejs開發中日誌方面存在的問題,以及通過統一日誌規範,希望達到什麼樣的效果。
只使用fatal
、error
、warn
、info
和debug
等級。
fatal - 導致程式退出的嚴重系統級錯誤,不可恢復,當錯誤發生時,系統管理員需要立即介入,一般應用**不使用。日誌格式統一採用json,便於error - 執行時異常以及預期之外的錯誤,也需要立即處理,但緊急程度低於fatal,當錯誤發生時,影響了程式的正確執行。需要注意的是這兩種級別屬於服務自己的錯誤,需要管理員介入,使用者輸入出錯不屬於此分類,請求後端、讀檔案、資料庫等超時、返回錯誤結構,屬於error
warn - 預期之外的執行時狀況,表示系統可能出現問題。對於那些目前還不是錯誤,然而不及時處理也會變成錯誤的情況,也可以記為warn,如磁碟過低。
info - 有意義的事件資訊,記錄程式正常的執行狀態,比如收到請求,成功執行。通過檢視info,可以快速定位warn,error, fatal。info不宜過多,通常情況下不超過 debug 的10%。
debug - 與程式執行時的流程相關的詳細資訊以及當前變數狀態。
elk
解析處理。
日誌中的各個欄位的值,都應該盡量使用英文,不使用中文。
日誌具體字段,分為 基礎資料 + 擴充套件資料。基礎資料,是底層日誌框架自帶的,所有日誌都會包含。擴充套件資料,不同型別的日誌,包含不同的字段。
目前使用的node-bunyan
日誌庫,官方文件,基礎字段包含如下:
下面定義的各個資料型別的擴充套件資料,不是全部的字段,僅包含該日誌型別下,必需的字段。這些必需的擴充套件字段,需要在elk
中建立索引,方便定位各種問題。
desc
型別日誌,擴充套件字段:todo
stat
型別日誌,擴充套件字段:}
visit
型別日誌,擴充套件字段:
biz
,
//本次node請求的處理時間,毫秒
tm: 500,
//該日誌相關的上下文資料,盡量拼成乙個字串,放在 extra 裡
extra: "",
//error 級別日誌,最好包含error相關資訊,比如請求後端相關引數等
err: ,
//呼叫後端服務相關引數和響應
service_req: ,
service_res:
}
開發者目前只關心visit
型別的日誌,即和某一次http請求相關聯的日誌。desc
和stat
型別的日誌,統一由開發框架封裝後實現,業務開發不用關心。下面講的,都是針對visit
型別的日誌。
一次http請求,會打出一系列相關聯的日誌。在node層,通常一次請求,會進一步**給n個後端服務,然後對後端資料進行一些處理、合併等操作,最後渲染頁面或是輸出json。因此,一次請求相關的日誌,大體分為以下幾種event
:
開發同學在打日誌時,應該謹慎的選擇級別,info
(含)級別以上,都應該能對定位問題、具體業務統計需求有要求,才能使用。大部分情況下,可以使用debug
級別,線上不會開啟debug
級別。
針對列印visit
型別的日誌,呼叫ctx.logger
(基於koa
的框架) 屬性打日誌,推薦引數都傳遞json
,具體方法如下:
ctx.logger.debug();
ctx.logger.info();
ctx.logger.warn();
//error級別日誌,應該提供 error 物件
ctx.logger.error();
注意1,額外的引數,推薦存放在extra
欄位中,統一拼成string
;如果確實有必要單獨出每個字段,禁止額外的引數占用上述通用欄位名!!
注意2,基礎資料中的msg
字段,禁止包含具體的上下文資料,和該日誌相關的上下文資料,應該拼成字串,放在單獨的extra
欄位中。比如,某個使用者登入介面,希望統計呼叫次數,可以這樣列印:
ctx.logger.info();
實現簡單的字段變更記錄
原理 在實體類變更前對其進行備份,呼叫newtonsoft.json下的序列化方法將其儲存成json格式,並在需要時呼叫反序列化方法,轉化成實體類 public static class testentitychange 將json格式的資料轉化成相應的實體 public static t gete...
轉存Druid監控記錄到日誌檔案
druid的監控記錄在是快取的,重啟之後無法找回,所以需要做持久化,定期把監控記錄轉存到日誌檔案中,實現步驟如下 1 datasource中增加配置 property name timebetweenlogstatsmillis value 600000 property name statlogg...
使用redis將日誌記錄到日誌伺服器
在web伺服器上 using servicestack.redis using system using system.collections.generic using system.linq using system.web using system.web.mvc namespace czbk...