-
Notifications
You must be signed in to change notification settings - Fork 45
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Provide a way to filter out log messages easily (#64)
Co-authored-by: Jim Kalafut <jkalafut@hashicorp.com> Co-authored-by: Dan Slimmon <dslimmon@hashicorp.com> Co-authored-by: Clint <catsby@users.noreply.github.com>
- Loading branch information
1 parent
24cddb1
commit ec1a562
Showing
4 changed files
with
139 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
package hclog | ||
|
||
import ( | ||
"regexp" | ||
"strings" | ||
) | ||
|
||
// ExcludeByMessage provides a simple way to build a list of log messages that | ||
// can be queried and matched. This is meant to be used with the Exclude | ||
// option on Options to suppress log messages. This does not hold any mutexs | ||
// within itself, so normal usage would be to Add entries at setup and none after | ||
// Exclude is going to be called. Exclude is called with a mutex held within | ||
// the Logger, so that doesn't need to use a mutex. Example usage: | ||
// | ||
// f := new(ExcludeByMessage) | ||
// f.Add("Noisy log message text") | ||
// appLogger.Exclude = f.Exclude | ||
type ExcludeByMessage struct { | ||
messages map[string]struct{} | ||
} | ||
|
||
// Add a message to be filtered. Do not call this after Exclude is to be called | ||
// due to concurrency issues. | ||
func (f *ExcludeByMessage) Add(msg string) { | ||
if f.messages == nil { | ||
f.messages = make(map[string]struct{}) | ||
} | ||
|
||
f.messages[msg] = struct{}{} | ||
} | ||
|
||
// Return true if the given message should be included | ||
func (f *ExcludeByMessage) Exclude(level Level, msg string, args ...interface{}) bool { | ||
_, ok := f.messages[msg] | ||
return ok | ||
} | ||
|
||
// ExcludeByPrefix is a simple type to match a message string that has a common prefix. | ||
type ExcludeByPrefix string | ||
|
||
// Matches an message that starts with the prefix. | ||
func (p ExcludeByPrefix) Exclude(level Level, msg string, args ...interface{}) bool { | ||
return strings.HasPrefix(msg, string(p)) | ||
} | ||
|
||
// ExcludeByRegexp takes a regexp and uses it to match a log message string. If it matches | ||
// the log entry is excluded. | ||
type ExcludeByRegexp struct { | ||
Regexp *regexp.Regexp | ||
} | ||
|
||
// Exclude the log message if the message string matches the regexp | ||
func (e ExcludeByRegexp) Exclude(level Level, msg string, args ...interface{}) bool { | ||
return e.Regexp.MatchString(msg) | ||
} | ||
|
||
// ExcludeFuncs is a slice of functions that will called to see if a log entry | ||
// should be filtered or not. It stops calling functions once at least one returns | ||
// true. | ||
type ExcludeFuncs []func(level Level, msg string, args ...interface{}) bool | ||
|
||
// Calls each function until one of them returns true | ||
func (ff ExcludeFuncs) Exclude(level Level, msg string, args ...interface{}) bool { | ||
for _, f := range ff { | ||
if f(level, msg, args...) { | ||
return true | ||
} | ||
} | ||
|
||
return false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package hclog | ||
|
||
import ( | ||
"regexp" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestExclude(t *testing.T) { | ||
t.Run("excludes by message", func(t *testing.T) { | ||
var em ExcludeByMessage | ||
em.Add("foo") | ||
em.Add("bar") | ||
|
||
assert.True(t, em.Exclude(Info, "foo")) | ||
assert.True(t, em.Exclude(Info, "bar")) | ||
assert.False(t, em.Exclude(Info, "qux")) | ||
assert.False(t, em.Exclude(Info, "foo qux")) | ||
assert.False(t, em.Exclude(Info, "qux bar")) | ||
}) | ||
|
||
t.Run("excludes by prefix", func(t *testing.T) { | ||
ebp := ExcludeByPrefix("foo: ") | ||
|
||
assert.True(t, ebp.Exclude(Info, "foo: rocks")) | ||
assert.False(t, ebp.Exclude(Info, "foo")) | ||
assert.False(t, ebp.Exclude(Info, "qux foo: bar")) | ||
}) | ||
|
||
t.Run("exclude by regexp", func(t *testing.T) { | ||
ebr := &ExcludeByRegexp{ | ||
Regexp: regexp.MustCompile("(foo|bar)"), | ||
} | ||
|
||
assert.True(t, ebr.Exclude(Info, "foo")) | ||
assert.True(t, ebr.Exclude(Info, "bar")) | ||
assert.True(t, ebr.Exclude(Info, "foo qux")) | ||
assert.True(t, ebr.Exclude(Info, "qux bar")) | ||
assert.False(t, ebr.Exclude(Info, "qux")) | ||
}) | ||
|
||
t.Run("excludes many funcs", func(t *testing.T) { | ||
ef := ExcludeFuncs{ | ||
ExcludeByPrefix("foo: ").Exclude, | ||
ExcludeByPrefix("bar: ").Exclude, | ||
} | ||
|
||
assert.True(t, ef.Exclude(Info, "foo: rocks")) | ||
assert.True(t, ef.Exclude(Info, "bar: rocks")) | ||
assert.False(t, ef.Exclude(Info, "foo")) | ||
assert.False(t, ef.Exclude(Info, "qux foo: bar")) | ||
|
||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters