Add the ability to discard an event from a hook
The Discard method has been added to the Event type so it can be called from a hook to prevent the event from behing printed. This new method works outside of the context of a hook too. Fixes #90
This commit is contained in:
parent
bae001d86b
commit
71e1f5e052
10
event.go
10
event.go
|
@ -60,11 +60,13 @@ func (e *Event) write() (err error) {
|
||||||
if e == nil {
|
if e == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
if e.level != Disabled {
|
||||||
e.buf = enc.AppendEndMarker(e.buf)
|
e.buf = enc.AppendEndMarker(e.buf)
|
||||||
e.buf = enc.AppendLineBreak(e.buf)
|
e.buf = enc.AppendLineBreak(e.buf)
|
||||||
if e.w != nil {
|
if e.w != nil {
|
||||||
_, err = e.w.WriteLevel(e.level, e.buf)
|
_, err = e.w.WriteLevel(e.level, e.buf)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
eventPool.Put(e)
|
eventPool.Put(e)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -72,7 +74,13 @@ func (e *Event) write() (err error) {
|
||||||
// Enabled return false if the *Event is going to be filtered out by
|
// Enabled return false if the *Event is going to be filtered out by
|
||||||
// log level or sampling.
|
// log level or sampling.
|
||||||
func (e *Event) Enabled() bool {
|
func (e *Event) Enabled() bool {
|
||||||
return e != nil
|
return e != nil && e.level != Disabled
|
||||||
|
}
|
||||||
|
|
||||||
|
// Discard disables the event so Msg(f) won't print it.
|
||||||
|
func (e *Event) Discard() *Event {
|
||||||
|
e.level = Disabled
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Msg sends the *Event with msg added as the message field if not empty.
|
// Msg sends the *Event with msg added as the message field if not empty.
|
||||||
|
|
9
hook.go
9
hook.go
|
@ -6,6 +6,15 @@ type Hook interface {
|
||||||
Run(e *Event, level Level, message string)
|
Run(e *Event, level Level, message string)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HookFunc is an adaptor to allow the use of an ordinary function
|
||||||
|
// as a Hook.
|
||||||
|
type HookFunc func(e *Event, level Level, message string)
|
||||||
|
|
||||||
|
// Run implements the Hook interface.
|
||||||
|
func (h HookFunc) Run(e *Event, level Level, message string) {
|
||||||
|
h(e, level, message)
|
||||||
|
}
|
||||||
|
|
||||||
// LevelHook applies a different hook for each level.
|
// LevelHook applies a different hook for each level.
|
||||||
type LevelHook struct {
|
type LevelHook struct {
|
||||||
NoLevelHook, DebugHook, InfoHook, WarnHook, ErrorHook, FatalHook, PanicHook Hook
|
NoLevelHook, DebugHook, InfoHook, WarnHook, ErrorHook, FatalHook, PanicHook Hook
|
||||||
|
|
237
hook_test.go
237
hook_test.go
|
@ -6,205 +6,136 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
type LevelNameHook struct{}
|
var (
|
||||||
|
levelNameHook = HookFunc(func(e *Event, level Level, msg string) {
|
||||||
func (h LevelNameHook) Run(e *Event, level Level, msg string) {
|
|
||||||
levelName := level.String()
|
levelName := level.String()
|
||||||
if level == NoLevel {
|
if level == NoLevel {
|
||||||
levelName = "nolevel"
|
levelName = "nolevel"
|
||||||
}
|
}
|
||||||
e.Str("level_name", levelName)
|
e.Str("level_name", levelName)
|
||||||
}
|
})
|
||||||
|
simpleHook = HookFunc(func(e *Event, level Level, msg string) {
|
||||||
type SimpleHook struct{}
|
|
||||||
|
|
||||||
func (h SimpleHook) Run(e *Event, level Level, msg string) {
|
|
||||||
e.Bool("has_level", level != NoLevel)
|
e.Bool("has_level", level != NoLevel)
|
||||||
e.Str("test", "logged")
|
e.Str("test", "logged")
|
||||||
}
|
})
|
||||||
|
copyHook = HookFunc(func(e *Event, level Level, msg string) {
|
||||||
type CopyHook struct{}
|
|
||||||
|
|
||||||
func (h CopyHook) Run(e *Event, level Level, msg string) {
|
|
||||||
hasLevel := level != NoLevel
|
hasLevel := level != NoLevel
|
||||||
e.Bool("copy_has_level", hasLevel)
|
e.Bool("copy_has_level", hasLevel)
|
||||||
if hasLevel {
|
if hasLevel {
|
||||||
e.Str("copy_level", level.String())
|
e.Str("copy_level", level.String())
|
||||||
}
|
}
|
||||||
e.Str("copy_msg", msg)
|
e.Str("copy_msg", msg)
|
||||||
}
|
})
|
||||||
|
nopHook = HookFunc(func(e *Event, level Level, message string) {
|
||||||
type NopHook struct{}
|
})
|
||||||
|
discardHook = HookFunc(func(e *Event, level Level, message string) {
|
||||||
func (h NopHook) Run(e *Event, level Level, msg string) {
|
e.Discard()
|
||||||
}
|
})
|
||||||
|
|
||||||
var (
|
|
||||||
levelNameHook LevelNameHook
|
|
||||||
simpleHook SimpleHook
|
|
||||||
copyHook CopyHook
|
|
||||||
nopHook NopHook
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHook(t *testing.T) {
|
func TestHook(t *testing.T) {
|
||||||
t.Run("Message", func(t *testing.T) {
|
tests := []struct {
|
||||||
out := &bytes.Buffer{}
|
name string
|
||||||
log := New(out).Hook(levelNameHook)
|
want string
|
||||||
|
test func(log Logger)
|
||||||
|
}{
|
||||||
|
{"Message", `{"level_name":"nolevel","message":"test message"}` + "\n", func(log Logger) {
|
||||||
|
log = log.Hook(levelNameHook)
|
||||||
log.Log().Msg("test message")
|
log.Log().Msg("test message")
|
||||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level_name":"nolevel","message":"test message"}`+"\n"; got != want {
|
}},
|
||||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
{"NoLevel", `{"level_name":"nolevel"}` + "\n", func(log Logger) {
|
||||||
}
|
log = log.Hook(levelNameHook)
|
||||||
})
|
|
||||||
t.Run("NoLevel", func(t *testing.T) {
|
|
||||||
out := &bytes.Buffer{}
|
|
||||||
log := New(out).Hook(levelNameHook)
|
|
||||||
log.Log().Msg("")
|
log.Log().Msg("")
|
||||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level_name":"nolevel"}`+"\n"; got != want {
|
}},
|
||||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
{"Print", `{"level":"debug","level_name":"debug"}` + "\n", func(log Logger) {
|
||||||
}
|
log = log.Hook(levelNameHook)
|
||||||
})
|
|
||||||
t.Run("Print", func(t *testing.T) {
|
|
||||||
out := &bytes.Buffer{}
|
|
||||||
log := New(out).Hook(levelNameHook)
|
|
||||||
log.Print("")
|
log.Print("")
|
||||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"debug","level_name":"debug"}`+"\n"; got != want {
|
}},
|
||||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
{"Error", `{"level":"error","level_name":"error"}` + "\n", func(log Logger) {
|
||||||
}
|
log = log.Hook(levelNameHook)
|
||||||
})
|
|
||||||
t.Run("Error", func(t *testing.T) {
|
|
||||||
out := &bytes.Buffer{}
|
|
||||||
log := New(out).Hook(levelNameHook)
|
|
||||||
log.Error().Msg("")
|
log.Error().Msg("")
|
||||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"error","level_name":"error"}`+"\n"; got != want {
|
}},
|
||||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
{"Copy/1", `{"copy_has_level":false,"copy_msg":""}` + "\n", func(log Logger) {
|
||||||
}
|
log = log.Hook(copyHook)
|
||||||
})
|
|
||||||
t.Run("Copy/1", func(t *testing.T) {
|
|
||||||
out := &bytes.Buffer{}
|
|
||||||
log := New(out).Hook(copyHook)
|
|
||||||
log.Log().Msg("")
|
log.Log().Msg("")
|
||||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"copy_has_level":false,"copy_msg":""}`+"\n"; got != want {
|
}},
|
||||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
{"Copy/2", `{"level":"info","copy_has_level":true,"copy_level":"info","copy_msg":"a message","message":"a message"}` + "\n", func(log Logger) {
|
||||||
}
|
log = log.Hook(copyHook)
|
||||||
})
|
|
||||||
t.Run("Copy/2", func(t *testing.T) {
|
|
||||||
out := &bytes.Buffer{}
|
|
||||||
log := New(out).Hook(copyHook)
|
|
||||||
log.Info().Msg("a message")
|
log.Info().Msg("a message")
|
||||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"info","copy_has_level":true,"copy_level":"info","copy_msg":"a message","message":"a message"}`+"\n"; got != want {
|
}},
|
||||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
{"Multi", `{"level":"error","level_name":"error","has_level":true,"test":"logged"}` + "\n", func(log Logger) {
|
||||||
}
|
log = log.Hook(levelNameHook).Hook(simpleHook)
|
||||||
})
|
|
||||||
t.Run("Multi", func(t *testing.T) {
|
|
||||||
out := &bytes.Buffer{}
|
|
||||||
log := New(out).Hook(levelNameHook).Hook(simpleHook)
|
|
||||||
log.Error().Msg("")
|
log.Error().Msg("")
|
||||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"error","level_name":"error","has_level":true,"test":"logged"}`+"\n"; got != want {
|
}},
|
||||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
{"Multi/Message", `{"level":"error","level_name":"error","has_level":true,"test":"logged","message":"a message"}` + "\n", func(log Logger) {
|
||||||
}
|
log = log.Hook(levelNameHook).Hook(simpleHook)
|
||||||
})
|
|
||||||
t.Run("Multi/Message", func(t *testing.T) {
|
|
||||||
out := &bytes.Buffer{}
|
|
||||||
log := New(out).Hook(levelNameHook).Hook(simpleHook)
|
|
||||||
log.Error().Msg("a message")
|
log.Error().Msg("a message")
|
||||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"error","level_name":"error","has_level":true,"test":"logged","message":"a message"}`+"\n"; got != want {
|
}},
|
||||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
{"Output/single/pre", `{"level":"error","level_name":"error"}` + "\n", func(log Logger) {
|
||||||
}
|
|
||||||
})
|
|
||||||
t.Run("Output/single/pre", func(t *testing.T) {
|
|
||||||
ignored := &bytes.Buffer{}
|
ignored := &bytes.Buffer{}
|
||||||
out := &bytes.Buffer{}
|
log = New(ignored).Hook(levelNameHook).Output(log.w)
|
||||||
log := New(ignored).Hook(levelNameHook).Output(out)
|
|
||||||
log.Error().Msg("")
|
log.Error().Msg("")
|
||||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"error","level_name":"error"}`+"\n"; got != want {
|
}},
|
||||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
{"Output/single/post", `{"level":"error","level_name":"error"}` + "\n", func(log Logger) {
|
||||||
}
|
|
||||||
})
|
|
||||||
t.Run("Output/single/post", func(t *testing.T) {
|
|
||||||
ignored := &bytes.Buffer{}
|
ignored := &bytes.Buffer{}
|
||||||
out := &bytes.Buffer{}
|
log = New(ignored).Output(log.w).Hook(levelNameHook)
|
||||||
log := New(ignored).Output(out).Hook(levelNameHook)
|
|
||||||
log.Error().Msg("")
|
log.Error().Msg("")
|
||||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"error","level_name":"error"}`+"\n"; got != want {
|
}},
|
||||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
{"Output/multi/pre", `{"level":"error","level_name":"error","has_level":true,"test":"logged"}` + "\n", func(log Logger) {
|
||||||
}
|
|
||||||
})
|
|
||||||
t.Run("Output/multi/pre", func(t *testing.T) {
|
|
||||||
ignored := &bytes.Buffer{}
|
ignored := &bytes.Buffer{}
|
||||||
out := &bytes.Buffer{}
|
log = New(ignored).Hook(levelNameHook).Hook(simpleHook).Output(log.w)
|
||||||
log := New(ignored).Hook(levelNameHook).Hook(simpleHook).Output(out)
|
|
||||||
log.Error().Msg("")
|
log.Error().Msg("")
|
||||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"error","level_name":"error","has_level":true,"test":"logged"}`+"\n"; got != want {
|
}},
|
||||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
{"Output/multi/post", `{"level":"error","level_name":"error","has_level":true,"test":"logged"}` + "\n", func(log Logger) {
|
||||||
}
|
|
||||||
})
|
|
||||||
t.Run("Output/multi/post", func(t *testing.T) {
|
|
||||||
ignored := &bytes.Buffer{}
|
ignored := &bytes.Buffer{}
|
||||||
out := &bytes.Buffer{}
|
log = New(ignored).Output(log.w).Hook(levelNameHook).Hook(simpleHook)
|
||||||
log := New(ignored).Output(out).Hook(levelNameHook).Hook(simpleHook)
|
|
||||||
log.Error().Msg("")
|
log.Error().Msg("")
|
||||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"error","level_name":"error","has_level":true,"test":"logged"}`+"\n"; got != want {
|
}},
|
||||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
{"Output/mixed", `{"level":"error","level_name":"error","has_level":true,"test":"logged"}` + "\n", func(log Logger) {
|
||||||
}
|
|
||||||
})
|
|
||||||
t.Run("Output/mixed", func(t *testing.T) {
|
|
||||||
ignored := &bytes.Buffer{}
|
ignored := &bytes.Buffer{}
|
||||||
out := &bytes.Buffer{}
|
log = New(ignored).Hook(levelNameHook).Output(log.w).Hook(simpleHook)
|
||||||
log := New(ignored).Hook(levelNameHook).Output(out).Hook(simpleHook)
|
|
||||||
log.Error().Msg("")
|
log.Error().Msg("")
|
||||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"error","level_name":"error","has_level":true,"test":"logged"}`+"\n"; got != want {
|
}},
|
||||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
{"With/single/pre", `{"level":"error","with":"pre","level_name":"error"}` + "\n", func(log Logger) {
|
||||||
}
|
log = log.Hook(levelNameHook).With().Str("with", "pre").Logger()
|
||||||
})
|
|
||||||
t.Run("With/single/pre", func(t *testing.T) {
|
|
||||||
out := &bytes.Buffer{}
|
|
||||||
log := New(out).Hook(levelNameHook).With().Str("with", "pre").Logger()
|
|
||||||
log.Error().Msg("")
|
log.Error().Msg("")
|
||||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"error","with":"pre","level_name":"error"}`+"\n"; got != want {
|
}},
|
||||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
{"With/single/post", `{"level":"error","with":"post","level_name":"error"}` + "\n", func(log Logger) {
|
||||||
}
|
log = log.With().Str("with", "post").Logger().Hook(levelNameHook)
|
||||||
})
|
|
||||||
t.Run("With/single/post", func(t *testing.T) {
|
|
||||||
out := &bytes.Buffer{}
|
|
||||||
log := New(out).With().Str("with", "post").Logger().Hook(levelNameHook)
|
|
||||||
log.Error().Msg("")
|
log.Error().Msg("")
|
||||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"error","with":"post","level_name":"error"}`+"\n"; got != want {
|
}},
|
||||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
{"With/multi/pre", `{"level":"error","with":"pre","level_name":"error","has_level":true,"test":"logged"}` + "\n", func(log Logger) {
|
||||||
}
|
log = log.Hook(levelNameHook).Hook(simpleHook).With().Str("with", "pre").Logger()
|
||||||
})
|
|
||||||
t.Run("With/multi/pre", func(t *testing.T) {
|
|
||||||
out := &bytes.Buffer{}
|
|
||||||
log := New(out).Hook(levelNameHook).Hook(simpleHook).With().Str("with", "pre").Logger()
|
|
||||||
log.Error().Msg("")
|
log.Error().Msg("")
|
||||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"error","with":"pre","level_name":"error","has_level":true,"test":"logged"}`+"\n"; got != want {
|
}},
|
||||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
{"With/multi/post", `{"level":"error","with":"post","level_name":"error","has_level":true,"test":"logged"}` + "\n", func(log Logger) {
|
||||||
}
|
log = log.With().Str("with", "post").Logger().Hook(levelNameHook).Hook(simpleHook)
|
||||||
})
|
|
||||||
t.Run("With/multi/post", func(t *testing.T) {
|
|
||||||
out := &bytes.Buffer{}
|
|
||||||
log := New(out).With().Str("with", "post").Logger().Hook(levelNameHook).Hook(simpleHook)
|
|
||||||
log.Error().Msg("")
|
log.Error().Msg("")
|
||||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"error","with":"post","level_name":"error","has_level":true,"test":"logged"}`+"\n"; got != want {
|
}},
|
||||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
{"With/mixed", `{"level":"error","with":"mixed","level_name":"error","has_level":true,"test":"logged"}` + "\n", func(log Logger) {
|
||||||
}
|
log = log.Hook(levelNameHook).With().Str("with", "mixed").Logger().Hook(simpleHook)
|
||||||
})
|
|
||||||
t.Run("With/mixed", func(t *testing.T) {
|
|
||||||
out := &bytes.Buffer{}
|
|
||||||
log := New(out).Hook(levelNameHook).With().Str("with", "mixed").Logger().Hook(simpleHook)
|
|
||||||
log.Error().Msg("")
|
log.Error().Msg("")
|
||||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"error","with":"mixed","level_name":"error","has_level":true,"test":"logged"}`+"\n"; got != want {
|
}},
|
||||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
{"Discard", "", func(log Logger) {
|
||||||
|
log = log.Hook(discardHook)
|
||||||
|
log.Log().Msg("test message")
|
||||||
|
}},
|
||||||
|
{"None", `{"level":"error"}` + "\n", func(log Logger) {
|
||||||
|
log.Error().Msg("")
|
||||||
|
}},
|
||||||
}
|
}
|
||||||
})
|
for _, tt := range tests {
|
||||||
t.Run("None", func(t *testing.T) {
|
tt := tt
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
out := &bytes.Buffer{}
|
out := &bytes.Buffer{}
|
||||||
log := New(out)
|
log := New(out)
|
||||||
log.Error().Msg("")
|
tt.test(log)
|
||||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"level":"error"}`+"\n"; got != want {
|
if got, want := decodeIfBinaryToString(out.Bytes()), tt.want; got != want {
|
||||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkHooks(b *testing.B) {
|
func BenchmarkHooks(b *testing.B) {
|
||||||
logger := New(ioutil.Discard)
|
logger := New(ioutil.Discard)
|
||||||
|
|
Loading…
Reference in New Issue