From 2988c1e4447c54de921bad2b5c243f43dd2e174e Mon Sep 17 00:00:00 2001 From: Olivier Poitrey Date: Wed, 2 Jan 2019 13:19:14 -0800 Subject: [PATCH] pkgerrors: remove fmt dep --- pkgerrors/stacktrace.go | 39 +++++++++++++++++++++++++++++++----- pkgerrors/stacktrace_test.go | 13 ++++++++++++ 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/pkgerrors/stacktrace.go b/pkgerrors/stacktrace.go index a868e56..4d0b121 100644 --- a/pkgerrors/stacktrace.go +++ b/pkgerrors/stacktrace.go @@ -1,8 +1,6 @@ package pkgerrors import ( - "fmt" - "github.com/pkg/errors" ) @@ -12,6 +10,36 @@ var ( StackSourceFunctionName = "func" ) +type state struct { + b []byte +} + +// Write implement fmt.Formatter interface. +func (s *state) Write(b []byte) (n int, err error) { + s.b = b + return len(b), nil +} + +// Width implement fmt.Formatter interface. +func (s *state) Width() (wid int, ok bool) { + return 0, false +} + +// Precision implement fmt.Formatter interface. +func (s *state) Precision() (prec int, ok bool) { + return 0, false +} + +// Flag implement fmt.Formatter interface. +func (s *state) Flag(c int) bool { + return false +} + +func frameField(f errors.Frame, s *state, c rune) string { + f.Format(s, c) + return string(s.b) +} + // MarshalStack implements pkg/errors stack trace marshaling. // // zerolog.ErrorStackMarshaler = MarshalStack @@ -25,12 +53,13 @@ func MarshalStack(err error) interface{} { } else { return nil } + s := &state{} out := make([]map[string]string, 0, len(st)) for _, frame := range st { out = append(out, map[string]string{ - StackSourceFileName: fmt.Sprintf("%s", frame), - StackSourceLineName: fmt.Sprintf("%d", frame), - StackSourceFunctionName: fmt.Sprintf("%n", frame), + StackSourceFileName: frameField(frame, s, 's'), + StackSourceLineName: frameField(frame, s, 'd'), + StackSourceFunctionName: frameField(frame, s, 'n'), }) } return out diff --git a/pkgerrors/stacktrace_test.go b/pkgerrors/stacktrace_test.go index a77428f..e771317 100644 --- a/pkgerrors/stacktrace_test.go +++ b/pkgerrors/stacktrace_test.go @@ -26,3 +26,16 @@ func TestLogStack(t *testing.T) { t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want) } } + +func BenchmarkLogStack(b *testing.B) { + zerolog.ErrorStackMarshaler = MarshalStack + out := &bytes.Buffer{} + log := zerolog.New(out) + err := errors.Wrap(errors.New("error message"), "from error") + b.ReportAllocs() + + for i := 0; i < b.N; i++ { + log.Log().Stack().Err(err).Msg("") + out.Reset() + } +}