序
本文次要钻研一下 golang 的 zap 的 NewExample
NewExample
zap@v1.16.0/logger.go
func NewExample(options ...Option) *Logger {
encoderCfg := zapcore.EncoderConfig{
MessageKey: "msg",
LevelKey: "level",
NameKey: "logger",
EncodeLevel: zapcore.LowercaseLevelEncoder,
EncodeTime: zapcore.ISO8601TimeEncoder,
EncodeDuration: zapcore.StringDurationEncoder,
}
core := zapcore.NewCore(zapcore.NewJSONEncoder(encoderCfg), os.Stdout, DebugLevel)
return New(core).WithOptions(options...)
}
NewExample 应用通过 core 来创立 Logger,其中 core 应用的 Encoder 为 JSONEncoder,WriteSyncer 应用的是 os.Stdout,LevelEnabler 应用的是 DebugLevel;应用的 JSONEncoder 的 zapcore.EncoderConfig 其 EncodeLevel 为 zapcore.LowercaseLevelEncoder, 其 TimeEncoder 为 zapcore.ISO8601TimeEncoder,,其 DurationEncoder 为 zapcore.StringDurationEncoder
encoder
zap@v1.16.0/zapcore/encoder.go
func LowercaseLevelEncoder(l Level, enc PrimitiveArrayEncoder) {enc.AppendString(l.String())
}
func ISO8601TimeEncoder(t time.Time, enc PrimitiveArrayEncoder) {encodeTimeLayout(t, "2006-01-02T15:04:05.000Z0700", enc)
}
func StringDurationEncoder(d time.Duration, enc PrimitiveArrayEncoder) {enc.AppendString(d.String())
}
LowercaseLevelEncoder 应用小写打印 log level;ISO8601TimeEncoder 应用
2006-01-02T15:04:05.000Z0700
格局打印工夫;StringDurationEncoder 应用 Duration 内置的 String()打印 time.Duration
NewJSONEncoder
zap@v1.16.0/zapcore/json_encoder.go
func NewJSONEncoder(cfg EncoderConfig) Encoder {return newJSONEncoder(cfg, false)
}
func newJSONEncoder(cfg EncoderConfig, spaced bool) *jsonEncoder {
return &jsonEncoder{
EncoderConfig: &cfg,
buf: bufferpool.Get(),
spaced: spaced,
}
}
func (enc *jsonEncoder) EncodeEntry(ent Entry, fields []Field) (*buffer.Buffer, error) {final := enc.clone()
final.buf.AppendByte('{')
if final.LevelKey != "" {final.addKey(final.LevelKey)
cur := final.buf.Len()
final.EncodeLevel(ent.Level, final)
if cur == final.buf.Len() {
// User-supplied EncodeLevel was a no-op. Fall back to strings to keep
// output JSON valid.
final.AppendString(ent.Level.String())
}
}
if final.TimeKey != "" {final.AddTime(final.TimeKey, ent.Time)
}
if ent.LoggerName != ""&& final.NameKey !="" {final.addKey(final.NameKey)
cur := final.buf.Len()
nameEncoder := final.EncodeName
// if no name encoder provided, fall back to FullNameEncoder for backwards
// compatibility
if nameEncoder == nil {nameEncoder = FullNameEncoder}
nameEncoder(ent.LoggerName, final)
if cur == final.buf.Len() {
// User-supplied EncodeName was a no-op. Fall back to strings to
// keep output JSON valid.
final.AppendString(ent.LoggerName)
}
}
if ent.Caller.Defined {
if final.CallerKey != "" {final.addKey(final.CallerKey)
cur := final.buf.Len()
final.EncodeCaller(ent.Caller, final)
if cur == final.buf.Len() {
// User-supplied EncodeCaller was a no-op. Fall back to strings to
// keep output JSON valid.
final.AppendString(ent.Caller.String())
}
}
if final.FunctionKey != "" {final.addKey(final.FunctionKey)
final.AppendString(ent.Caller.Function)
}
}
if final.MessageKey != "" {final.addKey(enc.MessageKey)
final.AppendString(ent.Message)
}
if enc.buf.Len() > 0 {final.addElementSeparator()
final.buf.Write(enc.buf.Bytes())
}
addFields(final, fields)
final.closeOpenNamespaces()
if ent.Stack != ""&& final.StacktraceKey !="" {final.AddString(final.StacktraceKey, ent.Stack)
}
final.buf.AppendByte('}')
if final.LineEnding != "" {final.buf.AppendString(final.LineEnding)
} else {final.buf.AppendString(DefaultLineEnding)
}
ret := final.buf
putJSONEncoder(final)
return ret, nil
}
NewJSONEncoder 创立的是 jsonEncoder;其 EncodeEntry 办法一次打印 LevelKey、TimeKey、LoggerName、Caller,最初才是业务的 message 自身,而后完结 json 打印,对于有 stacktrace 还会以非 json 的模式 (一般堆栈模式) 打印 stacktrace
实例
func exampleDemo() {logger := zap.NewExample()
defer logger.Sync() // flushes buffer, if any
sugar := logger.Sugar()
sugar.Info("this will be logged")
sugar.Info("time=", time.Now())
sugar.Panic("test panic")
}
输入
{"level":"info","msg":"this will be logged"}
{"level":"info","msg":"time=2020-12-07 23:14:48.50402 +0800 CST m=+0.000602110"}
{"level":"panic","msg":"test panic"}
panic: test panic
goroutine 1 [running]:
go.uber.org/zap/zapcore.(*CheckedEntry).Write(0xc0001680c0, 0x0, 0x0, 0x0)
/go/pkg/mod/go.uber.org/zap@v1.16.0/zapcore/entry.go:234 +0x585
go.uber.org/zap.(*SugaredLogger).log(0xc000179e98, 0xc000054e04, 0x0, 0x0, 0xc000179ea0, 0x1, 0x1, 0x0, 0x0, 0x0)
/go/pkg/mod/go.uber.org/zap@v1.16.0/sugar.go:234 +0xf6
go.uber.org/zap.(*SugaredLogger).Panic(...)
/go/pkg/mod/go.uber.org/zap@v1.16.0/sugar.go:123
main.exampleDemo()
/zap_demo.go:19 +0x277
main.main()
/zap_demo.go:10 +0x25
exit status 2
小结
NewExample 应用通过 core 来创立 Logger,其中 core 应用的 Encoder 为 JSONEncoder,WriteSyncer 应用的是 os.Stdout,LevelEnabler 应用的是 DebugLevel;NewJSONEncoder 创立的是 jsonEncoder;其 EncodeEntry 办法一次打印 LevelKey、TimeKey、LoggerName、Caller,最初才是业务的 message 自身,而后完结 json 打印,对于有 stacktrace 还会以非 json 的模式 (一般堆栈模式) 打印 stacktrace
doc
- zap