如何利用日志快速定位問題


如何利用日志快速定位問題

引言

一般來說軟件系統或者軟件組件都可以簡單的划分為下面三部分:

  • 輸入部分,例如:

    • 軟件系統外部通信數據/事件輸入;

    • 軟件組件API接口參數(同步/異步);

    • 軟件系統或者組件從外界讀取數據(存儲設備,文件,共享內存,數據庫等)

  • 處理部分,例如:

    • 軟件系統或者組件內部處理(比如:狀態機處理);

  • 輸出部分,例如:

    • 軟件系統輸出到外部的通信數據;

    • 軟件組件調用其他組件API;

    • 軟件系統或者組件寫數據到外部(存儲設備,網絡設備,文件,共享內存,數據庫等)

為了方便定位問題,上面每一部分都需要覆蓋"不多不少"的日志才行。一般來說,輸入輸出必須加入詳細的日志,方便快速界定問題的所屬,甚至重現問題;處理部分中關鍵動作、主要分支、重要入口、預期不會發生的情況,都必須加入詳細的日志,方便定位問題;

 

日志是設計的產物

一方面由於日志的受眾有不同的群體,生產工程師,測試工程師,技術支持,開發工程師等,故日志應該具有不同的抽象層次,"ECall is trigger"這句日志打印對生產工程師,測試工程師是友好的,他們完全明白發生了什么事情,"ECallSts = 0"這句日志恐怕只有開發工程師明白發生了什么事情。故我們應該在設計階段就定義好高抽象度,而且目標受眾是非開發工程師的日志,將這些日志作為設計的一個成果物。原因如下:

  1. 參與上流設計的工程師都是精英工程師,他們有能力定義足夠抽象的日志;

  2. 設計階段就應該考慮怎么驗證我們的系統,日志作為驗證設計的一種手段,就應該在設計階段被考慮;

  3. 上流設計工程師通過預定義好最少日志,在項目后期也方便驗證系統實現是否按照預期實現;

另一方面,軟件中出現的錯誤我們可以分為兩類,一類是設計階段就預估到了的,還有一類是由於能力有限設計階段沒有預估到,設計階段就預估到的錯誤我們需要設計相應的日志來覆蓋。

總的來說,在設計階段設計好接口類(輸入&輸出)日志 & 運行類日志(關鍵動作&主要分支&重要入口&預期不會發生的情況等)日志內容,在實現階段不斷完善調試類日志內容。需要強調的是,好的調試類日志,絕不是一遍就可以寫好的,因此團隊要重視日志優化這件事情,不要讓日志的質量持續降低(當項目變大時,項目的代碼也存在一樣的問題,越寫越亂)。

  • 在定位問題的過程中完善日志,如果定位問題花費了很長時間,那就說明日志還存在問題,需要進一步完善和優化;

  • 需要思考是否可以通過優化日志,來提前預判該問題是否可能發生(如某種資源耗盡而導致的錯誤,可以對資源的使用情況進行記錄)

  • 定義好整個團隊記錄日志的規范,保證每個開發記錄的日志格式統一;特別需要說明的是,對於DEBUG級別的日志,也需要定義好清晰的格式,而不是由開發人員自由發揮;

  • 整個團隊定期對記錄的日志內容進行Review;

日志怎么設計

日志內容格式

實際項目中日志框架都會包含時間、進程ID、線程ID、級別、模塊名等通用信息,但對日志內容卻沒有嚴格的限制。日志內容應該考慮可讀性與全局唯一性,符合人的理解。

  • 日志格式:采用 主語+謂語+賓語+狀語 的格式,日志打印遵從人類的自然語言:

    • 主語:會話的發起者

    • 謂語:將要具體進行什么樣的操作

    • 賓語:行為對象

    • 狀語:行為產生的結果

    例如: "TBox trigger ECALL successful“

  • 可讀性:不打無用的、無意義、不完全的日志,例如不是打印 “Unknown message type”,而是打印 “Unknown message type,type= , supported types=[A,B,C]”

  • 安全性:避免在日志中輸出一些敏感信息,例如密碼與Key等;

  • 全局唯一性:日志內容應該全局唯一,方便ctrl+f全局查找。

  • 信息充足性:在實踐中經常發生日志不夠的情況,在輸出日志時,要注意一並輸出上下文相關信息,比如函數的入參,函數返回值,內部主要數據等。同時也要注意日志內容不宜太長,最好顯示在一行內(最多50個字符)

日志等級划分

