Skip to content

Commit f9effc9

Browse files
committed
Implement BlockSelectors for level debug
This commit implements a block list of selectors for debug logging on `logp`.
1 parent 0c0f99a commit f9effc9

File tree

5 files changed

+70
-8
lines changed

5 files changed

+70
-8
lines changed

logp/config.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,10 @@ import (
2424
// Config contains the configuration options for the logger. To create a Config
2525
// from a common.Config use logp/config.Build.
2626
type Config struct {
27-
Beat string `config:",ignore"` // Name of the Beat (for default file name).
28-
Level Level `config:"level"` // Logging level (error, warning, info, debug).
29-
Selectors []string `config:"selectors"` // Selectors for debug level logging.
27+
Beat string `config:",ignore"` // Name of the Beat (for default file name).
28+
Level Level `config:"level"` // Logging level (error, warning, info, debug).
29+
Selectors []string `config:"selectors"` // Selectors for debug level logging.
30+
BlockList []string `config:"block_list"` // Block list of selectors for debug logging.
3031

3132
toObserver bool
3233
toIODiscard bool

logp/core.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ func init() {
5757

5858
type coreLogger struct {
5959
selectors map[string]struct{} // Set of enabled debug selectors.
60+
blockList map[string]struct{} // Set of blocked debug selectors.
6061
rootLogger *zap.Logger // Root logger without any options configured.
6162
globalLogger *zap.Logger // Logger used by legacy global functions (e.g. logp.Info).
6263
logger *Logger // Logger that is the basis for all logp.Loggers.
@@ -97,7 +98,12 @@ func ConfigureWithOutputs(cfg Config, outputs ...zapcore.Core) error {
9798

9899
// Enabled selectors when debug is enabled.
99100
selectors := make(map[string]struct{}, len(cfg.Selectors))
100-
if cfg.Level.Enabled(DebugLevel) && len(cfg.Selectors) > 0 {
101+
blockList := make(map[string]struct{}, len(cfg.BlockList))
102+
if cfg.Level.Enabled(DebugLevel) && (len(cfg.Selectors) > 0 || len(cfg.BlockList) > 0) {
103+
for _, sel := range cfg.BlockList {
104+
blockList[strings.TrimSpace(sel)] = struct{}{}
105+
}
106+
101107
for _, sel := range cfg.Selectors {
102108
selectors[strings.TrimSpace(sel)] = struct{}{}
103109
}
@@ -115,13 +121,14 @@ func ConfigureWithOutputs(cfg Config, outputs ...zapcore.Core) error {
115121
golog.SetOutput(_defaultGoLog)
116122
}
117123

118-
sink = selectiveWrapper(sink, selectors)
124+
sink = selectiveWrapper(sink, selectors, blockList)
119125
}
120126

121127
sink = newMultiCore(append(outputs, sink)...)
122128
root := zap.New(sink, makeOptions(cfg)...)
123129
storeLogger(&coreLogger{
124130
selectors: selectors,
131+
blockList: blockList,
125132
rootLogger: root,
126133
globalLogger: root.WithOptions(zap.AddCallerSkip(1)),
127134
logger: newLogger(root, ""),

logp/options.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ func WithSelectors(selectors ...string) Option {
3535
}
3636
}
3737

38+
// WithBlockList specifies what debug selectors are disabled. If no selectors
39+
// are specified, then nothing is blocked
40+
func WithBlockList(blockList ...string) Option {
41+
return func(cfg *Config) {
42+
cfg.BlockList = append(cfg.BlockList, blockList...)
43+
}
44+
}
45+
3846
// ToObserverOutput specifies that the output should be collected in memory so
3947
// that they can be read by an observer by calling ObserverLogs().
4048
func ToObserverOutput() Option {

logp/selective.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
type selectiveCore struct {
2525
allSelectors bool
2626
selectors map[string]struct{}
27+
blockList map[string]struct{}
2728
core zapcore.Core
2829
}
2930

@@ -33,12 +34,24 @@ func HasSelector(selector string) bool {
3334
return found
3435
}
3536

36-
func selectiveWrapper(core zapcore.Core, selectors map[string]struct{}) zapcore.Core {
37+
// IsBlocked returns true if the given selector was explicitly set.
38+
func IsBlocked(selector string) bool {
39+
l := loadLogger()
40+
_, found := l.blockList[selector]
41+
return found
42+
}
43+
44+
func selectiveWrapper(core zapcore.Core, selectors, blockList map[string]struct{}) zapcore.Core {
3745
if len(selectors) == 0 {
3846
return core
3947
}
4048
_, allSelectors := selectors["*"]
41-
return &selectiveCore{selectors: selectors, core: core, allSelectors: allSelectors}
49+
return &selectiveCore{
50+
selectors: selectors,
51+
core: core,
52+
allSelectors: allSelectors,
53+
blockList: blockList,
54+
}
4255
}
4356

4457
// Enabled returns whether a given logging level is enabled when logging a
@@ -49,7 +62,7 @@ func (c *selectiveCore) Enabled(level zapcore.Level) bool {
4962

5063
// With adds structured context to the Core.
5164
func (c *selectiveCore) With(fields []zapcore.Field) zapcore.Core {
52-
return selectiveWrapper(c.core.With(fields), c.selectors)
65+
return selectiveWrapper(c.core.With(fields), c.selectors, c.blockList)
5366
}
5467

5568
// Check determines whether the supplied Entry should be logged (using the
@@ -61,6 +74,9 @@ func (c *selectiveCore) With(fields []zapcore.Field) zapcore.Core {
6174
func (c *selectiveCore) Check(ent zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {
6275
if c.Enabled(ent.Level) {
6376
if ent.Level == zapcore.DebugLevel {
77+
if _, blocked := c.blockList[ent.LoggerName]; blocked {
78+
return ce
79+
}
6480
if c.allSelectors {
6581
return ce.AddCore(ent, c)
6682
} else if _, enabled := c.selectors[ent.LoggerName]; enabled {

logp/selective_test.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,33 @@ func TestLoggerSelectors(t *testing.T) {
5454
logs = ObserverLogs().TakeAll()
5555
assert.Len(t, logs, 1)
5656
}
57+
58+
func TestLoggerBlockList(t *testing.T) {
59+
if err := DevelopmentSetup(WithBlockList("tooVerbose", " sensitiveInformation "), ToObserverOutput()); err != nil {
60+
t.Fatal(err)
61+
}
62+
63+
require.True(t, IsBlocked("tooVerbose"))
64+
require.True(t, IsBlocked("sensitiveInformation"))
65+
66+
doesNotLog := NewLogger("tooVerbose")
67+
doesNotLog2 := NewLogger("sensitiveInformation")
68+
willLog := NewLogger("notVerbose")
69+
70+
doesNotLog.Debug("is not logged")
71+
logs := ObserverLogs().TakeAll()
72+
assert.Len(t, logs, 0)
73+
74+
doesNotLog2.Debug("is not logged")
75+
logs = ObserverLogs().TakeAll()
76+
assert.Len(t, logs, 0)
77+
78+
// Selectors only apply to debug level logs.
79+
willLog.Debug("is logged")
80+
logs = ObserverLogs().TakeAll()
81+
assert.Len(t, logs, 1)
82+
83+
willLog.Info("is also logged")
84+
logs = ObserverLogs().TakeAll()
85+
assert.Len(t, logs, 1)
86+
}

0 commit comments

Comments
 (0)