This repository has been archived by the owner on Jul 19, 2023. It is now read-only.
/
zap.go
122 lines (104 loc) · 2.89 KB
/
zap.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// Package zap implements the logger.Logger interface using uber/zap implementation.
package zap
import (
"errors"
"fmt"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"github.com/krostar/logger"
)
// Zap implements Logger interface.
type Zap struct {
*zap.SugaredLogger
level *zap.AtomicLevel
}
// New returns a new zap instance.
func New(opts ...Option) (logger.Logger, func() error, error) {
config := config{
Level: zapcore.InfoLevel,
Zap: zap.Config{
Development: false,
DisableCaller: true,
DisableStacktrace: true,
OutputPaths: []string{"stdout"},
ErrorOutputPaths: []string{"stderr"},
Encoding: "json",
EncoderConfig: zapcore.EncoderConfig{
MessageKey: "msg",
LineEnding: zapcore.DefaultLineEnding,
LevelKey: "lvl",
EncodeLevel: zapcore.LowercaseLevelEncoder,
TimeKey: "time",
EncodeTime: zapcore.ISO8601TimeEncoder,
EncodeDuration: zapcore.SecondsDurationEncoder,
CallerKey: "caller",
EncodeCaller: zapcore.ShortCallerEncoder,
},
},
}
for _, opt := range opts {
if err := opt(&config); err != nil {
return nil, nil, fmt.Errorf("unable to apply config: %w", err)
}
}
atomiclevel := zap.NewAtomicLevelAt(config.Level)
config.Zap.Level = atomiclevel
logger, err := config.Zap.Build()
if err != nil {
return nil, nil, fmt.Errorf("unable to create logger: %w", err)
}
return &Zap{
level: &atomiclevel,
SugaredLogger: logger.Sugar(),
}, logger.Sync, nil
}
func convertLevel(level logger.Level) (zapcore.Level, error) {
var zapLevel zapcore.Level
switch level {
case logger.LevelDebug:
zapLevel = zapcore.DebugLevel
case logger.LevelInfo:
zapLevel = zapcore.InfoLevel
case logger.LevelWarn:
zapLevel = zapcore.WarnLevel
case logger.LevelError:
zapLevel = zapcore.ErrorLevel
default:
return zapLevel, errors.New("level conversion to zap level impossible")
}
return zapLevel, nil
}
// SetLevel applies a new level to a logger instance.
func (l *Zap) SetLevel(level logger.Level) error {
zapLevel, err := convertLevel(level)
if err != nil {
return fmt.Errorf("logger level parsing to zap level failed: %w", err)
}
(l.level).SetLevel(zapLevel)
return nil
}
// WithField implements Logger.WithField for Zap logger.
func (l *Zap) WithField(key string, value interface{}) logger.Logger {
return &Zap{
level: l.level,
SugaredLogger: l.With(key, value),
}
}
// WithFields implements Logger.WithFields for Zap logger.
func (l *Zap) WithFields(fields map[string]interface{}) logger.Logger {
var f []interface{}
for key, value := range fields {
f = append(f, []interface{}{key, value}...)
}
return &Zap{
level: l.level,
SugaredLogger: l.With(f...),
}
}
// WithError implements Logger.WithError for Zap logger.
func (l *Zap) WithError(err error) logger.Logger {
if err != nil {
return l.WithField(logger.FieldErrorKey, err.Error())
}
return l
}