Skip to content

Commit

Permalink
Add support for pkg/errors
Browse files Browse the repository at this point in the history
Users who take the time (and performance hit) of using Dave Cheney's errors
package should get rich, annotated errors and stacktraces in their logs.
However, that package is only one of a number of similar packages hasn't yet
committed to a stable API, so we don't want to take a direct dependency on it.

To support these sorts of packages, serialize errors that implement
`fmt.Formatter` differently from those that don't.
  • Loading branch information
Akshay Shah committed Feb 19, 2017
1 parent aa2e5d0 commit e8f7ba6
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 1 deletion.
9 changes: 8 additions & 1 deletion zapcore/field.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,14 @@ func (f Field) AddTo(enc ObjectEncoder) {
case StringerType:
enc.AddString(f.Key, f.Interface.(fmt.Stringer).String())
case ErrorType:
enc.AddString(f.Key, f.Interface.(error).Error())
val := f.Interface.(error)
if fancy, ok := val.(fmt.Formatter); ok {
// This is a rich error type, like those produced by
// github.com/pkg/errors.
enc.AddString(f.Key, fmt.Sprintf("%+v", fancy))
} else {
enc.AddString(f.Key, val.Error())
}
case SkipType:
break
default:
Expand Down
17 changes: 17 additions & 0 deletions zapcore/field_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"testing"
"time"

richErrors "github.com/pkg/errors"
"github.com/stretchr/testify/assert"

. "go.uber.org/zap/zapcore"
Expand Down Expand Up @@ -127,3 +128,19 @@ func TestFields(t *testing.T) {
assert.Equal(t, tt.want, enc.Fields["k"], "Unexpected output from field %+v.", f)
}
}

func TestRichErrorSupport(t *testing.T) {
f := Field{
Type: ErrorType,
Interface: richErrors.WithMessage(richErrors.New("egad"), "failed"),
Key: "k",
}
enc := NewMapObjectEncoder()
f.AddTo(enc)
serialized := enc.Fields["k"]
// Don't assert the exact format used by a third-party package, but ensure
// that some critical elements are present.
assert.Regexp(t, `egad`, serialized, "Expected original error message to be present.")
assert.Regexp(t, `failed`, serialized, "Expected error annotation to be present.")
assert.Regexp(t, `TestRichErrorSupport`, serialized, "Expected calling function to be present in stacktrace.")
}

0 comments on commit e8f7ba6

Please sign in to comment.