這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
1.結構化日誌的意義
1.1 日誌格式化
日誌主要用於Tracing Service的運行資訊,作為後端攻城獅,一般都會有一種想法,平時的時候希望日誌越少越好,出問題的時候又總是抱怨,怎麼才tmd這點日誌,還在關鍵的地方沒列印.
因此,日誌很重要,將日誌進行格式化也很重要,日誌格式化主要是為了方便後續進行分析.如通過將錯誤碼格式化到日誌中,我們可以對收集後的日誌分析介面的調用健康狀態,將介面耗時格式化後上報,可以監控延時高的操作,並查詢出關聯日誌進行分析.
所以只要是格式化輸出,很容易有很多應用.
1.2 日誌庫應該有的特性
這裡主要是兩方面,每次操作的耗時,以及每次操作分配的記憶體,作為日誌庫,兩個指標都應該要極低.
能通過調節日誌等級列印不同層級的日誌.
能夠設定採樣率,防止服務要求增加時輸出的日誌量劇增,從而影響服務效能.
自動按一定大小切分檔案,定期歸檔,儲存一定數量檔案.
基於以上幾點,選擇uber開源的日誌庫 zap.
2.整合到grpc中
2.1 思路
grpc 定義了grpclog包,並定義了LoggerV2的介面,因此,只要通過zap實現LoggerV2的介面,並通過SetLoggerV2(l LoggerV2)介面將實現的對象設定到grpclog包中,那麼grpc將使用zap進行日誌輸出,同時上層應用也可以使用grpclog進行業務日誌列印.
2.2 實現
完整代碼以及使用樣本見 grpc-wrapper
type ZapLogger struct { logger *zap.Logger}//建立封裝了zap的對象,該對象是對LoggerV2介面的實現func NewZapLogger(logger *zap.Logger) *ZapLogger { return &ZapLogger{ logger: logger, }}func (zl *ZapLogger) Info(args ...interface{}) { zl.logger.Sugar().Info(args...)}func (zl *ZapLogger) Infoln(args ...interface{}) { zl.logger.Sugar().Info(args...)}func (zl *ZapLogger) Infof(format string, args ...interface{}) { zl.logger.Sugar().Infof(format, args...)}func (zl *ZapLogger) Warning(args ...interface{}) { zl.logger.Sugar().Warn(args...)}func (zl *ZapLogger) Warningln(args ...interface{}) { zl.logger.Sugar().Warn(args...)}func (zl *ZapLogger) Warningf(format string, args ...interface{}) { zl.logger.Sugar().Warnf(format, args...)}func (zl *ZapLogger) Error(args ...interface{}) { zl.logger.Sugar().Error(args...)}func (zl *ZapLogger) Errorln(args ...interface{}) { zl.logger.Sugar().Error(args...)}func (zl *ZapLogger) Errorf(format string, args ...interface{}) { zl.logger.Sugar().Errorf(format, args...)}func (zl *ZapLogger) Fatal(args ...interface{}) { zl.logger.Sugar().Fatal(args...)}func (zl *ZapLogger) Fatalln(args ...interface{}) { zl.logger.Sugar().Fatal(args...)}// Fatalf logs to fatal levelfunc (zl *ZapLogger) Fatalf(format string, args ...interface{}) { zl.logger.Sugar().Fatalf(format, args...)}// V reports whether verbosity level l is at least the requested verbose level.func (zl *ZapLogger) V(v int) bool { return false}
3.最終效果
可以看到,日誌以json格式輸出,並顯示了日誌列印時的程式碼數,同時當出現error時進行了調用棧的追蹤.
參考
grpc
zap.
grpc-wrapper