Skip to content

Commit d90bbc6

Browse files
authored
Merge pull request #560 from alvaroaleman/logger-config
✨ Allow fine-grained configuration of log/zap
2 parents 7b08fd6 + e825f3a commit d90bbc6

File tree

1 file changed

+113
-17
lines changed

1 file changed

+113
-17
lines changed

pkg/log/zap/zap.go

Lines changed: 113 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -29,45 +29,141 @@ import (
2929
"go.uber.org/zap/zapcore"
3030
)
3131

32+
// New returns a brand new Logger configured with Opts. It
33+
// uses KubeAwareEncoder which adds Type information and
34+
// Namespace/Name to the log.
35+
func New(opts ...Opts) logr.Logger {
36+
return zapr.NewLogger(NewRaw(opts...))
37+
}
38+
3239
// Logger is a Logger implementation.
3340
// If development is true, a Zap development config will be used
3441
// (stacktraces on warnings, no sampling), otherwise a Zap production
3542
// config will be used (stacktraces on errors, sampling).
43+
//
44+
// Deprecated, use New() and the functional opts pattern instead:
45+
//
46+
// New(func(o *Options){
47+
// o.Development: development,
48+
// })
3649
func Logger(development bool) logr.Logger {
3750
return LoggerTo(os.Stderr, development)
3851
}
3952

4053
// LoggerTo returns a new Logger implementation using Zap which logs
4154
// to the given destination, instead of stderr. It otherwise behaves like
4255
// ZapLogger.
56+
//
57+
// Deprecated, use New() and the functional opts pattern instead:
58+
//
59+
// New(func(o *Options){
60+
// o.Development: development,
61+
// o.DestWriter: writer,
62+
// })
4363
func LoggerTo(destWriter io.Writer, development bool) logr.Logger {
4464
return zapr.NewLogger(RawLoggerTo(destWriter, development))
4565
}
4666

4767
// RawLoggerTo returns a new zap.Logger configured with KubeAwareEncoder
4868
// which logs to a given destination
69+
//
70+
// Deprecated, use NewRaw() and the functional opts pattern instead:
71+
//
72+
// NewRaw(func(o *Options){
73+
// o.Development: development,
74+
// })
4975
func RawLoggerTo(destWriter io.Writer, development bool, opts ...zap.Option) *zap.Logger {
50-
// this basically mimics New<type>Config, but with a custom sink
51-
sink := zapcore.AddSync(destWriter)
52-
53-
var enc zapcore.Encoder
54-
var lvl zap.AtomicLevel
55-
if development {
56-
encCfg := zap.NewDevelopmentEncoderConfig()
57-
enc = zapcore.NewConsoleEncoder(encCfg)
58-
lvl = zap.NewAtomicLevelAt(zap.DebugLevel)
59-
opts = append(opts, zap.Development(), zap.AddStacktrace(zap.ErrorLevel))
76+
o := func(o *Options) {
77+
o.DestWritter = destWriter
78+
o.Development = development
79+
o.ZapOpts = opts
80+
}
81+
return NewRaw(o)
82+
}
83+
84+
// Opts allows to manipulate Options
85+
type Opts func(*Options)
86+
87+
// Options contains all possible settings
88+
type Options struct {
89+
// If Development is true, a Zap development config will be used
90+
// (stacktraces on warnings, no sampling), otherwise a Zap production
91+
// config will be used (stacktraces on errors, sampling).
92+
Development bool
93+
// The encoder to use, defaults to console when Development is true
94+
// and JSON otherwise
95+
Encoder zapcore.Encoder
96+
// The destination to write to, defaults to os.Stderr
97+
DestWritter io.Writer
98+
// The level to use, defaults to Debug when Development is true and
99+
// Info otherwise
100+
Level *zap.AtomicLevel
101+
// StacktraceLevel is the level at and above which stacktraces will
102+
// be recorded for all messages. Defaults to Warn when Development
103+
// is true and Error otherwise
104+
StacktraceLevel *zap.AtomicLevel
105+
// Raw zap.Options to configure on the underlying zap logger
106+
ZapOpts []zap.Option
107+
}
108+
109+
// addDefaults adds defaults to the Options
110+
func (o *Options) addDefaults() {
111+
if o.DestWritter == nil {
112+
o.DestWritter = os.Stderr
113+
}
114+
115+
if o.Development {
116+
if o.Encoder == nil {
117+
encCfg := zap.NewDevelopmentEncoderConfig()
118+
o.Encoder = zapcore.NewConsoleEncoder(encCfg)
119+
}
120+
if o.Level == nil {
121+
lvl := zap.NewAtomicLevelAt(zap.DebugLevel)
122+
o.Level = &lvl
123+
}
124+
if o.StacktraceLevel == nil {
125+
lvl := zap.NewAtomicLevelAt(zap.WarnLevel)
126+
o.StacktraceLevel = &lvl
127+
}
128+
o.ZapOpts = append(o.ZapOpts, zap.Development())
129+
60130
} else {
61-
encCfg := zap.NewProductionEncoderConfig()
62-
enc = zapcore.NewJSONEncoder(encCfg)
63-
lvl = zap.NewAtomicLevelAt(zap.InfoLevel)
64-
opts = append(opts, zap.AddStacktrace(zap.WarnLevel),
131+
if o.Encoder == nil {
132+
encCfg := zap.NewProductionEncoderConfig()
133+
o.Encoder = zapcore.NewJSONEncoder(encCfg)
134+
}
135+
if o.Level == nil {
136+
lvl := zap.NewAtomicLevelAt(zap.InfoLevel)
137+
o.Level = &lvl
138+
}
139+
if o.StacktraceLevel == nil {
140+
lvl := zap.NewAtomicLevelAt(zap.ErrorLevel)
141+
o.StacktraceLevel = &lvl
142+
}
143+
o.ZapOpts = append(o.ZapOpts,
65144
zap.WrapCore(func(core zapcore.Core) zapcore.Core {
66145
return zapcore.NewSampler(core, time.Second, 100, 100)
67146
}))
68147
}
69-
opts = append(opts, zap.AddCallerSkip(1), zap.ErrorOutput(sink))
70-
log := zap.New(zapcore.NewCore(&KubeAwareEncoder{Encoder: enc, Verbose: development}, sink, lvl))
71-
log = log.WithOptions(opts...)
148+
149+
o.ZapOpts = append(o.ZapOpts, zap.AddStacktrace(o.StacktraceLevel))
150+
}
151+
152+
// NewRaw returns a new zap.Logger configured with the passed Opts
153+
// or their defaults. It uses KubeAwareEncoder which adds Type
154+
// information and Namespace/Name to the log.
155+
func NewRaw(opts ...Opts) *zap.Logger {
156+
o := &Options{}
157+
for _, opt := range opts {
158+
opt(o)
159+
}
160+
o.addDefaults()
161+
162+
// this basically mimics New<type>Config, but with a custom sink
163+
sink := zapcore.AddSync(o.DestWritter)
164+
165+
o.ZapOpts = append(o.ZapOpts, zap.AddCallerSkip(1), zap.ErrorOutput(sink))
166+
log := zap.New(zapcore.NewCore(&KubeAwareEncoder{Encoder: o.Encoder, Verbose: o.Development}, sink, *o.Level))
167+
log = log.WithOptions(o.ZapOpts...)
72168
return log
73169
}

0 commit comments

Comments
 (0)