Skip to content

Commit

Permalink
zaptest/observer: Support filtering by message or field (#386)
Browse files Browse the repository at this point in the history
* zaptest/observer: Support filtering by message or field

Add `Filter*` functions to filter a set of ObservedLogs and return
a new set of ObservedLogs. This allows chaining of multiple filters
such as `sink.FilterMessage(..).FilterField(..)` for easier use in
tests.

* Handle duplicate fields
  • Loading branch information
prashantv authored and akshayjshah committed Mar 25, 2017
1 parent 16dc29a commit 7cb1af2
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 0 deletions.
32 changes: 32 additions & 0 deletions zaptest/observer/observer.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,38 @@ func (o *ObservedLogs) AllUntimed() []LoggedEntry {
return ret
}

// FilterMessage filters entries to those that have the specified message.
func (o *ObservedLogs) FilterMessage(msg string) *ObservedLogs {
return o.filter(func(e LoggedEntry) bool {
return e.Message == msg
})
}

// FilterField filters entries to those that have the specified field.
func (o *ObservedLogs) FilterField(field zapcore.Field) *ObservedLogs {
return o.filter(func(e LoggedEntry) bool {
for _, ctxField := range e.Context {
if ctxField == field {
return true
}
}
return false
})
}

func (o *ObservedLogs) filter(match func(LoggedEntry) bool) *ObservedLogs {
o.mu.RLock()
defer o.mu.RUnlock()

var filtered []LoggedEntry
for _, entry := range o.logs {
if match(entry) {
filtered = append(filtered, entry)
}
}
return &ObservedLogs{logs: filtered}
}

func (o *ObservedLogs) add(log LoggedEntry) {
o.mu.Lock()
o.logs = append(o.logs, log)
Expand Down
63 changes: 63 additions & 0 deletions zaptest/observer/observer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,66 @@ func TestObserverWith(t *testing.T) {
},
}, logs.All(), "expected no field sharing between With siblings")
}

func TestFilters(t *testing.T) {
logs := []LoggedEntry{
{
Entry: zapcore.Entry{Level: zap.InfoLevel, Message: "log a"},
Context: []zapcore.Field{zap.String("fStr", "1"), zap.Int("a", 1)},
},
{
Entry: zapcore.Entry{Level: zap.InfoLevel, Message: "log a"},
Context: []zapcore.Field{zap.String("fStr", "2"), zap.Int("b", 2)},
},
{
Entry: zapcore.Entry{Level: zap.InfoLevel, Message: "log b"},
Context: []zapcore.Field{zap.Int("a", 1), zap.Int("b", 2)},
},
{
Entry: zapcore.Entry{Level: zap.InfoLevel, Message: "log c"},
Context: []zapcore.Field{zap.Int("a", 1), zap.Namespace("ns"), zap.Int("a", 2)},
},
}

logger, sink := New(zap.InfoLevel)
for _, log := range logs {
logger.Write(log.Entry, log.Context)
}

tests := []struct {
msg string
filtered *ObservedLogs
want []LoggedEntry
}{
{
msg: "filter by message",
filtered: sink.FilterMessage("log a"),
want: logs[0:2],
},
{
msg: "filter by field",
filtered: sink.FilterField(zap.String("fStr", "1")),
want: logs[0:1],
},
{
msg: "filter by message and field",
filtered: sink.FilterMessage("log a").FilterField(zap.Int("b", 2)),
want: logs[1:2],
},
{
msg: "filter by field with duplicate fields",
filtered: sink.FilterField(zap.Int("a", 2)),
want: logs[3:4],
},
{
msg: "filter doesn't match any messages",
filtered: sink.FilterMessage("no match"),
want: []LoggedEntry{},
},
}

for _, tt := range tests {
got := tt.filtered.AllUntimed()
assert.Equal(t, tt.want, got, tt.msg)
}
}

0 comments on commit 7cb1af2

Please sign in to comment.