1. 程式人生 > 實用技巧 >SkyWalking Agent端日誌外掛的編寫歷程與使用說明

SkyWalking Agent端日誌外掛的編寫歷程與使用說明

概述

前一段時間順利完成了SkyWalking Agent端logger-plugin外掛的開發,在此做個總結。一方面給外掛的使用方法寫一中文說明,另一方面分享一下該外掛開發過程中的一些考量以及收穫。

logger-plugin外掛,主要作用實現將將程式在呼叫過程中產生的日誌比如錯誤日誌資訊,存入到span log中。然後可以通過web端直接查詢,便於開發者排錯與分析。同時為了提高使用的靈活性,我們還提供了配置檔案,通過配置檔案可以對需要存入到span log的日誌來源(log4j2、logbak、log4j)、包名、日誌級別、內容進行控制。但同時需要提醒的一點是,由於該外掛直接作用於agent端,可能會造成一定程度的效能損失

,請謹慎使用。

相關PR地址如下:Support collecting logs of log4j, log4j2, and logback in the tracing context,以供參考。

使用方式

基於效能的考量,該外掛在設計之初定位為可選外掛,因而預設情況下該外掛的功能並不會啟動。如需使用,需要在8.4.0釋出之後,將外掛從apache-skywalking-apm-bin/agent/optional-plugins/目錄下複製到apache-skywalking-apm-bin/agent/plugins/下,方能生效。

配置檔案

首先需要說明的一點是,釋出時預設是沒有配置檔案的,外掛會按照如下預設配置內容執行:

log4j.packages=*
log4j.level=error
log4j2.packages=*
log4j2.level=error
logback.packages=*
logback.level=error

上述配置檔案含義如下:

  1. 該外掛預設會對所有支援的日誌框架生效,包括log4j、log4j2、logbback。
  2. 外掛之後將高於error級別的日誌資訊存入到span log中,而對trace, debug, info, warn級別的日誌資訊不生效。
  3. 預設情況下,會收集所有包級別的日誌資訊。

.如果需要自定義外掛的配置資訊,需要在apache-skywalking-apm-bin/agent/config/logger-plugin/

目錄下建立logconfig.properties檔案進行配置。

配置檔案可配置內容及其含義如下:

packages

含義:指定需要轉存的日誌資訊的包名,預設匹配所有包。

取值:

  • 包名:例如org.apache。若有多個包名中間需用逗號隔開
  • *:匹配所有包級別的日誌資訊。

Level

含義:所需轉存的日誌資訊的級別,預設情況是error級別的日誌資訊

日誌級別從小到大排列如下:

trace < debug < info <warn< error < fatal

同時我們在自定義配置資訊的時候需要注意,由於logback不支援fatal級別的日誌資訊,因而如果錯誤的進行如下配置:

logback.level=error

則會造成針對logback的配置失效,也即不會收集任何關於logback日誌外掛產生的日誌資訊,並會產生錯誤日誌,以供使用者排查。

設計思路

其實這個外掛剛開始外掛之初,由於個人工程經驗不足,當時考慮想要實現功能很多,比如需要支援正則表示式用以過濾,支援日誌的格式化配置等等。但在和其他社群成員的討論過程中發現,需要功能其實和該外掛的定位不同,比如過濾日誌資訊的功能,日誌系統中已經支援了。如果該外掛再增加該功能一方面會增加外掛使用的複雜程度,另一方面,也會造成更大的效能損耗。而針對另一功能日誌的格式化,這與該外掛的定位也是不符合的,apm系統本身就是為了實現追蹤和快速定位,對收集到的日誌資訊希望儘量簡練,有效,許多格式化的資訊,根本無需收集。因而該功能最終也被廢止。

同時針對日誌轉存到span的格式,和社群成員也進行仔細的溝通,為了適應未來SkyWalking的日誌查詢功能,因此在轉存日誌資訊時,儲存到OAP端的span log日誌是結構化的類似於下面的形式:

"logs": [
  {
    "time": 1605225365711,
    "data": [
      {
        "key": "event",
        "value": "warn"
      },
      {
        "key": "log.kind",
        "value": "org.apache.skywalking.oap.server.analyzer.provider.trace.parser.listener.MultiScopesAnalysisListener"
      },
      {
        "key": "message",
        "value": "span {} has illegal status code {}"
      },
      {
        "key": "param.1",
        "value": "*span*"
      },
      {
        "key": "param.2",
        "value": "*tag.getValue()*"
      }
    ]
  }
]

便於後續Web端實現靈活的查詢。關於日誌格式詳細的討論過程,可以參考《What format should we have in mind for logging to spans?》

同時在設計的過程中,剛開始找到插入點也是不合理的,比如剛開始選擇的直接增強sl4j.Logger介面,這回造成一個問題,一旦使用者沒有使用Log4j建立Logger物件就會造成日誌外掛失效,最終在BFergerson的幫助下,換成了一個更加合理的插入點。

總結

這篇文章更多的可能是個人在開發logger-plugin外掛過程中踩過坑的總結吧,在整個開發過程中,其實收穫蠻多的,比如並非一個軟體功能越多越好。這個需要從該軟體本身的定位出發,兼顧效能和易用性,做到一種平衡。同時簡單寫了寫logger-plugin外掛的使用方法,希望能夠給感興趣的同學以幫助。