diff --git a/logger/default.go b/logger/default.go index 782a1230..968ed76e 100644 --- a/logger/default.go +++ b/logger/default.go @@ -39,6 +39,28 @@ func (l *defaultLogger) String() string { return "micro" } +func (l *defaultLogger) Clone(opts ...Option) Logger { + newopts := NewOptions(opts...) + oldopts := l.opts + for _, o := range opts { + o(&newopts) + o(&oldopts) + } + + oldopts.Wrappers = newopts.Wrappers + l.Lock() + cl := &defaultLogger{opts: oldopts, logFunc: l.logFunc, logfFunc: l.logfFunc} + l.Unlock() + + // wrap the Log func + for i := len(newopts.Wrappers); i > 0; i-- { + cl.logFunc = newopts.Wrappers[i-1].Log(cl.logFunc) + cl.logfFunc = newopts.Wrappers[i-1].Logf(cl.logfFunc) + } + + return cl +} + func (l *defaultLogger) V(level Level) bool { l.RLock() ok := l.opts.Level.Enabled(level) @@ -46,6 +68,12 @@ func (l *defaultLogger) V(level Level) bool { return ok } +func (l *defaultLogger) Level(level Level) { + l.Lock() + l.opts.Level = level + l.Unlock() +} + func (l *defaultLogger) Fields(fields ...interface{}) Logger { nl := &defaultLogger{opts: l.opts, enc: l.enc} if len(fields) == 0 { diff --git a/logger/logger.go b/logger/logger.go index 656769e3..f991cc15 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -19,8 +19,12 @@ var ( type Logger interface { // Init initialises options Init(opts ...Option) error + // Clone create logger copy with new options + Clone(opts ...Option) Logger // V compare provided verbosity level with current log level V(level Level) bool + // Level sets the log level for logger + Level(level Level) // The Logger options Options() Options // Fields set fields to always be logged with keyval pairs diff --git a/logger/logger_test.go b/logger/logger_test.go index 576c1a02..ef23f6eb 100644 --- a/logger/logger_test.go +++ b/logger/logger_test.go @@ -7,6 +7,27 @@ import ( "testing" ) +func TestClone(t *testing.T) { + ctx := context.TODO() + buf := bytes.NewBuffer(nil) + l := NewLogger(WithLevel(TraceLevel), WithOutput(buf)) + if err := l.Init(); err != nil { + t.Fatal(err) + } + nl := l.Clone(WithLevel(ErrorLevel)) + if err := nl.Init(); err != nil { + t.Fatal(err) + } + nl.Info(ctx, "info message") + if len(buf.Bytes()) != 0 { + t.Fatal("message must not be logged") + } + l.Info(ctx, "info message") + if len(buf.Bytes()) == 0 { + t.Fatal("message must be logged") + } +} + func TestRedirectStdLogger(t *testing.T) { buf := bytes.NewBuffer(nil) l := NewLogger(WithLevel(TraceLevel), WithOutput(buf)) diff --git a/logger/wrapper.go b/logger/wrapper.go index 48b90ab5..3e8d8f46 100644 --- a/logger/wrapper.go +++ b/logger/wrapper.go @@ -20,9 +20,7 @@ type Wrapper interface { Logf(LogfFunc) LogfFunc } -var ( - _ Logger = &OmitLogger{} -) +var _ Logger = &OmitLogger{} type OmitLogger struct { l Logger @@ -40,6 +38,14 @@ func (w *OmitLogger) V(level Level) bool { return w.l.V(level) } +func (w *OmitLogger) Level(level Level) { + w.l.Level(level) +} + +func (w *OmitLogger) Clone(opts ...Option) Logger { + return w.l.Clone(opts...) +} + func (w *OmitLogger) Options() Options { return w.l.Options() }