Add ErrorHandler global to allow handling of write errors

This commit is contained in:
Olivier Poitrey 2018-11-20 10:54:42 -08:00
parent 848482bc3d
commit 8747b7b3a5
4 changed files with 32 additions and 1 deletions

View File

@ -479,6 +479,7 @@ Some settings can be changed and will by applied to all loggers:
// using the Dur method. // using the Dur method.
* `DurationFieldUnit`: Sets the unit of the fields added by `Dur` (default: `time.Millisecond`). * `DurationFieldUnit`: Sets the unit of the fields added by `Dur` (default: `time.Millisecond`).
* `DurationFieldInteger`: If set to true, `Dur` fields are formatted as integers instead of floats. * `DurationFieldInteger`: If set to true, `Dur` fields are formatted as integers instead of floats.
* `ErrorHandler`: Called whenever zerolog fails to write an event on its output. If not set, an error is printed on the stderr. This handler must be thread safe and non-blocking.
## Field Types ## Field Types

View File

@ -137,9 +137,13 @@ func (e *Event) msg(msg string) {
defer e.done(msg) defer e.done(msg)
} }
if err := e.write(); err != nil { if err := e.write(); err != nil {
if ErrorHandler != nil {
ErrorHandler(err)
} else {
fmt.Fprintf(os.Stderr, "zerolog: could not write event: %v\n", err) fmt.Fprintf(os.Stderr, "zerolog: could not write event: %v\n", err)
} }
} }
}
// Fields is a helper function to use a map to set fields using type assertion. // Fields is a helper function to use a map to set fields using type assertion.
func (e *Event) Fields(fields map[string]interface{}) *Event { func (e *Event) Fields(fields map[string]interface{}) *Event {

View File

@ -37,6 +37,11 @@ var (
// DurationFieldInteger renders Dur fields as integer instead of float if // DurationFieldInteger renders Dur fields as integer instead of float if
// set to true. // set to true.
DurationFieldInteger = false DurationFieldInteger = false
// ErrorHandler is called whenever zerolog fails to write an event on its
// output. If not set, an error is printed on the stderr. This handler must
// be thread safe and non-blocking.
ErrorHandler func(err error)
) )
var ( var (

View File

@ -640,3 +640,24 @@ func TestErrorMarshalFunc(t *testing.T) {
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want) t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
} }
} }
type errWriter struct {
error
}
func (w errWriter) Write(p []byte) (n int, err error) {
return 0, w.error
}
func TestErrorHandler(t *testing.T) {
var got error
want := errors.New("write error")
ErrorHandler = func(err error) {
got = err
}
log := New(errWriter{want})
log.Log().Msg("test")
if got != want {
t.Errorf("ErrorHandler err = %#v, want %#v", got, want)
}
}