這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
設計自用的golang日誌模組
golang的原生日誌模組不能滿足需求,而開源的第三方包,也不完全夠用。使用者較多的logrus,卻沒有rotate功能,這已經是眾所周知的。對於營運來說,當然是希望日誌的處理中比較簡單、實用、夠用。不需要額外的通過系統來實現logrotate。
1、需求
從需求方面來說,主要有幾個方面:
一方面肯定是需要有輪轉功能,而且要限制保留的日誌份數。至於是按檔案大小,還是按天、按小時切割,則可以討論。
另一方面,對於日誌的層級,如果能夠動態調整,則方便日誌關閉常規日誌,線上調試時,動態降低日誌的等級,列印更多debug日誌。
2、調研
目前主要的有幾個:
- github.com/sirupsen/logrus。使用者廣泛,但明確表示不支援日誌切割功能,建議通過hook走日誌系統。
- github.com/natefinch/lumberjack。支援以檔案大小的方式切割日誌。使用者偏少。
- gopkg.in/inconshreveable/log15.v2。比較老牌。
- github.com/lestrrat-go/file-rotatelogs。基於小時數進行切割的小眾包。
- github.com/xiaomi-tc/log15。小米基於log15寫的二次封裝增加了切割功能。但只有2星。
- 有前同事基於log15寫的二次封裝,但log15.v2/ext的包不太容易理解。
- github.com/ngaut/log。完全不依賴第三方包。可基於日期及小時進行切割。
綜上,ngaut比較適合學習和瞭解封裝過程。而基於logrus則是比較靠譜的選擇,底層需要其他包實現的切割功能。
3、功能設計
主要點:
- 由logrus來完成日誌功能。
- 需要完成日誌切割,曆史日誌需要壓縮
- 支援參考Go代碼遇到的問題提供的level熱更新
3.1 基於file-rotatelogs實現
即基於日期的日誌輪轉。
代碼:github.com/jungle85gopy/rotlogs/daterot
範例程式碼:參考github.com/jungle85gopy/rotlogs/example/date/date.go
兩個不足之處:
- 該庫沒有壓縮功能。
- 日誌目錄對相對路徑不友好。
- 比如使用log/access.log時。log/access.log是個軟鏈,連結到帶日誌的檔案。
# ls -l loglrwxr-xr-x 1 song staff 28 Mar 8 13:23 access.log -> log/access.log.20180308-1323-rw-r--r-- 1 song staff 2511 Mar 8 13:23 access.log.20180308-1323# tail log/access.logtail: log/access.log: No such file or directory
解決辦法之一就是不使用軟鏈,將是不主動設定BaseLinkName變數。
3.2 基於lumberjack實現
即基於檔案大小的日誌輪轉。
代碼:github.com/jungle85gopy/rotlogs
範例程式碼:參考github.com/jungle85gopy/rotlogs/example/size/size.go
這個版本的不足之處,在於日誌切割後日誌,其檔案名稱過於複雜。可能不便後後繼處理
# ls -l log abcd-2018-03-08T14-09-31.066.log.gzabcd-2018-03-08T14-26-18.794.log.gz