天天看點

日志記錄的最佳實踐

作者:Thoughtworks

簡介

日志(Log)是由系統在運作過程中産生的結構化或者非結構化的文字資訊。通常情況,可以将其視為應用程式對某個事件(Event)的記錄。日志通常可以幫助我們發現一些微服務架構系統的非預期或突發的行為。 Logging作為 Observability(可觀察性,在IT和雲計算中,它是根據系統生成的資料,例如日志、名額和資料鍊追蹤等來衡量系統目前狀态的能力)的重要組成部分,在我們的系統開發、維護中起到無法替代的作用。

日志記錄的最佳實踐

Pillars of Observability

日志的重要性

要了解為什麼日志在産品或者系統中扮演着重要的角色,我們必須了解它的價值。至少到現在,日志被應用最廣泛的是報警、故障排除和業務資料可視化。

報警

日志可以作為我們業務系統監控的重要資料來源;成熟的産品系統都有報警系統,如果系統中出現超過某個已定義的某個名額的問題,日志系統會自動将報警資訊發送到通知平台,On-call 的人就可以根據報警資訊定位解決問題了。

故障排除

這種情況非常普遍;想象一下你最近負責開發維護的系統被他人發現有問題,在你梳理完思路之後第一件事是幹什麼?肯定是檢視系統資訊驗證自己的假設是否成立,這裡列印在伺服器上的日志就是最好的輔助資訊。而作為程式員的我們,日志是我們最熟悉不過的解決問題的利器。

業務資料可視化

很多公司可以利用存儲在自己資料庫裡的生産環境的日志,結合相應的工具可以對業務進行業務資料可視化。這裡最典型的代表是 Grafana 和 SumoLogic。

怎麼做

模闆化

為了更好支援上面的各種情況,我們需要對我們的日志格式進行梳理,按照一定的規範來寫日志,而不是随便寫一句廢話。

日志記錄的最佳實踐

Log Format

  • 基礎版本
    • 對于日志,時間,日志級别,和日志資訊最為重要,是以一個合格的日志應該至少包含這些資訊。
  • 進階版本
    • 在基礎版的基礎上,加入線程名,主機名,方法名,類名,方法對應的行數;
    • 線程名:多數應用的使用者都不是單一的,對于單執行個體的服務對同一個接口很多使用者通路應用會将在不同的線程中執行,這時如果要區分對應使用者的業務流程,那麼通過線程名是最好的。
    • 主機名:現在的應用大多部署在 Cloud 中,都是多執行個體的,是以在單節點的基礎上,日志在多執行個體上就需要執行個體級别的區分,而主機名是最好的區分方式。
    • 方法名:列印了日志的方法名,友善區分相同日志的出處。
    • 類名:列印了日志的類名,友善快速定位業務流程。
    • 行數:列印了日志的行數,友善快速定位日志的具體位置。

格式化

為了提高日志的可讀性,我們可以對日志進行修飾。

  • 對日志級别、主機名和線程名前後加中括号;
  • 對方法名所在的類名和行号加括号,并在類名與行号中間用冒号隔開;
  • 在行号和日志資訊中間加入一個橫線來分隔;
  • 對于日志資訊也可以進行特定的格式化對于正常的請求(Request)、響應(Response)或者其他業務日志,可以在自定義資訊和參數之間用下劃線分隔;多個參數之間用逗号分隔,當然參數也是可選的;對于錯誤資訊格式化,也可以按照 Key:Value 的形式進行組織。

鍊式追蹤

記錄下了日志,如果隻是一行行簡單的文字說明,那是沒有太大意義的。在複雜系統或業務操作頻繁的系統中,會産生非常多的日志,在這種情況下,我們就得花時間去過濾出相關的日志。解決上面問題的最好辦法是日志的鍊式追蹤;簡單說就是,在每條日志中加入業務系統中的一個或者多個唯一的 ID,這樣在定位業務問題的時候可以通過這些唯一的 ID 和 其他條件(e.g. 時間)快速過濾出相關的日志。

按需記錄日志

日志級别

日志記錄的最佳實踐

Log Level

日志的輸出都是分級别的,不同的場景需要列印不同級别的日志;以下是幾個比較重要的日志級别。

  • Debug: 記錄技術細節,和一些幫助了解系統運作的日志;
  • Info: 記錄業務資訊的日志;
  • Warn: 非緊急且可控的可接受的錯誤資訊;
  • Error: 非期望的錯誤或者系統表現,通常是由系統bug或者環境問題導緻。

同時不是所有的日志都需要記錄,我們要做到按需記錄。下表是在不同的環境選擇不同日志級别的推薦。

Environment Log Leave
Dev Debug
Test Debug
UAT Info
Prod Info

日志位置

有了日志級别,日志列印的位置也需要明确。一般情況下:

  • 其他系統調用自有系統時需要在收到請求和完成請求時各列印一次日志;
  • 自有系統調用第三方系統的接口前和收到傳回資訊後各列印一次日志;
  • 在系統中任何有異常的地方需要列印日志;

還有一種特殊情況是,像消息傳遞之類的系統,為了節省日志存儲和減少檢視幹擾,大多時候我們不需要在收到消息後直接列印該消息,一般建議在收到消息後,如果系統處理有異常,在異常中将原始消息列印。

工具推薦

不同的程式設計語言有不同的日志工具;比較著名的是 Apache 的 Log4j, Log4j是高度可配置的,并可通過在運作時的外部檔案配置。它根據記錄的優先級别,并提供機制以訓示記錄資訊到許多的目的地,諸如:資料庫,檔案,控制台,UNIX系統日志等;而且 log4j 已經被移植到了其他程式設計語言中了,如 Python 中的 logging, NodeJS 中的log4js, Rust 中的log4rs。

注意點

  • 避免列印或記錄任何敏感資訊,包括但不限于各種PII,PCI資訊,一定要記得遵守當地的各種法律法規,如中國的《個人資訊保護法》(PILI),歐洲的一般資料保護條例GDPR等
  • 按需選擇合适的日志級别和日志位置
  • ……

總結

好的日志不僅可以為程式開發提供便利,為故障排除提供最重要的輔助資訊,更可以為業務或基礎設施提供優化建議或資料統計。

參考材料

  • THE TOP 25 GRAFANA DASHBOARD EXAMPLES
  • Grafana lab
  • SumoLogic
  • Log4j

文/Thoughtworks 谷中仁

更多精彩洞見,請關注公衆号Thoughtworks洞見

繼續閱讀