標籤:mount erro deb throw lsp 恢複 視頻 use 分類
背景
軟體系統生產穩定,依靠著各種高可用、高吞吐、高效能的設計。一旦出現生產問題,常常需要線上定位問題。
日誌則是必備的,問題定位利器。常常出現線上問題,我們都可以通過日誌精確定位。同時在開發過程中,由於極長的調用鏈難以快速定位問題或難以複現時,它是極好的利器。
記錄層級
一個項目各個log層級的定義應該是清楚明確的,是每個開發人員所遵循的;
即使是TRACE或者DEBUG層級的日誌,也應該有一定的規範,要保證除了開發人員自己以外,包括測試人員和營運人員都可以方便地通過日誌定位問題;
FATAL
表示需要立即被處理的系統級錯誤。
當該錯誤發生時,表示服務已經出現了某種程度的不可用,系統管理員需要立即介入。
這屬於最嚴重的記錄層級,因此該日誌級 別必須慎用,如果這種層級的日誌經常出現,則該日誌也失去了意義。
通常情況下,一個進程的生命週期中應該只記錄一次FATAL層級的日誌,即該進程遇到無 法恢複的錯誤而退出時。
當然,如果某個系統的子系統遇到了不可恢複的錯誤,那該子系統的調用方也可以記入FATAL層級日誌,以便通過日誌警示提醒系統管 理員修複;
ERROR
該層級的錯誤也需要馬上被處理,但是緊急程度要低於FATAL層級。
當ERROR錯誤發生時,已經影響了使用者的正常訪問。從該意義上來說,實際上 ERROR錯誤和FATAL錯誤對使用者的影響是相當的。
FATAL相當於服務已經掛了,而ERROR相當於好死不如賴活著,然而活著卻無法提供正常的服務,只能不斷地列印ERROR日誌。
特別需要注意的是,ERROR和FATAL都屬於伺服器自己的異常,是需要馬上得到人工介入並處理的。
而對於使用者自己 操作不當,如請求參數錯誤等等,是絕對不應該記為ERROR日誌的;
WARN
該日誌表示系統可能出現問題,也可能沒有,這種情況如網路的波動等。
對於那些目前還不是錯誤,然而不及時處理也會變為錯誤的情況,也可以記為WARN日 志,例如一個儲存系統的磁碟使用量超過閥值,或者系統中某個使用者的儲存配額快用完等等。
對於WARN層級的日誌,雖然不需要系統管理員馬上處理,也是需要 即使查看並處理的。
因此此種層級的日誌也不應太多,能不打WARN層級的日誌,就盡量不要打;
INFO
該種日誌記錄系統的正常運行狀態,例如某個子系統的初始化,某個請求的成功執行等等。
通過查看INFO層級的日誌,可以很快地對系統中出現的 WARN,ERROR,FATAL錯誤進行定位。
INFO日誌不宜過多,通常情況下,INFO層級的日誌應該不大於TRACE日誌的10%;
DEBUG or TRACE
這兩種日誌具體的規範應該由項目組自己定義,該層級日誌的主要作用是對系統每一步的運行狀態進行精確的記錄。
通過該種日誌,可以查看某一個操作每一步的執 行過程,可以準確定位是何種操作,何種參數,何種順序導致了某種錯誤的發生。
可以保證在不重現錯誤的情況下,也可以通過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); } } |
此處推薦的需要在日誌中記錄的內容
- 在系統啟動或初始化時記錄重要的系統初始化參數
- 記錄系統運行過程中的所有的錯誤
- 記錄系統運行過程中的所有的警告
- 在持久化資料修改時記錄修改前和修改後的值
- 記錄系統各主要模組之間的請求和響應
- 重要的狀態變化(如對系統白名單的修改等)
- 系統中一些長期執行的任務的執行進度
- 服務資訊:介面、方法、版本等等
- 如果是逾時,配置的逾時時間,本次處理所用的時間,是Server端逾時還Client逾時?
- 重試的次數,本次重試的是第幾次(fail over)
RequestID
將一個請求的整個處理流程和唯一的requestID關聯起來,requestID規則另行定義。
日誌輸出層級
在設定日誌輸出層級時,推薦如下:
- 開發、測試環境開啟DEBUG;
- 線上生產環境保證設定為WARN層級;
關於日誌分類
日誌從功能來說,可分為診斷記錄、統計日誌、審計日誌。
診斷記錄:
- 請求入口和出口
- 外部服務調用和返回
- 資源消耗操作: 開啟檔案等
- 容錯行為: 譬如雲硬碟的副本修複操作
- 程式異常: 譬如資料庫無法串連
-
後台操作:清理程式
-
啟動、關閉、配置載入
-
拋出異常時,不記錄日誌
統計日誌:
- 使用者訪問統計
- 計費日誌(如記錄使用者交易流水日誌,格式較為嚴格,便於統計)
審計日誌:
關於日誌格式
日誌格式一定要統一,不能任由開發人員的喜好來。舉例來說,對於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命令,在遇到不同的錯誤行為時,分別針對性的給出了報錯資訊。
日誌實踐推薦