From f88884123535bd057ff471a828930818ebcf50b1 Mon Sep 17 00:00:00 2001 From: Alvaro Aleman Date: Sat, 10 Aug 2019 13:30:42 +0200 Subject: [PATCH] :sparkles: Allow fine-grained configuration of log/zap --- pkg/log/zap/zap.go | 94 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 77 insertions(+), 17 deletions(-) diff --git a/pkg/log/zap/zap.go b/pkg/log/zap/zap.go index 5812e85bfb..bcefe66161 100644 --- a/pkg/log/zap/zap.go +++ b/pkg/log/zap/zap.go @@ -29,6 +29,11 @@ import ( "go.uber.org/zap/zapcore" ) +// New returns a brand new Logger configured with Opts +func New(opts ...Opts) logr.Logger { + return zapr.NewLogger(NewRaw(opts...)) +} + // Logger is a Logger implementation. // If development is true, a Zap development config will be used // (stacktraces on warnings, no sampling), otherwise a Zap production @@ -47,27 +52,82 @@ func LoggerTo(destWriter io.Writer, development bool) logr.Logger { // RawLoggerTo returns a new zap.Logger configured with KubeAwareEncoder // which logs to a given destination func RawLoggerTo(destWriter io.Writer, development bool, opts ...zap.Option) *zap.Logger { - // this basically mimics NewConfig, but with a custom sink - sink := zapcore.AddSync(destWriter) - - var enc zapcore.Encoder - var lvl zap.AtomicLevel - if development { - encCfg := zap.NewDevelopmentEncoderConfig() - enc = zapcore.NewConsoleEncoder(encCfg) - lvl = zap.NewAtomicLevelAt(zap.DebugLevel) - opts = append(opts, zap.Development(), zap.AddStacktrace(zap.ErrorLevel)) + o := func(o *Options) { + o.DestWritter = destWriter + o.Development = development + o.ZapOpts = opts + } + return NewRaw(o) +} + +// Opts allows to manipulate Options +type Opts func(*Options) + +// Options contains all possible settings +type Options struct { + // If Development is true, a Zap development config will be used + // (stacktraces on warnings, no sampling), otherwise a Zap production + // config will be used (stacktraces on errors, sampling). + Development bool + // The encoder to use, defaults to console when Development is true + // and JSON otherwise + Encoder zapcore.Encoder + // The destination to write to, defaults to os.Stderr + DestWritter io.Writer + // The level to use, defaults to Debug when Development is true and + // Info otherwise + Level *zap.AtomicLevel + // Raw zap.Options to configure on the underlying zap logger + ZapOpts []zap.Option +} + +// addDefaults adds defaults to the Options +func (o *Options) addDefaults() { + if o.DestWritter == nil { + o.DestWritter = os.Stderr + } + + if o.Development { + if o.Encoder == nil { + encCfg := zap.NewDevelopmentEncoderConfig() + o.Encoder = zapcore.NewConsoleEncoder(encCfg) + } + if o.Level == nil { + lvl := zap.NewAtomicLevelAt(zap.DebugLevel) + o.Level = &lvl + } + o.ZapOpts = append(o.ZapOpts, zap.Development(), zap.AddStacktrace(zap.ErrorLevel)) + } else { - encCfg := zap.NewProductionEncoderConfig() - enc = zapcore.NewJSONEncoder(encCfg) - lvl = zap.NewAtomicLevelAt(zap.InfoLevel) - opts = append(opts, zap.AddStacktrace(zap.WarnLevel), + if o.Encoder == nil { + encCfg := zap.NewProductionEncoderConfig() + o.Encoder = zapcore.NewJSONEncoder(encCfg) + } + if o.Level == nil { + lvl := zap.NewAtomicLevelAt(zap.InfoLevel) + o.Level = &lvl + } + o.ZapOpts = append(o.ZapOpts, zap.AddStacktrace(zap.WarnLevel), zap.WrapCore(func(core zapcore.Core) zapcore.Core { return zapcore.NewSampler(core, time.Second, 100, 100) })) } - opts = append(opts, zap.AddCallerSkip(1), zap.ErrorOutput(sink)) - log := zap.New(zapcore.NewCore(&KubeAwareEncoder{Encoder: enc, Verbose: development}, sink, lvl)) - log = log.WithOptions(opts...) +} + +// NewRaw returns a new zap.Logger configured with the passed Opts +// or their defaults +func NewRaw(opts ...Opts) *zap.Logger { + o := &Options{} + for _, opt := range opts { + opt(o) + } + o.addDefaults() + + // this basically mimics NewConfig, but with a custom sink + sink := zapcore.AddSync(o.DestWritter) + + o.ZapOpts = append(o.ZapOpts, zap.AddCallerSkip(1), zap.ErrorOutput(sink)) + log := zap.New(zapcore.NewCore(&KubeAwareEncoder{Encoder: o.Encoder, Verbose: o.Development}, sink, *o.Level)) + log = log.WithOptions(o.ZapOpts...) return log }