diff --git a/pkgerrors/stacktrace.go b/pkgerrors/stacktrace.go index 01420e64..2f62ffdd 100644 --- a/pkgerrors/stacktrace.go +++ b/pkgerrors/stacktrace.go @@ -42,15 +42,32 @@ func frameField(f errors.Frame, s *state, c rune) string { // MarshalStack implements pkg/errors stack trace marshaling. // -// zerolog.ErrorStackMarshaler = MarshalStack +// zerolog.ErrorStackMarshaler = MarshalStack func MarshalStack(err error) interface{} { type stackTracer interface { StackTrace() errors.StackTrace } - sterr, ok := err.(stackTracer) - if !ok { + var sterr stackTracer + var ok bool + for err != nil { + sterr, ok = err.(stackTracer) + if ok { + break + } + + u, ok := err.(interface { + Unwrap() error + }) + if !ok { + return nil + } + + err = u.Unwrap() + } + if sterr == nil { return nil } + st := sterr.StackTrace() s := &state{} out := make([]map[string]string, 0, len(st)) diff --git a/pkgerrors/stacktrace_test.go b/pkgerrors/stacktrace_test.go index 4f9838c4..5a138323 100644 --- a/pkgerrors/stacktrace_test.go +++ b/pkgerrors/stacktrace_test.go @@ -4,6 +4,7 @@ package pkgerrors import ( "bytes" + "fmt" "regexp" "testing" @@ -17,11 +18,11 @@ func TestLogStack(t *testing.T) { out := &bytes.Buffer{} log := zerolog.New(out) - err := errors.Wrap(errors.New("error message"), "from error") + err := fmt.Errorf("from error: %w", errors.New("error message")) log.Log().Stack().Err(err).Msg("") got := out.String() - want := `\{"stack":\[\{"func":"TestLogStack","line":"20","source":"stacktrace_test.go"\},.*\],"error":"from error: error message"\}\n` + want := `\{"stack":\[\{"func":"TestLogStack","line":"21","source":"stacktrace_test.go"\},.*\],"error":"from error: error message"\}\n` if ok, _ := regexp.MatchString(want, got); !ok { t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want) } @@ -33,11 +34,11 @@ func TestLogStackFromContext(t *testing.T) { out := &bytes.Buffer{} log := zerolog.New(out).With().Stack().Logger() // calling Stack() on log context instead of event - err := errors.Wrap(errors.New("error message"), "from error") + err := fmt.Errorf("from error: %w", errors.New("error message")) log.Log().Err(err).Msg("") // not explicitly calling Stack() got := out.String() - want := `\{"stack":\[\{"func":"TestLogStackFromContext","line":"36","source":"stacktrace_test.go"\},.*\],"error":"from error: error message"\}\n` + want := `\{"stack":\[\{"func":"TestLogStackFromContext","line":"37","source":"stacktrace_test.go"\},.*\],"error":"from error: error message"\}\n` if ok, _ := regexp.MatchString(want, got); !ok { t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want) }