一般來說,日志等級分為五種級別,從高到低分別是:FATAL,ERROR、WARN、INFO、DEBUG:

  • FATAL:系統已經無法正常工作,屬於最嚴重的日志級別,一般來說應該非常少見。比如

    • 引發整個系統失敗的錯誤發生了;

    • 系統無法正常啟動;

    • 某個進程遇到無法恢復的錯誤而自動退出;

    • 關鍵組件啟動失敗;

  • ERROR:系統部分功能已經無法正常使用,緊急程度要低於FATAL級別。比如:

    • 調用外部系統接口返回失敗,重試多次后依然失敗;

    • 系統資源使用(RAM,CPU)超過預期;

  • WARN:不會影響程序繼續執行后續的邏輯,更多是一種重要提示需要引起重視。程序可以容忍這些信息,不過它們應該被及時地檢查及修復。比如:

    • 組件輸入輸出異常時需要打印(API參數值異常/同步API返回值異常/異步事件超時);

    • 備份數據恢復出錯,采用默認備份數據;

  • INFO:記錄系統的正常運行狀態,通過查看INFO級別的日志,方便很快地對系統中出現的WARN,ERROR,FATAL錯誤進行定位。比如:

    • 組件相關信息打印(組件初始化完成了/正常輸入輸出/內部狀態機發生遷移/主要分支入口/主要操作成功了/異步請求執行結果輸出)

    • 系統操作行為:如開啟/銷毀線程,打開/關閉連接,定時任務觸發等;

    • 資源或狀態變化:系統初始化成功,關鍵資源的統計信息;

    • 非預期執行:為程序在“有可能”執行到的地方打印日志,如switch case語句塊中的default;

  • DEBUG:該級別日志的主要作用是對系統每一步的運行狀態進行精確的記錄。通過該種日志,可以查看某一個操作每一步的執行過程,可以准確定位是何種操作,何種參數,何種順序導致了某種錯誤的發生。可以保證在不重現錯誤的情況下,也可以通過DEBUG(或TRACE)級別的日志對問題進行診斷。比如:

    • 方便CT & IT測試添加的日志

    • 非API函數的入參打印

快速定位

如前面所說,系統或者組件一般可以分為三部分,輸入->處理->輸出。故在調查具體的bug時,我們需要能知道以下信息:

  1. 本軟件系統/本軟件組件輸入輸出是否正常;

  2. 如果輸出不正常,到底是輸入異常導致 OR 軟件系統或者組件處理出錯導致;

  3. 如果是系統或者組件內部出錯,要能通過日志定位到具體原因。

  4. 鑒於bug很多都是時序混亂、數據非法等造成的,故需要通過日志快速知道問題發生時各組件交互時序,系統/組件輸入數據是否非法等。

在以往的項目中經常遇到這個問題,幾乎總有人會在問題發生時說,這個日志基本上沒有什么用處/或者這個日志我不知道想要干什么,但是每個人似乎又不能說出具體日志應該怎么輸出才對。 故能否像MISRC規范對代碼提出一些硬性要求一樣,對日志也制定一些最低要求

===================================================================================================================================

  • FSR1 [強制]:項目團隊要制定日志輸出規范.
  • FSR2 [強制]:項目團隊要制定日志評審流程。
  • FSR3 [強制]:設計階段設計好日志(邊界類&運行類日志)。
  • FSR4 [建議]:設計階段設計用於系統測試&結合測試的日志。
  • FSR5 [強制]:系統的輸入輸出,必須覆蓋詳細的日志,日志中包含輸入或者輸出的一些關鍵參數。
  • FSR6 [強制]:組件的輸入輸出,必須覆蓋詳細的日志,日志中包含輸入或者輸出的一些關鍵參數。
  • FSR7 [強制]:組件必須至少包含以下4種關鍵詞的日志,用來診斷組件是否健康。
    • FSR7.1 [強制]:程序流關鍵分支上打印用一種關鍵詞,通過篩選該關鍵詞能快速定位問題出現在那個時序段。
  • FSR7.2 [強制]:設計時考慮不可能發生的分支上打印用一種關鍵詞,通過篩選該關鍵詞能快速是否進入了以為不可能進入的分支。
    • FSR7.3 [強制]:函數入參范圍檢查不合格打印用一種關鍵詞,通過篩選該關鍵詞能快速知道是否函數入參超過范圍。
  • FSR7.4 [強制]:組件輸入輸出打印用一種關鍵詞,通過篩選該關鍵詞能快速知道組件是否正常。
    • FSR7.5 [強制]:上述4種關鍵詞在所有組件都是相同的。
  • FSR8 [建議]: 日志內容總體上來說要盡可能少(不意味着信息缺失),方便快速分析。
  • FSR9 [強制]: 日志內容要包含時間戳,日志等級,模塊名等關鍵詞方便快速篩選。
  • FSR10 [建議]: 錯誤之處覆蓋的日志要包含上下文相關信息(函數的入參/函數返回值/內部主要數據值等)。
  • FSR11[強制]: 不循環打印相同內容日志。
  • FSR12[強制]: 每行日志內容不宜過長,不超過50字。
  • FSR13[建議]: 日志內容要遵守上述日志內容輸出格式。
  • FSR14[強制]: 日志登記要遵守上述日志等級划分要求 。
  • FSR15[強制]: 系統版本號/各部件版本號/數據庫版本號等相關版本信息需要以最高等級輸出。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM