最近在考慮后端日志規范擬定,參考了一些別的同志的經驗,加上自己的一些思考,初步整理如下。
一、日志規范
1. 日志嚴格分級
-
DEBUG:該級別日志的主要作用是對系統每一步的運行狀態進行精確的記錄。可以將各類詳細信息記錄到DEBUG里,起到調試的作用,包括
參數信息、調試細節信息、返回值信息
等。 -
INFO:該種日志記錄系統的正常運行狀態,通過查看INFO級別的日志,可以很快地對系統中出現的 WARN,ERROR,FATAL錯誤進行定位。可以將
初始化系統配置、業務狀態變化信息
,或者用戶業務流程中的核心處理記錄
到INFO日志中,方便日常運維工作以及錯誤回溯時上下文場景復現。 -
WARN:該日志表示
系統可能出現問題
,也可能沒有。 -
ERROR:
該級別的錯誤也需要馬上被處理
,但是緊急程度要低於FATAL級別。ERROR應該盡量詳細記錄。 -
FATAL:
需要立即被處理的系統級錯誤
。系統需要將錯誤相關痕跡以及錯誤細節記錄FATAL日志中,方便后續人工回溯解決。
必須嚴格按照日志的級別給出日志。
2. 日志記錄時機
a) 程序設計語言異常位置
:C++提示異常的位置。結合實際業務使用WARN及以上級別
日志。
b) 業務流程與預期不符
:如外部參數不正確等問題,取決於開發人員的經驗。結合實際業務,使用WARN和ERROR級別
日志。
c) 系統核心角色,組件關鍵動作
:如用戶從登陸到交易完成的整個流程,各個服務節點間交互的位置,核心組件運行過程等。建議記錄INFO級別
日志。
d) 系統及各模塊初始化
:各個服務組件的啟動參數,狀態信息。建議INFO級別
日志記錄。
3. 日志記錄規范
在出現問題之后,需要立即根據日志定位問題。對於INFO及以上級別的日志,要求按照一定順序,輸出以下必要的信息。(最好各個級別日志都遵循以下規范,否則有些日志可能仍無法快速定位。)
- 當前服務器IP
- 當前服務或應用名
- (實例ID):若是不同實例不同名,可忽略,參考應用名。
- 當前類名(如有)
- 當前函數名
- 當前行號
- 內容信息:包含參數信息,調試信息等等。可以有多項。
例子:
PJ_LOG_INFO("Host:{},App:{},Class:{},Function:{},Line:{},Content:{}",localhost,app_example,class_example,func_example,1234,content);
TODO:
- 如果定位問題花費了很長時間,說明系統日志還存在問題,需要進一步完善和優化。
- 日志集中,如何集中?哪些日志集中在一起?同一個在線系統的日志?所有在線系統的所有日志?若存在多個在線的系統?如果日志集中后,需要考慮日志融合和區分。
二、日志追蹤定位
TODO:可以嘗試使用zipkin或者基於Google dapper搭建。
參考
- Trace:跟蹤,表示一條鏈路,以一個唯一的TraceID標識。一次完整調用需要傳遞並記錄唯一的traceID,需要參考一下zipkin代碼。
- Span:跨度,dapper中的基本工作單元,以一個至少Trace內的SpanID標識。每個span中包含traceid,spanid,parentid,spanname,下面提到的annotationsh和binaryAnnotations等。
- Annotation:基本標注列表,一個標注可以理解成span生命周期中重要時刻的數據快照。
"annotations": [
{
"timestamp":1476197067420000,
"value": "cs",
"endpoint": {
"serviceName":"gateway",
"ipv4": "xxx.xxx.xxx.110"
}
},
{
"timestamp":1476197072114000,
"value": "cr",
"endpoint": {
"serviceName":"gateway",
"ipv4": "xxx.xxx.xxx.110"
}
}
],
- BinaryAnnotation:業務標注列表,如果某些跟蹤埋點需要帶上部分業務數據(比如url地址、返回碼和異常信息等),可以將需要的數據以鍵值對的形式放入到這個字段中。
"binaryAnnotations": [
{
"key":"http.url",
"value": "http://localhost:8080/service1",
"endpoint": {
"serviceName":"gateway",
"ipv4": "xxx.xxx.xxx.110"
}
}
]
還有很多沒有完成的工作和不太成熟的地方,歡迎交流指正。