From f2ca0bc9d94c1f1804f7efeb4cf16f76b52842bc Mon Sep 17 00:00:00 2001 From: Vasiliy Tolstov Date: Wed, 4 Mar 2020 01:04:22 +0300 Subject: [PATCH] fix zaplogger field duplication Signed-off-by: Vasiliy Tolstov --- options.go | 6 ++++++ zap.go | 58 ++++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 49 insertions(+), 15 deletions(-) diff --git a/options.go b/options.go index 915b1af..7b69005 100644 --- a/options.go +++ b/options.go @@ -11,6 +11,12 @@ type Options struct { logger.Options } +type callerSkipKey struct{} + +func WithCallerSkip(i int) logger.Option { + return logger.SetOption(callerSkipKey{}, i) +} + type configKey struct{} // WithConfig pass zap.Config to logger diff --git a/zap.go b/zap.go index c997ee2..18dea7d 100644 --- a/zap.go +++ b/zap.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "os" + "sync" "go.uber.org/zap" "go.uber.org/zap/zapcore" @@ -15,6 +16,8 @@ type zaplog struct { cfg zap.Config zap *zap.Logger opts logger.Options + sync.RWMutex + fields map[string]interface{} } func (l *zaplog) Init(opts ...logger.Option) error { @@ -34,13 +37,18 @@ func (l *zaplog) Init(opts ...logger.Option) error { } + skip, ok := l.opts.Context.Value(callerSkipKey{}).(int) + if !ok || skip < 1 { + skip = 1 + } + // Set log Level if not default zapConfig.Level = zap.NewAtomicLevel() if l.opts.Level != logger.InfoLevel { zapConfig.Level.SetLevel(loggerToZapLevel(l.opts.Level)) } - log, err := zapConfig.Build() + log, err := zapConfig.Build(zap.AddCallerSkip(skip)) if err != nil { return err } @@ -63,55 +71,75 @@ func (l *zaplog) Init(opts ...logger.Option) error { l.cfg = zapConfig l.zap = log + l.fields = make(map[string]interface{}) return nil } func (l *zaplog) Fields(fields map[string]interface{}) logger.Logger { - data := make([]zap.Field, 0, len(fields)) + l.Lock() + l.fields = make(map[string]interface{}, len(fields)) for k, v := range fields { - data = append(data, zap.Any(k, v)) + l.fields[k] = v } - l.zap = l.zap.With(data...) + l.Unlock() + return l } func (l *zaplog) Error(err error) logger.Logger { - l.zap = l.zap.With(zap.Error(err)) + l.Lock() + l.fields["error"] = err + l.Unlock() + return l } func (l *zaplog) Log(level logger.Level, args ...interface{}) { + l.RLock() + data := make([]zap.Field, 0, len(l.fields)) + for k, v := range l.fields { + data = append(data, zap.Any(k, v)) + } + l.RUnlock() + lvl := loggerToZapLevel(level) msg := fmt.Sprint(args...) switch lvl { case zap.DebugLevel: - l.zap.Debug(msg) + l.zap.Debug(msg, data...) case zap.InfoLevel: - l.zap.Info(msg) + l.zap.Info(msg, data...) case zap.WarnLevel: - l.zap.Warn(msg) + l.zap.Warn(msg, data...) case zap.ErrorLevel: - l.zap.Error(msg) + l.zap.Error(msg, data...) case zap.FatalLevel: - l.zap.Fatal(msg) + l.zap.Fatal(msg, data...) } } func (l *zaplog) Logf(level logger.Level, format string, args ...interface{}) { + l.RLock() + data := make([]zap.Field, 0, len(l.fields)) + for k, v := range l.fields { + data = append(data, zap.Any(k, v)) + } + l.RUnlock() + lvl := loggerToZapLevel(level) msg := fmt.Sprintf(format, args...) switch lvl { case zap.DebugLevel: - l.zap.Debug(msg) + l.zap.Debug(msg, data...) case zap.InfoLevel: - l.zap.Info(msg) + l.zap.Info(msg, data...) case zap.WarnLevel: - l.zap.Warn(msg) + l.zap.Warn(msg, data...) case zap.ErrorLevel: - l.zap.Error(msg) + l.zap.Error(msg, data...) case zap.FatalLevel: - l.zap.Fatal(msg) + l.zap.Fatal(msg, data...) } }