為什么要用zap來寫日志
原來是寫PHP的,一直用的error_log,第一次寫Go項目的時候,還真不知道該怎么寫日志,后來就按照PHP的寫法自己不成規范的搗鼓寫。去了新公司之后,發現用的是zap。后來查詢 了解了下zap,前同事反應他們很多大公司都在使用zap寫日志,GitHub上star 高達7K多,足以說明它受歡迎的程度。
1.zap是Uber開源的日志庫;
2.很多大的公司和小的公司都在使用;
3.跟seelog、logrus等類庫相比,高性能是它最突出的優勢;
我想以上幾個原因就已經說明了它的廣泛性、穩定性,就值得我們去嘗試。
怎么使用zap
我們說下簡單的使用案例
首相當然是下載
go get -u go.uber.org/zap
先貼一個我這邊常用的zap的配置
zap.Config{
Level: zap.NewAtomicLevelAt(zap.DebugLevel),
Development: true,
Encoding: "json",
EncoderConfig: zapcore.EncoderConfig{
TimeKey: "t",
LevelKey: "level",
NameKey: "log",
CallerKey: "caller",
MessageKey: "msg",
StacktraceKey: "trace",
LineEnding: zapcore.DefaultLineEnding,
EncodeLevel: zapcore.LowercaseLevelEncoder,
EncodeTime: 時間格式函數,
EncodeDuration: zapcore.SecondsDurationEncoder,
EncodeCaller: zapcore.ShortCallerEncoder,
},
OutputPaths: []string{"/tmp/zap.log"},
ErrorOutputPaths: []string{"/tmp/zap.log"},
InitialFields: map[string]interface{}{
"app": "test",
},
}
基本配置的說明
Level:日志級別,跟其他語言是一樣的。只不過它需要的類型是AtomicLevel。所以需要使用zap.NewAtomicLevelAt做下如下的轉化。
zap.NewAtomicLevelAt(zap.DebugLevel)
zap.DebugLevel
zap.InfoLevel
zap.WarnLevel
zap.ErrorLevel
Development:bool 是否是開發環境。如果是開發模式,對DPanicLevel進行堆棧跟蹤
DisableCaller:bool 禁止使用調用函數的文件名和行號來注釋日志。默認進行注釋日志
DisableStacktrace:bool 是否禁用堆棧跟蹤捕獲。默認對Warn級別以上和生產error級別以上的進行堆棧跟蹤。
Encoding:編碼類型,目前兩種json 和 console【按照空格隔開】,常用json
EncoderConfig:生成格式的一些配置--TODO 后面我們詳細看下EncoderConfig配置各個說明
OutputPaths:[]string 日志寫入文件的地址
ErrorOutputPaths:[]string 將系統內的error記錄到文件的地址
InitialFields:map[string]interface{} 加入一些初始的字段數據,比如項目名
當然了,如果想控制台輸出,OutputPaths和ErrorOutputPaths不能配置為文件地址,而應該改為stdout。
關於config的配置,具體的可以參考文件里面的注釋
go.uber.org/zap/config.go
type Config struct
EncoderConfig配置說明
MessageKey:輸入信息的key名
LevelKey:輸出日志級別的key名
TimeKey:輸出時間的key名
NameKey CallerKey StacktraceKey跟以上類似,看名字就知道
LineEnding:每行的分隔符。基本zapcore.DefaultLineEnding 即"\n"
EncodeLevel:基本zapcore.LowercaseLevelEncoder。將日志級別字符串轉化為小寫
EncodeTime:輸出的時間格式
EncodeDuration:一般zapcore.SecondsDurationEncoder,執行消耗的時間轉化成浮點型的秒
EncodeCaller:一般zapcore.ShortCallerEncoder,以包/文件:行號 格式化調用堆棧
EncodeName:可選值。
具體EncoderConfig的說明,可以參考文件里面的注釋
go.uber.org/zapcore/encoder.go
type EncoderConfig struct
舉個栗子
你扯這么多配置說明,誰有時間看這玩意,寫個常用的讓大家照着用就好了嘛。
package main
import (
"fmt"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"time"
)
var logger *zap.Logger
func formatEncodeTime(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
enc.AppendString(fmt.Sprintf("%d%02d%02d_%02d%02d%02d", t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second()))
}
func FormateLog(args []interface{}) *zap.Logger {
log := logger.With(ToJsonData(args))
return log
}
func Debug(msg string, args ...interface{}) {
FormateLog(args).Sugar().Debugf(msg)
}
func ToJsonData(args []interface{}) zap.Field {
det := make([]string, 0)
if len(args) > 0 {
for _, v := range args {
det = append(det, fmt.Sprintf("%+v", v))
}
}
zap := zap.Any("detail", det)
return zap
}
func InitZapLog() {
cfg := zap.Config{
Level: zap.NewAtomicLevelAt(zap.DebugLevel),
Development: true,
Encoding: "json",
EncoderConfig: zapcore.EncoderConfig{
TimeKey: "t",
LevelKey: "level",
NameKey: "logger",
CallerKey: "caller",
MessageKey: "msg",
StacktraceKey: "trace",
LineEnding: zapcore.DefaultLineEnding,
EncodeLevel: zapcore.LowercaseLevelEncoder,
EncodeTime: formatEncodeTime,
EncodeDuration: zapcore.SecondsDurationEncoder,
EncodeCaller: zapcore.ShortCallerEncoder,
},
OutputPaths: []string{"/tmp/zap.log"},
ErrorOutputPaths: []string{"/tmp/zap.log"},
InitialFields: map[string]interface{}{
"app": "test",
},
}
var err error
logger, err = cfg.Build()
if err != nil {
panic("log init fail:" + err.Error())
}
}
func main() {
InitZapLog()
defer logger.Sync()
a := []string{"test","hello","world"}
Debug("output",a)
}
執行下,就會在日志文件上輸入按照我們配置日志格式。
tail -f /tmp/zap.log
{"level":"debug","t":"20190630_044053","caller":"myproject/main.go:21","msg":"output","app":"test","detail":["[test hello world]"]}
然后我們試下控制台輸出,修改三個console相關的配置代碼
···
OutputPaths: []string{"stdout"},
ErrorOutputPaths: []string{"stdout"},
控制台窗口就會輸出
{"level":"debug","t":"20190630_092533","caller":"myproject/main.go:21","msg":"output","app":"test","detail":["[test hello world]"]}
···
當然了,zap最想的使用和文檔,看官網嘛
https://github.com/uber-go/zap
https://godoc.org/go.uber.org/zap