/
zap.go
102 lines (85 loc) · 2.47 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
package logger
import (
"errors"
"sort"
"time"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
var errEncodingNotSupported = errors.New("encoding not supported")
// NewLogger New is similar to Config.Build except that info and error logs are separated
// only json/console encoder is supported (zap doesn't provide a way to refer to other encoders)
func NewLogger(cfg zap.Config) (logger *zap.Logger, err error) {
sink, errSink, err := openSinks(cfg)
if err != nil {
return
}
var encoder zapcore.Encoder
switch cfg.Encoding {
case "json":
encoder = zapcore.NewJSONEncoder(cfg.EncoderConfig)
case "console":
encoder = zapcore.NewConsoleEncoder(cfg.EncoderConfig)
default:
err = errEncodingNotSupported
return
}
logLevel := cfg.Level.Level()
stdoutPriority := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
return lvl >= logLevel && lvl < zapcore.ErrorLevel
})
stderrPriority := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool {
return lvl >= zapcore.ErrorLevel
})
core := zapcore.NewTee(
zapcore.NewCore(encoder, sink, stdoutPriority),
zapcore.NewCore(encoder, errSink, stderrPriority),
)
return zap.New(core, buildOptions(cfg, errSink)...), nil
}
func openSinks(cfg zap.Config) (zapcore.WriteSyncer, zapcore.WriteSyncer, error) {
sink, closeOut, err := zap.Open(cfg.OutputPaths...)
if err != nil {
return nil, nil, err
}
errSink, _, err := zap.Open(cfg.ErrorOutputPaths...)
if err != nil {
closeOut()
return nil, nil, err
}
return sink, errSink, nil
}
func buildOptions(cfg zap.Config, errSink zapcore.WriteSyncer) []zap.Option {
opts := []zap.Option{zap.ErrorOutput(errSink)}
if cfg.Development {
opts = append(opts, zap.Development())
}
if cfg.DisableCaller {
opts = append(opts, zap.AddCaller())
}
stackLevel := zap.ErrorLevel
if cfg.Development {
stackLevel = zap.WarnLevel
}
if cfg.DisableStacktrace {
opts = append(opts, zap.AddStacktrace(stackLevel))
}
if cfg.Sampling != nil {
opts = append(opts, zap.WrapCore(func(core zapcore.Core) zapcore.Core {
return zapcore.NewSampler(core, time.Second, cfg.Sampling.Initial, cfg.Sampling.Thereafter)
}))
}
if len(cfg.InitialFields) > 0 {
fs := make([]zap.Field, 0, len(cfg.InitialFields))
keys := make([]string, 0, len(cfg.InitialFields))
for k := range cfg.InitialFields {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
fs = append(fs, zap.Any(k, cfg.InitialFields[k]))
}
opts = append(opts, zap.Fields(fs...))
}
return opts
}