fix zaplogger field duplication

Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
This commit is contained in:
Василий Толстов 2020-03-04 01:04:22 +03:00
parent 4574e9ab74
commit f2ca0bc9d9
2 changed files with 49 additions and 15 deletions

View File

@ -11,6 +11,12 @@ type Options struct {
logger.Options logger.Options
} }
type callerSkipKey struct{}
func WithCallerSkip(i int) logger.Option {
return logger.SetOption(callerSkipKey{}, i)
}
type configKey struct{} type configKey struct{}
// WithConfig pass zap.Config to logger // WithConfig pass zap.Config to logger

58
zap.go
View File

@ -4,6 +4,7 @@ import (
"context" "context"
"fmt" "fmt"
"os" "os"
"sync"
"go.uber.org/zap" "go.uber.org/zap"
"go.uber.org/zap/zapcore" "go.uber.org/zap/zapcore"
@ -15,6 +16,8 @@ type zaplog struct {
cfg zap.Config cfg zap.Config
zap *zap.Logger zap *zap.Logger
opts logger.Options opts logger.Options
sync.RWMutex
fields map[string]interface{}
} }
func (l *zaplog) Init(opts ...logger.Option) error { 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 // Set log Level if not default
zapConfig.Level = zap.NewAtomicLevel() zapConfig.Level = zap.NewAtomicLevel()
if l.opts.Level != logger.InfoLevel { if l.opts.Level != logger.InfoLevel {
zapConfig.Level.SetLevel(loggerToZapLevel(l.opts.Level)) zapConfig.Level.SetLevel(loggerToZapLevel(l.opts.Level))
} }
log, err := zapConfig.Build() log, err := zapConfig.Build(zap.AddCallerSkip(skip))
if err != nil { if err != nil {
return err return err
} }
@ -63,55 +71,75 @@ func (l *zaplog) Init(opts ...logger.Option) error {
l.cfg = zapConfig l.cfg = zapConfig
l.zap = log l.zap = log
l.fields = make(map[string]interface{})
return nil return nil
} }
func (l *zaplog) Fields(fields map[string]interface{}) logger.Logger { 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 { 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 return l
} }
func (l *zaplog) Error(err error) logger.Logger { 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 return l
} }
func (l *zaplog) Log(level logger.Level, args ...interface{}) { 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) lvl := loggerToZapLevel(level)
msg := fmt.Sprint(args...) msg := fmt.Sprint(args...)
switch lvl { switch lvl {
case zap.DebugLevel: case zap.DebugLevel:
l.zap.Debug(msg) l.zap.Debug(msg, data...)
case zap.InfoLevel: case zap.InfoLevel:
l.zap.Info(msg) l.zap.Info(msg, data...)
case zap.WarnLevel: case zap.WarnLevel:
l.zap.Warn(msg) l.zap.Warn(msg, data...)
case zap.ErrorLevel: case zap.ErrorLevel:
l.zap.Error(msg) l.zap.Error(msg, data...)
case zap.FatalLevel: case zap.FatalLevel:
l.zap.Fatal(msg) l.zap.Fatal(msg, data...)
} }
} }
func (l *zaplog) Logf(level logger.Level, format string, args ...interface{}) { 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) lvl := loggerToZapLevel(level)
msg := fmt.Sprintf(format, args...) msg := fmt.Sprintf(format, args...)
switch lvl { switch lvl {
case zap.DebugLevel: case zap.DebugLevel:
l.zap.Debug(msg) l.zap.Debug(msg, data...)
case zap.InfoLevel: case zap.InfoLevel:
l.zap.Info(msg) l.zap.Info(msg, data...)
case zap.WarnLevel: case zap.WarnLevel:
l.zap.Warn(msg) l.zap.Warn(msg, data...)
case zap.ErrorLevel: case zap.ErrorLevel:
l.zap.Error(msg) l.zap.Error(msg, data...)
case zap.FatalLevel: case zap.FatalLevel:
l.zap.Fatal(msg) l.zap.Fatal(msg, data...)
} }
} }