軟件系統生產穩定,依靠着各類高可用、高吞吐、高性能的設計。一旦出現生產問題,經常須要線上定位問題。java
日誌則是必備的,問題定位利器。經常出現線上問題,咱們均可以經過日誌精肯定位。同時在開發過程當中,因爲極長的調用鏈難以快速定位問題或難以復現時,它是極好的利器。linux
一個項目各個log級別的定義應該是清楚明確的,是每一個開發人員所遵循的;數據庫
即便是TRACE或者DEBUG級別的日誌,也應該有必定的規範,要保證除了開發人員本身之外,包括測試人員和運維人員均可以方便地經過日誌定位問題;bash
表示須要當即被處理的系統級錯誤。服務器
當該錯誤發生時,表示服務已經出現了某種程度的不可用,系統管理員須要當即介入。網絡
這屬於最嚴重的日誌級別,所以該日誌級 別必須慎用,若是這種級別的日誌常常出現,則該日誌也失去了意義。app
一般狀況下,一個進程的生命週期中應該只記錄一次FATAL級別的日誌,即該進程遇到無 法恢復的錯誤而退出時。運維
固然,若是某個系統的子系統遇到了不可恢復的錯誤,那該子系統的調用方也能夠記入FATAL級別日誌,以便經過日誌報警提醒系統管 理員修復;ide
該級別的錯誤也須要立刻被處理,可是緊急程度要低於FATAL級別。函數
當ERROR錯誤發生時,已經影響了用戶的正常訪問。從該意義上來講,實際上 ERROR錯誤和FATAL錯誤對用戶的影響是至關的。
FATAL至關於服務已經掛了,而ERROR至關於好死不如賴活着,然而活着卻沒法提供正常的服務,只能不斷地打印ERROR日誌。
特別須要注意的是,ERROR和FATAL都屬於服務器本身的異常,是須要立刻獲得人工介入並處理的。
而對於用戶本身 操做不當,如請求參數錯誤等等,是絕對不該該記爲ERROR日誌的;
該日誌表示系統可能出現問題,也可能沒有,這種狀況如網絡的波動等。
對於那些目前還不是錯誤,然而不及時處理也會變爲錯誤的狀況,也能夠記爲WARN日 志,例如一個存儲系統的磁盤使用量超過閥值,或者系統中某個用戶的存儲配額快用完等等。
對於WARN級別的日誌,雖然不須要系統管理員立刻處理,也是須要 即便查看並處理的。
所以此種級別的日誌也不該太多,能不打WARN級別的日誌,就儘可能不要打;
該種日誌記錄系統的正常運行狀態,例如某個子系統的初始化,某個請求的成功執行等等。
經過查看INFO級別的日誌,能夠很快地對系統中出現的 WARN,ERROR,FATAL錯誤進行定位。
INFO日誌不宜過多,一般狀況下,INFO級別的日誌應該不大於TRACE日誌的10%;
這兩種日誌具體的規範應該由項目組本身定義,該級別日誌的主要做用是對系統每一步的運行狀態進行精確的記錄。
經過該種日誌,能夠查看某一個操做每一步的執 行過程,能夠準肯定位是何種操做,何種參數,何種順序致使了某種錯誤的發生。
能夠保證在不重現錯誤的狀況下,也能夠經過DEBUG(或TRACE)級別的 日誌對問題進行診斷。
須要注意的是,DEBUG日誌也須要規範日誌格式,應該保證除了記錄日誌的開發人員本身外,其餘的如運維,測試人員等也能夠經過 DEBUG(或TRACE)日誌來定位問題;
日誌過多你們夥會說影響性能,可是值得指出的是出錯是小几率分支。若是是出錯是大機率分支那,打日誌之外操做更會成爲瓶頸!
多打日誌減小支持時間,比起開發所用的實現時間,線上和線下的排查/支持要花費不少時間;
抓住異常沒有書寫人和響應日誌,將致使難以定位。
@Override
public
UserAmountStat getUserYestodayStat(Long userId, String day)
throws
GlobalServiceException {
// TODO Auto-generated method stub
try
{
UserAmountStat stat = userAmountStatMapper.getUserYestodayStat(userId, day);
if
(stat ==
null
) {
stat =
new
UserAmountStat();
stat.setBet(0l);
stat.setPrize(0l);
stat.setBonus(0l);
}
return
stat;
}
catch
(Exception e) {
// TODO: handle exception
throw
new
GlobalServiceException(e);
}
}
|
將一個請求的整個處理流程和惟一的requestID關聯起來,requestID規則另行定義。
在設置日誌輸出級別時,推薦以下:
日誌從功能來講,可分爲診斷日誌、統計日誌、審計日誌。
後臺操做:清理程序
啓動、關閉、配置加載
拋出異常時,不記錄日誌
日誌格式必定要統一,不能任由開發人員的喜愛來。舉例來講,對於NOS視頻截圖超時的ERROR日誌,有如下幾種方式打印:
第一種:
logger.error(「Gearman timeout exception
for
request 」 + getRequestID() + 」 value: 」 + value, e);
第二種:
logger.error(「RequestID: 」 + getRequestID() + 「, Error Message: Gearman timeout exception: 」 + e);
第三種:
logger.error(getErrorMessage(getRequestID(), getErrorMessage(), e));
|
第一種方式打印日誌便是開發人員按照本身的喜愛來的,這種方法帶來的問題是:
而第三種方式,經過一個函數來規範日誌格式,全部開發人員即可以經過該接口實現統一的日誌。
日誌書寫語義必定要明確,定義明確語義的異常類信息,在此列舉linux環境下兩個報錯信息做爲示例;
[root
@ip
-
172
-
31
-
1
-
43
~]# cd /file
-bash: cd: /file: 沒有那個文件或目錄
[root
@ip
-
172
-
31
-
1
-
43
~]# cd build-
public
-ult_6.
0
-
2015
-
09
-
02
-17_6d3c3ee51a.tar.gz
-bash: cd: build-
public
-ult_6.
0
-
2015
-
09
-
02
-17_6d3c3ee51a.tar.gz: 不是目錄
|
咱們能夠看到一樣是cd命令,在遇到不一樣的錯誤行爲時,分別針對性的給出了報錯信息。