Skip to content

Commit

Permalink
Implement BlockSelectors for level debug
Browse files Browse the repository at this point in the history
This commit implements a block list of selectors for debug logging on
`logp`.
  • Loading branch information
belimawr committed Jun 8, 2023
1 parent 0c0f99a commit 854c7b4
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 20 deletions.
7 changes: 4 additions & 3 deletions logp/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ import (
// Config contains the configuration options for the logger. To create a Config
// from a common.Config use logp/config.Build.
type Config struct {
Beat string `config:",ignore"` // Name of the Beat (for default file name).
Level Level `config:"level"` // Logging level (error, warning, info, debug).
Selectors []string `config:"selectors"` // Selectors for debug level logging.
Beat string `config:",ignore"` // Name of the Beat (for default file name).
Level Level `config:"level"` // Logging level (error, warning, info, debug).
Selectors []string `config:"selectors"` // Selectors for debug level logging.
BlockSelectors []string `config:"block_selectors"` // Block list of selectors for debug logging.

toObserver bool
toIODiscard bool
Expand Down
35 changes: 21 additions & 14 deletions logp/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,13 @@ func init() {
}

type coreLogger struct {
selectors map[string]struct{} // Set of enabled debug selectors.
rootLogger *zap.Logger // Root logger without any options configured.
globalLogger *zap.Logger // Logger used by legacy global functions (e.g. logp.Info).
logger *Logger // Logger that is the basis for all logp.Loggers.
level zap.AtomicLevel // The minimum level being printed
observedLogs *observer.ObservedLogs // Contains events generated while in observation mode (a testing mode).
selectors map[string]struct{} // Set of enabled debug selectors.
blockSelectors map[string]struct{} // Set of blocked debug selectors.
rootLogger *zap.Logger // Root logger without any options configured.
globalLogger *zap.Logger // Logger used by legacy global functions (e.g. logp.Info).
logger *Logger // Logger that is the basis for all logp.Loggers.
level zap.AtomicLevel // The minimum level being printed
observedLogs *observer.ObservedLogs // Contains events generated while in observation mode (a testing mode).
}

// Configure configures the logp package.
Expand Down Expand Up @@ -97,7 +98,12 @@ func ConfigureWithOutputs(cfg Config, outputs ...zapcore.Core) error {

// Enabled selectors when debug is enabled.
selectors := make(map[string]struct{}, len(cfg.Selectors))
if cfg.Level.Enabled(DebugLevel) && len(cfg.Selectors) > 0 {
blockSelectors := make(map[string]struct{}, len(cfg.BlockSelectors))
if cfg.Level.Enabled(DebugLevel) && (len(cfg.Selectors) > 0 || len(cfg.BlockSelectors) > 0) {
for _, sel := range cfg.BlockSelectors {
blockSelectors[strings.TrimSpace(sel)] = struct{}{}
}

for _, sel := range cfg.Selectors {
selectors[strings.TrimSpace(sel)] = struct{}{}
}
Expand All @@ -115,18 +121,19 @@ func ConfigureWithOutputs(cfg Config, outputs ...zapcore.Core) error {
golog.SetOutput(_defaultGoLog)
}

sink = selectiveWrapper(sink, selectors)
sink = selectiveWrapper(sink, selectors, blockSelectors)
}

sink = newMultiCore(append(outputs, sink)...)
root := zap.New(sink, makeOptions(cfg)...)
storeLogger(&coreLogger{
selectors: selectors,
rootLogger: root,
globalLogger: root.WithOptions(zap.AddCallerSkip(1)),
logger: newLogger(root, ""),
level: level,
observedLogs: observedLogs,
selectors: selectors,
blockSelectors: blockSelectors,
rootLogger: root,
globalLogger: root.WithOptions(zap.AddCallerSkip(1)),
logger: newLogger(root, ""),
level: level,
observedLogs: observedLogs,
})
return nil
}
Expand Down
8 changes: 8 additions & 0 deletions logp/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ func WithSelectors(selectors ...string) Option {
}
}

// WithBlockList specifies what debug selectors are disabled. If no selectors
// are specified, then nothing is blocked
func WithBlockList(blockList ...string) Option {
return func(cfg *Config) {
cfg.BlockList = append(cfg.BlockList, blockList...)
}
}

// ToObserverOutput specifies that the output should be collected in memory so
// that they can be read by an observer by calling ObserverLogs().
func ToObserverOutput() Option {
Expand Down
22 changes: 19 additions & 3 deletions logp/selective.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
type selectiveCore struct {
allSelectors bool
selectors map[string]struct{}
blockList map[string]struct{}
core zapcore.Core
}

Expand All @@ -33,12 +34,24 @@ func HasSelector(selector string) bool {
return found
}

func selectiveWrapper(core zapcore.Core, selectors map[string]struct{}) zapcore.Core {
// IsBlocked returns true if the given selector was explicitly set.
func IsBlocked(selector string) bool {
l := loadLogger()
_, found := l.blockSelectors[selector]
return found
}

func selectiveWrapper(core zapcore.Core, selectors, blockList map[string]struct{}) zapcore.Core {
if len(selectors) == 0 {
return core
}
_, allSelectors := selectors["*"]
return &selectiveCore{selectors: selectors, core: core, allSelectors: allSelectors}
return &selectiveCore{
selectors: selectors,
core: core,
allSelectors: allSelectors,
blockList: blockList,
}
}

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

// With adds structured context to the Core.
func (c *selectiveCore) With(fields []zapcore.Field) zapcore.Core {
return selectiveWrapper(c.core.With(fields), c.selectors)
return selectiveWrapper(c.core.With(fields), c.selectors, c.blockList)
}

// Check determines whether the supplied Entry should be logged (using the
Expand All @@ -61,6 +74,9 @@ func (c *selectiveCore) With(fields []zapcore.Field) zapcore.Core {
func (c *selectiveCore) Check(ent zapcore.Entry, ce *zapcore.CheckedEntry) *zapcore.CheckedEntry {
if c.Enabled(ent.Level) {
if ent.Level == zapcore.DebugLevel {
if _, blocked := c.blockList[ent.LoggerName]; blocked {
return ce
}
if c.allSelectors {
return ce.AddCore(ent, c)
} else if _, enabled := c.selectors[ent.LoggerName]; enabled {
Expand Down
30 changes: 30 additions & 0 deletions logp/selective_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,33 @@ func TestLoggerSelectors(t *testing.T) {
logs = ObserverLogs().TakeAll()
assert.Len(t, logs, 1)
}

func TestLoggerBlockList(t *testing.T) {
if err := DevelopmentSetup(WithBlockList("tooVerbose", " sensitiveInformation "), ToObserverOutput()); err != nil {
t.Fatal(err)
}

require.True(t, IsBlocked("tooVerbose"))
require.True(t, IsBlocked("sensitiveInformation"))

doesNotLog := NewLogger("tooVerbose")
doesNotLog2 := NewLogger("sensitiveInformation")
willLog := NewLogger("notVerbose")

doesNotLog.Debug("is not logged")
logs := ObserverLogs().TakeAll()
assert.Len(t, logs, 0)

doesNotLog2.Debug("is not logged")
logs = ObserverLogs().TakeAll()
assert.Len(t, logs, 0)

// Selectors only apply to debug level logs.
willLog.Debug("is logged")
logs = ObserverLogs().TakeAll()
assert.Len(t, logs, 1)

willLog.Info("is also logged")
logs = ObserverLogs().TakeAll()
assert.Len(t, logs, 1)
}

0 comments on commit 854c7b4

Please sign in to comment.