設計自用的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 log
lrwxr-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.log
tail: 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.gz
abcd-2018-03-08T14-26-18.794.log.gz