@@ -32,16 +32,17 @@ type LogOption = zap.Option
3232
3333// Logger logs messages to the configured output.
3434type Logger struct {
35- logger * zap.Logger
36- sugar * zap.SugaredLogger
35+ logger * zap.Logger
36+ sugar * zap.SugaredLogger
37+ selectors map [string ]struct {} // Set of enabled debug selectors.
3738}
3839
39- func newLogger (rootLogger * zap.Logger , selector string , options ... LogOption ) * Logger {
40+ func newLogger (rootLogger * zap.Logger , selector map [ string ] struct {} , options ... LogOption ) * Logger {
4041 log := rootLogger .
4142 WithOptions (zap .AddCallerSkip (1 )).
42- WithOptions (options ... ).
43- Named ( selector )
44- return & Logger {log , log .Sugar ()}
43+ WithOptions (options ... )
44+
45+ return & Logger {log , log .Sugar (), selector }
4546}
4647
4748// NewLogger returns a new Logger labeled with the name of the selector. This
@@ -50,13 +51,14 @@ func newLogger(rootLogger *zap.Logger, selector string, options ...LogOption) *L
5051// Instead create new Logger instance that your object reuses. Or if you need to
5152// log from a static context then you may use logp.L().Infow(), for example.
5253func NewLogger (selector string , options ... LogOption ) * Logger {
53- return newLogger (loadLogger ().rootLogger , selector , options ... )
54+ logger := loadLogger ().rootLogger .Named (selector )
55+ return newLogger (logger , make (map [string ]struct {}), options ... )
5456}
5557
5658// NewNopLogger returns a no-op logger
5759func NewNopLogger () * Logger {
5860 logger := zap .NewNop ()
59- return & Logger {logger , logger .Sugar ()}
61+ return & Logger {logger , logger .Sugar (), make ( map [ string ] struct {}) }
6062}
6163
6264// NewProductionLogger returns a production suitable logp.Logger
@@ -66,7 +68,7 @@ func NewProductionLogger(selector string, options ...LogOption) (*Logger, error)
6668 if err != nil {
6769 return nil , err
6870 }
69- return & Logger {log , log .Sugar ()}, nil
71+ return & Logger {log , log .Sugar (), make ( map [ string ] struct {}) }, nil
7072}
7173
7274// NewDevelopmentLogger returns a development suitable logp.Logger
@@ -83,7 +85,7 @@ func NewDevelopmentLogger(selector string, options ...LogOption) (*Logger, error
8385 if err != nil {
8486 return nil , err
8587 }
86- return & Logger {logger , logger .Sugar ()}, nil
88+ return & Logger {logger , logger .Sugar (), make ( map [ string ] struct {}) }, nil
8789}
8890
8991// NewInMemory returns a new in-memory logger along with the buffer to which it
@@ -144,24 +146,30 @@ func NewInMemoryLocal(selector string, encCfg zapcore.EncoderConfig) (*Logger, *
144146 return logger , & buff
145147}
146148
149+ // HasSelector returns true if the given selector was explicitly set.
150+ func (l * Logger ) HasSelector (selector string ) bool {
151+ _ , found := l .selectors [selector ]
152+ return found
153+ }
154+
147155// WithOptions returns a clone of l with options applied.
148156func (l * Logger ) WithOptions (options ... LogOption ) * Logger {
149157 cloned := l .logger .WithOptions (options ... )
150- return & Logger {cloned , cloned .Sugar ()}
158+ return & Logger {cloned , cloned .Sugar (), l . selectors }
151159}
152160
153161// With creates a child logger and adds structured context to it. Fields added
154162// to the child don't affect the parent, and vice versa.
155163func (l * Logger ) With (args ... interface {}) * Logger {
156164 sugar := l .sugar .With (args ... )
157- return & Logger {sugar .Desugar (), sugar }
165+ return & Logger {sugar .Desugar (), sugar , l . selectors }
158166}
159167
160168// Named adds a new path segment to the logger's name. Segments are joined by
161169// periods.
162170func (l * Logger ) Named (name string ) * Logger {
163171 logger := l .logger .Named (name )
164- return & Logger {logger , logger .Sugar ()}
172+ return & Logger {logger , logger .Sugar (), l . selectors }
165173}
166174
167175// Sprint
0 commit comments