聊聊golang的zap的NewDevelopment
source link: https://segmentfault.com/a/1190000038393987
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
序
本文主要研究一下golang的zap的NewDevelopment
NewDevelopment
[email protected]/logger.go
func NewDevelopment(options ...Option) (*Logger, error) { return NewDevelopmentConfig().Build(options...) }
NewDevelopment使用NewDevelopmentConfig进行build
NewDevelopmentConfig
[email protected]/config.go
func NewDevelopmentConfig() Config { return Config{ Level: NewAtomicLevelAt(DebugLevel), Development: true, Encoding: "console", EncoderConfig: NewDevelopmentEncoderConfig(), OutputPaths: []string{"stderr"}, ErrorOutputPaths: []string{"stderr"}, } }
NewDevelopmentConfig创建Config,其Level为NewAtomicLevelAt(DebugLevel),Development为true,Encoding为console,EncoderConfig为NewDevelopmentEncoderConfig,OutputPaths及ErrorOutputPaths均为stderr
NewDevelopmentEncoderConfig
[email protected]/config.go
func NewDevelopmentEncoderConfig() zapcore.EncoderConfig { return zapcore.EncoderConfig{ // Keys can be anything except the empty string. TimeKey: "T", LevelKey: "L", NameKey: "N", CallerKey: "C", FunctionKey: zapcore.OmitKey, MessageKey: "M", StacktraceKey: "S", LineEnding: zapcore.DefaultLineEnding, EncodeLevel: zapcore.CapitalLevelEncoder, EncodeTime: zapcore.ISO8601TimeEncoder, EncodeDuration: zapcore.StringDurationEncoder, EncodeCaller: zapcore.ShortCallerEncoder, } }
NewDevelopmentEncoderConfig创建zapcore.EncoderConfig,其LineEnding为zapcore.DefaultLineEnding,EncodeLevel为zapcore.CapitalLevelEncoder,EncodeTime为zapcore.ISO8601TimeEncoder,EncodeDuration为zapcore.StringDurationEncoder,EncodeCaller为zapcore.ShortCallerEncoder
encoder
[email protected]/zapcore/encoder.go
const DefaultLineEnding = "\n" func CapitalLevelEncoder(l Level, enc PrimitiveArrayEncoder) { enc.AppendString(l.CapitalString()) } 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()) } func ShortCallerEncoder(caller EntryCaller, enc PrimitiveArrayEncoder) { // TODO: consider using a byte-oriented API to save an allocation. enc.AppendString(caller.TrimmedPath()) }
encoder
[email protected]/encoder.go
var ( errNoEncoderNameSpecified = errors.New("no encoder name specified") _encoderNameToConstructor = map[string]func(zapcore.EncoderConfig) (zapcore.Encoder, error){ "console": func(encoderConfig zapcore.EncoderConfig) (zapcore.Encoder, error) { return zapcore.NewConsoleEncoder(encoderConfig), nil }, "json": func(encoderConfig zapcore.EncoderConfig) (zapcore.Encoder, error) { return zapcore.NewJSONEncoder(encoderConfig), nil }, } _encoderMutex sync.RWMutex )
_encoderNameToConstructor内置了console、json两种encoder
NewConsoleEncoder
[email protected]/console_encoder.go
func NewConsoleEncoder(cfg EncoderConfig) Encoder { if len(cfg.ConsoleSeparator) == 0 { // Use a default delimiter of '\t' for backwards compatibility cfg.ConsoleSeparator = "\t" } return consoleEncoder{newJSONEncoder(cfg, true)} } type consoleEncoder struct { *jsonEncoder } func (c consoleEncoder) EncodeEntry(ent Entry, fields []Field) (*buffer.Buffer, error) { line := bufferpool.Get() // We don't want the entry's metadata to be quoted and escaped (if it's // encoded as strings), which means that we can't use the JSON encoder. The // simplest option is to use the memory encoder and fmt.Fprint. // // If this ever becomes a performance bottleneck, we can implement // ArrayEncoder for our plain-text format. arr := getSliceEncoder() if c.TimeKey != "" && c.EncodeTime != nil { c.EncodeTime(ent.Time, arr) } if c.LevelKey != "" && c.EncodeLevel != nil { c.EncodeLevel(ent.Level, arr) } if ent.LoggerName != "" && c.NameKey != "" { nameEncoder := c.EncodeName if nameEncoder == nil { // Fall back to FullNameEncoder for backward compatibility. nameEncoder = FullNameEncoder } nameEncoder(ent.LoggerName, arr) } if ent.Caller.Defined { if c.CallerKey != "" && c.EncodeCaller != nil { c.EncodeCaller(ent.Caller, arr) } if c.FunctionKey != "" { arr.AppendString(ent.Caller.Function) } } for i := range arr.elems { if i > 0 { line.AppendString(c.ConsoleSeparator) } fmt.Fprint(line, arr.elems[i]) } putSliceEncoder(arr) // Add the message itself. if c.MessageKey != "" { c.addSeparatorIfNecessary(line) line.AppendString(ent.Message) } // Add any structured context. c.writeContext(line, fields) // If there's no stacktrace key, honor that; this allows users to force // single-line output. if ent.Stack != "" && c.StacktraceKey != "" { line.AppendByte('\n') line.AppendString(ent.Stack) } if c.LineEnding != "" { line.AppendString(c.LineEnding) } else { line.AppendString(DefaultLineEnding) } return line, nil }
consoleEncoder内嵌了 *jsonEncoder
,其EncodeEntry方法通过getSliceEncoder()获取`*sliceArrayEncoder,然后依次往arr添加time、level、loggerName、caller,最后再添加业务的message本身,对于有stacktrace还会追加stacktrace
实例
func developmentDemo() { logger, _ := zap.NewDevelopment() defer logger.Sync() // flushes buffer, if any sugar := logger.Sugar() sugar.Info("this will be logged") sugar.Panic("test panic") }
输出
2020-12-06T23:29:08.081+0800 INFO log-demo/zap_demo.go:17 this will be logged 2020-12-06T23:29:08.082+0800 PANIC log-demo/zap_demo.go:18 test panic main.developmentDemo /zap_demo.go:18 main.main /zap_demo.go:10 runtime.main /usr/local/go/src/runtime/proc.go:204 panic: test panic goroutine 1 [running]: go.uber.org/zap/zapcore.(*CheckedEntry).Write(0xc0000f20c0, 0x0, 0x0, 0x0) /go/pkg/mod/go.uber.org/[email protected]/zapcore/entry.go:234 +0x585 go.uber.org/zap.(*SugaredLogger).log(0xc0000fbed0, 0x4, 0x0, 0x0, 0xc0000fbed8, 0x1, 0x1, 0x0, 0x0, 0x0) /go/pkg/mod/go.uber.org/[email protected]/sugar.go:234 +0xf6 go.uber.org/zap.(*SugaredLogger).Panic(...) /go/pkg/mod/go.uber.org/[email protected]/sugar.go:123 main.developmentDemo() /zap_demo.go:18 +0x199 main.main() /zap_demo.go:10 +0x25 exit status 2
小结
NewDevelopmentEncoderConfig创建zapcore.EncoderConfig,其LineEnding为zapcore.DefaultLineEnding,EncodeLevel为zapcore.CapitalLevelEncoder,EncodeTime为zapcore.ISO8601TimeEncoder,EncodeDuration为zapcore.StringDurationEncoder,EncodeCaller为zapcore.ShortCallerEncoder
doc
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK