From e96ae7c42bc73a3be81c8a1502a83b0301690dcb Mon Sep 17 00:00:00 2001 From: Peter Edge Date: Thu, 6 Apr 2017 14:02:34 +0200 Subject: [PATCH 1/8] Add zapgrpc package --- zapgrpc/zapgrpc.go | 61 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 zapgrpc/zapgrpc.go diff --git a/zapgrpc/zapgrpc.go b/zapgrpc/zapgrpc.go new file mode 100644 index 000000000..33771cce0 --- /dev/null +++ b/zapgrpc/zapgrpc.go @@ -0,0 +1,61 @@ +// Copyright (c) 2017 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +// Package zapgrpc provides a logger that is compatible with grpclog. +package zapgrpc // import "go.uber.org/zap/zapgrpc" + +import "go.uber.org/zap" + +// Logger mimics grpclog's Logger interface. +type Logger interface { + Fatal(args ...interface{}) + Fatalf(format string, args ...interface{}) + Fatalln(args ...interface{}) + Print(args ...interface{}) + Printf(format string, args ...interface{}) + Println(args ...interface{}) +} + +// NewLogger returns a new Logger that wraps the given *zap.Logger. +// +// Print statements will log at the Info level. +func NewLogger(l *zap.Logger) Logger { + return &logger{l.Sugar()} +} + +type logger struct { + *zap.SugaredLogger +} + +func (l *logger) Fatalln(args ...interface{}) { + l.SugaredLogger.Fatal(args...) +} + +func (l *logger) Print(args ...interface{}) { + l.SugaredLogger.Info(args...) +} + +func (l *logger) Printf(format string, args ...interface{}) { + l.SugaredLogger.Infof(format, args...) +} + +func (l *logger) Println(args ...interface{}) { + l.SugaredLogger.Info(args...) +} From c8d7cb5e04e06e3c06f584faa871281064e8f99d Mon Sep 17 00:00:00 2001 From: Peter Edge Date: Thu, 6 Apr 2017 14:45:56 +0200 Subject: [PATCH 2/8] Updates to zapgrpc --- zapgrpc/zapgrpc.go | 90 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 68 insertions(+), 22 deletions(-) diff --git a/zapgrpc/zapgrpc.go b/zapgrpc/zapgrpc.go index 33771cce0..64ea50ae4 100644 --- a/zapgrpc/zapgrpc.go +++ b/zapgrpc/zapgrpc.go @@ -1,4 +1,4 @@ -// Copyright (c) 2017 Uber Technologies, Inc. +// Copyright (c) 2016 Uber Technologies, Inc. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -23,39 +23,85 @@ package zapgrpc // import "go.uber.org/zap/zapgrpc" import "go.uber.org/zap" -// Logger mimics grpclog's Logger interface. -type Logger interface { - Fatal(args ...interface{}) - Fatalf(format string, args ...interface{}) - Fatalln(args ...interface{}) - Print(args ...interface{}) - Printf(format string, args ...interface{}) - Println(args ...interface{}) +// LoggerOption is an option for a new Logger. +type LoggerOption func(*loggerOptions) + +// WithDebug says to print the debug level instead of the default info level. +func WithDebug() LoggerOption { + return func(loggerOptions *loggerOptions) { + loggerOptions.printFunc = (*zap.SugaredLogger).Debug + loggerOptions.printfFunc = (*zap.SugaredLogger).Debugf + } } -// NewLogger returns a new Logger that wraps the given *zap.Logger. +// NewLogger returns a new Logger. // // Print statements will log at the Info level. -func NewLogger(l *zap.Logger) Logger { - return &logger{l.Sugar()} +func NewLogger(l *zap.Logger, options ...LoggerOption) *Logger { + loggerOptions := newLoggerOptions(options...) + return &Logger{ + l.Sugar(), + (*zap.SugaredLogger).Fatal, + (*zap.SugaredLogger).Fatalf, + loggerOptions.printFunc, + loggerOptions.printfFunc, + } +} + +// Logger is a logger that is compatible with the grpclog Logger interface. +type Logger struct { + sugaredLogger *zap.SugaredLogger + fatalFunc func(*zap.SugaredLogger, ...interface{}) + fatalfFunc func(*zap.SugaredLogger, string, ...interface{}) + printFunc func(*zap.SugaredLogger, ...interface{}) + printfFunc func(*zap.SugaredLogger, string, ...interface{}) +} + +// Fatal implements grpclog.Logger#Fatal. +func (l *Logger) Fatal(args ...interface{}) { + l.fatalFunc(l.sugaredLogger, args...) +} + +// Fatalf implements grpclog.Logger#Fatalf. +func (l *Logger) Fatalf(format string, args ...interface{}) { + l.fatalfFunc(l.sugaredLogger, format, args...) +} + +// Fatalln implements grpclog.Logger#Fatalln. +func (l *Logger) Fatalln(args ...interface{}) { + l.fatalFunc(l.sugaredLogger, args...) } -type logger struct { - *zap.SugaredLogger +// Print implements grpclog.Logger#Print. +func (l *Logger) Print(args ...interface{}) { + l.printFunc(l.sugaredLogger, args...) } -func (l *logger) Fatalln(args ...interface{}) { - l.SugaredLogger.Fatal(args...) +// Printf implements grpclog.Logger#Printf. +func (l *Logger) Printf(format string, args ...interface{}) { + l.printfFunc(l.sugaredLogger, format, args...) } -func (l *logger) Print(args ...interface{}) { - l.SugaredLogger.Info(args...) +// Println implements grpclog.Logger#Println. +func (l *Logger) Println(args ...interface{}) { + l.printFunc(l.sugaredLogger, args...) } -func (l *logger) Printf(format string, args ...interface{}) { - l.SugaredLogger.Infof(format, args...) +type loggerOptions struct { + printFunc func(*zap.SugaredLogger, ...interface{}) + printfFunc func(*zap.SugaredLogger, string, ...interface{}) } -func (l *logger) Println(args ...interface{}) { - l.SugaredLogger.Info(args...) +func newLoggerOptions(options ...LoggerOption) *loggerOptions { + loggerOptions := &loggerOptions{} + for _, option := range options { + option(loggerOptions) + } + if loggerOptions.printFunc == nil { + loggerOptions.printFunc = (*zap.SugaredLogger).Info + } + if loggerOptions.printfFunc == nil { + loggerOptions.printfFunc = (*zap.SugaredLogger).Infof + } + return loggerOptions } From 23bd17a405403976f430ab1b44c67ef7b60bd004 Mon Sep 17 00:00:00 2001 From: Peter Edge Date: Thu, 6 Apr 2017 14:49:59 +0200 Subject: [PATCH 3/8] Clean up comments --- zapgrpc/zapgrpc.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/zapgrpc/zapgrpc.go b/zapgrpc/zapgrpc.go index 64ea50ae4..54b2d17ae 100644 --- a/zapgrpc/zapgrpc.go +++ b/zapgrpc/zapgrpc.go @@ -35,8 +35,6 @@ func WithDebug() LoggerOption { } // NewLogger returns a new Logger. -// -// Print statements will log at the Info level. func NewLogger(l *zap.Logger, options ...LoggerOption) *Logger { loggerOptions := newLoggerOptions(options...) return &Logger{ From 379bb7757cb331f1806b0aeb7bca9e4d2a8cc939 Mon Sep 17 00:00:00 2001 From: Peter Edge Date: Wed, 12 Apr 2017 21:08:54 +0200 Subject: [PATCH 4/8] Update zapgrpc LoggerOptions to take a Logger --- zapgrpc/zapgrpc.go | 38 +++++++++++--------------------------- 1 file changed, 11 insertions(+), 27 deletions(-) diff --git a/zapgrpc/zapgrpc.go b/zapgrpc/zapgrpc.go index 54b2d17ae..b48df8515 100644 --- a/zapgrpc/zapgrpc.go +++ b/zapgrpc/zapgrpc.go @@ -24,26 +24,29 @@ package zapgrpc // import "go.uber.org/zap/zapgrpc" import "go.uber.org/zap" // LoggerOption is an option for a new Logger. -type LoggerOption func(*loggerOptions) +type LoggerOption func(*Logger) // WithDebug says to print the debug level instead of the default info level. func WithDebug() LoggerOption { - return func(loggerOptions *loggerOptions) { - loggerOptions.printFunc = (*zap.SugaredLogger).Debug - loggerOptions.printfFunc = (*zap.SugaredLogger).Debugf + return func(logger *Logger) { + logger.printFunc = (*zap.SugaredLogger).Debug + logger.printfFunc = (*zap.SugaredLogger).Debugf } } // NewLogger returns a new Logger. func NewLogger(l *zap.Logger, options ...LoggerOption) *Logger { - loggerOptions := newLoggerOptions(options...) - return &Logger{ + logger := &Logger{ l.Sugar(), (*zap.SugaredLogger).Fatal, (*zap.SugaredLogger).Fatalf, - loggerOptions.printFunc, - loggerOptions.printfFunc, + (*zap.SugaredLogger).Info, + (*zap.SugaredLogger).Infof, } + for _, option := range options { + option(logger) + } + return logger } // Logger is a logger that is compatible with the grpclog Logger interface. @@ -84,22 +87,3 @@ func (l *Logger) Printf(format string, args ...interface{}) { func (l *Logger) Println(args ...interface{}) { l.printFunc(l.sugaredLogger, args...) } - -type loggerOptions struct { - printFunc func(*zap.SugaredLogger, ...interface{}) - printfFunc func(*zap.SugaredLogger, string, ...interface{}) -} - -func newLoggerOptions(options ...LoggerOption) *loggerOptions { - loggerOptions := &loggerOptions{} - for _, option := range options { - option(loggerOptions) - } - if loggerOptions.printFunc == nil { - loggerOptions.printFunc = (*zap.SugaredLogger).Info - } - if loggerOptions.printfFunc == nil { - loggerOptions.printfFunc = (*zap.SugaredLogger).Infof - } - return loggerOptions -} From a51186d1d77b82f02dd94e2638b42f6184860713 Mon Sep 17 00:00:00 2001 From: Peter Edge Date: Thu, 13 Apr 2017 12:50:14 +0200 Subject: [PATCH 5/8] Add testing for zapgrpc --- zapgrpc/zapgrpc_test.go | 96 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 zapgrpc/zapgrpc_test.go diff --git a/zapgrpc/zapgrpc_test.go b/zapgrpc/zapgrpc_test.go new file mode 100644 index 000000000..ffc869600 --- /dev/null +++ b/zapgrpc/zapgrpc_test.go @@ -0,0 +1,96 @@ +package zapgrpc + +import ( + "testing" + + "go.uber.org/zap" + "go.uber.org/zap/zapcore" + "go.uber.org/zap/zaptest/observer" + + "github.com/stretchr/testify/require" +) + +func TestLoggerInfoExpected(t *testing.T) { + checkMessages(t, zapcore.DebugLevel, nil, zapcore.InfoLevel, []string{ + "hello", + "world", + "foo", + }, func(logger *Logger) { + logger.Print("hello") + logger.Printf("world") + logger.Println("foo") + }) +} + +func TestLoggerDebugExpected(t *testing.T) { + checkMessages(t, zapcore.DebugLevel, []LoggerOption{WithDebug()}, zapcore.DebugLevel, []string{ + "hello", + "world", + "foo", + }, func(logger *Logger) { + logger.Print("hello") + logger.Printf("world") + logger.Println("foo") + }) +} + +func TestLoggerDebugSuppressed(t *testing.T) { + checkMessages(t, zapcore.InfoLevel, []LoggerOption{WithDebug()}, zapcore.DebugLevel, nil, func(logger *Logger) { + logger.Print("hello") + logger.Printf("world") + logger.Println("foo") + }) +} + +func TestLoggerFatalExpected(t *testing.T) { + checkMessages(t, zapcore.DebugLevel, nil, zapcore.FatalLevel, []string{ + "hello", + "world", + "foo", + }, func(logger *Logger) { + logger.Fatal("hello") + logger.Fatalf("world") + logger.Fatalln("foo") + }) +} + +func checkMessages( + t testing.TB, + levelEnabler zapcore.LevelEnabler, + loggerOptions []LoggerOption, + expectedLevel zapcore.Level, + expectedMessages []string, + f func(*Logger), +) { + if expectedLevel == zapcore.FatalLevel { + expectedLevel = zapcore.WarnLevel + } + withLogger(levelEnabler, loggerOptions, func(logger *Logger, observedLogs *observer.ObservedLogs) { + f(logger) + logEntries := observedLogs.All() + require.Equal(t, len(expectedMessages), len(logEntries)) + for i, logEntry := range logEntries { + require.Equal(t, expectedLevel, logEntry.Level) + require.Equal(t, expectedMessages[i], logEntry.Message) + } + }) +} + +func withLogger( + levelEnabler zapcore.LevelEnabler, + loggerOptions []LoggerOption, + f func(*Logger, *observer.ObservedLogs), +) { + core, observedLogs := observer.New(levelEnabler) + f(NewLogger(zap.New(core), append(loggerOptions, withWarn())...), observedLogs) +} + +// withWarn redirects the fatal level to the warn level. +// +// This is used for testing. +func withWarn() LoggerOption { + return func(logger *Logger) { + logger.fatalFunc = (*zap.SugaredLogger).Warn + logger.fatalfFunc = (*zap.SugaredLogger).Warnf + } +} From ca2270b3ce088dc85340823ef45d1c8b800341c3 Mon Sep 17 00:00:00 2001 From: Peter Edge Date: Thu, 13 Apr 2017 13:06:58 +0200 Subject: [PATCH 6/8] Fix lint --- zapgrpc/zapgrpc_test.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/zapgrpc/zapgrpc_test.go b/zapgrpc/zapgrpc_test.go index ffc869600..cd1526f66 100644 --- a/zapgrpc/zapgrpc_test.go +++ b/zapgrpc/zapgrpc_test.go @@ -1,3 +1,23 @@ +// Copyright (c) 2016 Uber Technologies, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + package zapgrpc import ( From fa1c1696eca6c42804d009ec726d77311cf0b0a0 Mon Sep 17 00:00:00 2001 From: Akshay Shah Date: Thu, 13 Apr 2017 21:33:29 -0700 Subject: [PATCH 7/8] Add zapgrpc to Makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d772c7ca5..efd28f8c7 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ export GO15VENDOREXPERIMENT=1 BENCH_FLAGS ?= -cpuprofile=cpu.pprof -memprofile=mem.pprof -benchmem PKGS ?= $(shell glide novendor) # Many Go tools take file globs or directories as arguments instead of packages. -PKG_FILES ?= *.go zapcore benchmarks buffer zaptest zaptest/observer internal/bufferpool internal/exit internal/multierror internal/color +PKG_FILES ?= *.go zapcore benchmarks buffer zapgrpc zaptest zaptest/observer internal/bufferpool internal/exit internal/multierror internal/color COVERALLS_IGNORE := internal/readme/readme.go From 35d347b464085f82646b8b47c5266a46360d170a Mon Sep 17 00:00:00 2001 From: Akshay Shah Date: Thu, 13 Apr 2017 21:45:24 -0700 Subject: [PATCH 8/8] Make options more opaque --- zapgrpc/zapgrpc.go | 77 +++++++++++++++++++++++------------------ zapgrpc/zapgrpc_test.go | 33 +++++++++--------- 2 files changed, 60 insertions(+), 50 deletions(-) diff --git a/zapgrpc/zapgrpc.go b/zapgrpc/zapgrpc.go index b48df8515..1181e6a0d 100644 --- a/zapgrpc/zapgrpc.go +++ b/zapgrpc/zapgrpc.go @@ -23,67 +23,78 @@ package zapgrpc // import "go.uber.org/zap/zapgrpc" import "go.uber.org/zap" -// LoggerOption is an option for a new Logger. -type LoggerOption func(*Logger) +// An Option overrides a Logger's default configuration. +type Option interface { + apply(*Logger) +} -// WithDebug says to print the debug level instead of the default info level. -func WithDebug() LoggerOption { - return func(logger *Logger) { - logger.printFunc = (*zap.SugaredLogger).Debug - logger.printfFunc = (*zap.SugaredLogger).Debugf - } +type optionFunc func(*Logger) + +func (f optionFunc) apply(log *Logger) { + f(log) +} + +// WithDebug configures a Logger to print at zap's DebugLevel instead of +// InfoLevel. +func WithDebug() Option { + return optionFunc(func(logger *Logger) { + logger.print = (*zap.SugaredLogger).Debug + logger.printf = (*zap.SugaredLogger).Debugf + }) } // NewLogger returns a new Logger. -func NewLogger(l *zap.Logger, options ...LoggerOption) *Logger { +// +// By default, Loggers print at zap's InfoLevel. +func NewLogger(l *zap.Logger, options ...Option) *Logger { logger := &Logger{ - l.Sugar(), - (*zap.SugaredLogger).Fatal, - (*zap.SugaredLogger).Fatalf, - (*zap.SugaredLogger).Info, - (*zap.SugaredLogger).Infof, + log: l.Sugar(), + fatal: (*zap.SugaredLogger).Fatal, + fatalf: (*zap.SugaredLogger).Fatalf, + print: (*zap.SugaredLogger).Info, + printf: (*zap.SugaredLogger).Infof, } for _, option := range options { - option(logger) + option.apply(logger) } return logger } -// Logger is a logger that is compatible with the grpclog Logger interface. +// Logger adapts zap's Logger to be compatible with grpclog.Logger. type Logger struct { - sugaredLogger *zap.SugaredLogger - fatalFunc func(*zap.SugaredLogger, ...interface{}) - fatalfFunc func(*zap.SugaredLogger, string, ...interface{}) - printFunc func(*zap.SugaredLogger, ...interface{}) - printfFunc func(*zap.SugaredLogger, string, ...interface{}) + log *zap.SugaredLogger + fatal func(*zap.SugaredLogger, ...interface{}) + fatalf func(*zap.SugaredLogger, string, ...interface{}) + print func(*zap.SugaredLogger, ...interface{}) + printf func(*zap.SugaredLogger, string, ...interface{}) } -// Fatal implements grpclog.Logger#Fatal. +// Fatal implements grpclog.Logger. func (l *Logger) Fatal(args ...interface{}) { - l.fatalFunc(l.sugaredLogger, args...) + l.fatal(l.log, args...) } -// Fatalf implements grpclog.Logger#Fatalf. +// Fatalf implements grpclog.Logger. func (l *Logger) Fatalf(format string, args ...interface{}) { - l.fatalfFunc(l.sugaredLogger, format, args...) + l.fatalf(l.log, format, args...) } -// Fatalln implements grpclog.Logger#Fatalln. +// Fatalln implements grpclog.Logger. func (l *Logger) Fatalln(args ...interface{}) { - l.fatalFunc(l.sugaredLogger, args...) + l.fatal(l.log, args...) } -// Print implements grpclog.Logger#Print. +// Print implements grpclog.Logger. func (l *Logger) Print(args ...interface{}) { - l.printFunc(l.sugaredLogger, args...) + l.print(l.log, args...) } -// Printf implements grpclog.Logger#Printf. +// Printf implements grpclog.Logger. func (l *Logger) Printf(format string, args ...interface{}) { - l.printfFunc(l.sugaredLogger, format, args...) + l.printf(l.log, format, args...) } -// Println implements grpclog.Logger#Println. +// Println implements grpclog.Logger. func (l *Logger) Println(args ...interface{}) { - l.printFunc(l.sugaredLogger, args...) + l.print(l.log, args...) } diff --git a/zapgrpc/zapgrpc_test.go b/zapgrpc/zapgrpc_test.go index cd1526f66..036f3d764 100644 --- a/zapgrpc/zapgrpc_test.go +++ b/zapgrpc/zapgrpc_test.go @@ -43,7 +43,7 @@ func TestLoggerInfoExpected(t *testing.T) { } func TestLoggerDebugExpected(t *testing.T) { - checkMessages(t, zapcore.DebugLevel, []LoggerOption{WithDebug()}, zapcore.DebugLevel, []string{ + checkMessages(t, zapcore.DebugLevel, []Option{WithDebug()}, zapcore.DebugLevel, []string{ "hello", "world", "foo", @@ -55,7 +55,7 @@ func TestLoggerDebugExpected(t *testing.T) { } func TestLoggerDebugSuppressed(t *testing.T) { - checkMessages(t, zapcore.InfoLevel, []LoggerOption{WithDebug()}, zapcore.DebugLevel, nil, func(logger *Logger) { + checkMessages(t, zapcore.InfoLevel, []Option{WithDebug()}, zapcore.DebugLevel, nil, func(logger *Logger) { logger.Print("hello") logger.Printf("world") logger.Println("foo") @@ -76,8 +76,8 @@ func TestLoggerFatalExpected(t *testing.T) { func checkMessages( t testing.TB, - levelEnabler zapcore.LevelEnabler, - loggerOptions []LoggerOption, + enab zapcore.LevelEnabler, + opts []Option, expectedLevel zapcore.Level, expectedMessages []string, f func(*Logger), @@ -85,7 +85,7 @@ func checkMessages( if expectedLevel == zapcore.FatalLevel { expectedLevel = zapcore.WarnLevel } - withLogger(levelEnabler, loggerOptions, func(logger *Logger, observedLogs *observer.ObservedLogs) { + withLogger(enab, opts, func(logger *Logger, observedLogs *observer.ObservedLogs) { f(logger) logEntries := observedLogs.All() require.Equal(t, len(expectedMessages), len(logEntries)) @@ -97,20 +97,19 @@ func checkMessages( } func withLogger( - levelEnabler zapcore.LevelEnabler, - loggerOptions []LoggerOption, + enab zapcore.LevelEnabler, + opts []Option, f func(*Logger, *observer.ObservedLogs), ) { - core, observedLogs := observer.New(levelEnabler) - f(NewLogger(zap.New(core), append(loggerOptions, withWarn())...), observedLogs) + core, observedLogs := observer.New(enab) + f(NewLogger(zap.New(core), append(opts, withWarn())...), observedLogs) } -// withWarn redirects the fatal level to the warn level. -// -// This is used for testing. -func withWarn() LoggerOption { - return func(logger *Logger) { - logger.fatalFunc = (*zap.SugaredLogger).Warn - logger.fatalfFunc = (*zap.SugaredLogger).Warnf - } +// withWarn redirects the fatal level to the warn level, which makes testing +// easier. +func withWarn() Option { + return optionFunc(func(logger *Logger) { + logger.fatal = (*zap.SugaredLogger).Warn + logger.fatalf = (*zap.SugaredLogger).Warnf + }) }