Skip to content

Commit 9591248

Browse files
Dmitry Kropachevdkropachev
Dmitry Kropachev
authored andcommitted
Add option to override sink and encoder (#1438)
Makes it possible to override/wrap encoder/sink
1 parent 4425037 commit 9591248

File tree

2 files changed

+64
-7
lines changed

2 files changed

+64
-7
lines changed

config.go

+26-7
Original file line numberDiff line numberDiff line change
@@ -237,12 +237,12 @@ func NewDevelopmentConfig() Config {
237237

238238
// Build constructs a logger from the Config and Options.
239239
func (cfg Config) Build(opts ...Option) (*Logger, error) {
240-
enc, err := cfg.buildEncoder()
240+
enc, err := cfg.buildEncoder(filterOptions[wrapEncoderOption](opts...)...)
241241
if err != nil {
242242
return nil, err
243243
}
244244

245-
sink, errSink, err := cfg.openSinks()
245+
sink, errSink, err := cfg.openSinks(filterOptions[wrapSinkerOption](opts...)...)
246246
if err != nil {
247247
return nil, err
248248
}
@@ -256,7 +256,7 @@ func (cfg Config) Build(opts ...Option) (*Logger, error) {
256256
cfg.buildOptions(errSink)...,
257257
)
258258
if len(opts) > 0 {
259-
log = log.WithOptions(opts...)
259+
log = log.WithOptions(filterOptions[Option](opts...)...)
260260
}
261261
return log, nil
262262
}
@@ -312,19 +312,38 @@ func (cfg Config) buildOptions(errSink zapcore.WriteSyncer) []Option {
312312
return opts
313313
}
314314

315-
func (cfg Config) openSinks() (zapcore.WriteSyncer, zapcore.WriteSyncer, error) {
315+
func (cfg Config) openSinks(opts ...wrapSinkerOption) (zapcore.WriteSyncer, zapcore.WriteSyncer, error) {
316316
sink, closeOut, err := Open(cfg.OutputPaths...)
317317
if err != nil {
318318
return nil, nil, err
319319
}
320-
errSink, _, err := Open(cfg.ErrorOutputPaths...)
320+
errSink, errCloseOut, err := Open(cfg.ErrorOutputPaths...)
321321
if err != nil {
322322
closeOut()
323323
return nil, nil, err
324324
}
325+
326+
for _, opt := range opts {
327+
sink, errSink, err = opt.wrapSink(cfg.OutputPaths, sink, cfg.ErrorOutputPaths, errSink)
328+
if err != nil {
329+
closeOut()
330+
errCloseOut()
331+
return nil, nil, err
332+
}
333+
}
325334
return sink, errSink, nil
326335
}
327336

328-
func (cfg Config) buildEncoder() (zapcore.Encoder, error) {
329-
return newEncoder(cfg.Encoding, cfg.EncoderConfig)
337+
func (cfg Config) buildEncoder(opts ...wrapEncoderOption) (zapcore.Encoder, error) {
338+
enc, err := newEncoder(cfg.Encoding, cfg.EncoderConfig)
339+
if err != nil {
340+
return nil, err
341+
}
342+
for _, opt := range opts {
343+
enc, err = opt.wrapEncoder(cfg.Encoding, cfg.EncoderConfig, enc)
344+
if err != nil {
345+
return nil, err
346+
}
347+
}
348+
return enc, nil
330349
}

options.go

+38
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,49 @@ import (
2626
"go.uber.org/zap/zapcore"
2727
)
2828

29+
func filterOptions[T Option](in ...Option) []T {
30+
var opts []T
31+
for _, opt := range in {
32+
if o, ok := opt.(T); ok {
33+
opts = append(opts, o)
34+
}
35+
}
36+
return opts
37+
}
38+
2939
// An Option configures a Logger.
3040
type Option interface {
3141
apply(*Logger)
3242
}
3343

44+
// wrapEncoderOption wraps a func to make it satisfy the WrapEncoderOption interface.
45+
type wrapEncoderOption func(encoding string, cfg zapcore.EncoderConfig, encoder zapcore.Encoder) (zapcore.Encoder, error)
46+
47+
func (f wrapEncoderOption) wrapEncoder(encoding string, cfg zapcore.EncoderConfig, encoder zapcore.Encoder) (zapcore.Encoder, error) {
48+
return f(encoding, cfg, encoder)
49+
}
50+
51+
func (f wrapEncoderOption) apply(_ *Logger) {}
52+
53+
// WrapEncoder wraps or replaces the Logger's underlying zapcore.Encoder.
54+
func WrapEncoder(fn func(encoding string, cfg zapcore.EncoderConfig, encoder zapcore.Encoder) (zapcore.Encoder, error)) Option {
55+
return wrapEncoderOption(fn)
56+
}
57+
58+
// wrapEncoderOption wraps a func to make it satisfy the WrapSinkersOption interface.
59+
type wrapSinkerOption func(paths []string, sink zapcore.WriteSyncer, errPath []string, errSink zapcore.WriteSyncer) (zapcore.WriteSyncer, zapcore.WriteSyncer, error)
60+
61+
func (f wrapSinkerOption) wrapSink(paths []string, sink zapcore.WriteSyncer, errPath []string, errSink zapcore.WriteSyncer) (zapcore.WriteSyncer, zapcore.WriteSyncer, error) {
62+
return f(paths, sink, errPath, errSink)
63+
}
64+
65+
func (f wrapSinkerOption) apply(_ *Logger) {}
66+
67+
// WrapSinker wraps or replaces the Logger's underlying zapcore.Encoder.
68+
func WrapSinker(fn func(paths []string, sink zapcore.WriteSyncer, errPath []string, errSink zapcore.WriteSyncer) (zapcore.WriteSyncer, zapcore.WriteSyncer, error)) Option {
69+
return wrapSinkerOption(fn)
70+
}
71+
3472
// optionFunc wraps a func so it satisfies the Option interface.
3573
type optionFunc func(*Logger)
3674

0 commit comments

Comments
 (0)