From ec6853cd6787c987f49ad7336a673b4c1cb28ef6 Mon Sep 17 00:00:00 2001 From: Yuki Iwanaga Date: Mon, 17 Apr 2017 18:15:08 +0900 Subject: [PATCH 1/4] Expose file and line of Frame --- stack.go | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/stack.go b/stack.go index 6b1f2891..481410f5 100644 --- a/stack.go +++ b/stack.go @@ -15,9 +15,9 @@ type Frame uintptr // multiple frames may have the same PC value. func (f Frame) pc() uintptr { return uintptr(f) - 1 } -// file returns the full path to the file that contains the +// File returns the full path to the file that contains the // function for this Frame's pc. -func (f Frame) file() string { +func (f Frame) File() string { fn := runtime.FuncForPC(f.pc()) if fn == nil { return "unknown" @@ -26,9 +26,9 @@ func (f Frame) file() string { return file } -// line returns the line number of source code of the +// Line returns the line number of source code of the // function for this Frame's pc. -func (f Frame) line() int { +func (f Frame) Line() int { fn := runtime.FuncForPC(f.pc()) if fn == nil { return 0 @@ -62,13 +62,12 @@ func (f Frame) Format(s fmt.State, verb rune) { fmt.Fprintf(s, "%s\n\t%s", fn.Name(), file) } default: - io.WriteString(s, path.Base(f.file())) + io.WriteString(s, path.Base(f.File())) } case 'd': - fmt.Fprintf(s, "%d", f.line()) + fmt.Fprintf(s, "%d", f.Line()) case 'n': - name := runtime.FuncForPC(f.pc()).Name() - io.WriteString(s, funcname(name)) + io.WriteString(s, f.Name()) case 'v': f.Format(s, 's') io.WriteString(s, ":") From b8b5eb297b53b50ace00f3e33456ad90baf9ad8f Mon Sep 17 00:00:00 2001 From: Yuki Iwanaga Date: Mon, 17 Apr 2017 18:16:06 +0900 Subject: [PATCH 2/4] Add method for retrieving a name of function --- stack.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/stack.go b/stack.go index 481410f5..f962cb73 100644 --- a/stack.go +++ b/stack.go @@ -11,6 +11,11 @@ import ( // Frame represents a program counter inside a stack frame. type Frame uintptr +// Name returns the name of function for this Frame's pc. +func (f Frame) Name() string { + return funcname(runtime.FuncForPC(f.pc()).Name()) +} + // pc returns the program counter for this frame; // multiple frames may have the same PC value. func (f Frame) pc() uintptr { return uintptr(f) - 1 } From f43bbc05515084f1f75c34818c2b20967907a1ff Mon Sep 17 00:00:00 2001 From: Yuki Iwanaga Date: Mon, 17 Apr 2017 18:16:27 +0900 Subject: [PATCH 3/4] Create helper function --- errors.go | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/errors.go b/errors.go index 842ee804..66d7b658 100644 --- a/errors.go +++ b/errors.go @@ -267,3 +267,42 @@ func Cause(err error) error { } return err } + +// Trace returns the underlying stack trace of the error, if possible. +// An error value has a stack trace if it implements the following +// interface: +// +// type stackTracer interface { +// StackTrace() errors.StackTrace +// } +// +// If the error does not implement StackTrace, nil will be returned. +// If the error is nil, nil will be returned without further +// investigation. +func Trace(err error) (frames []Frame) { + if err == nil { + return nil + } + + type stackTracer interface { + StackTrace() StackTrace + } + + type causer interface { + Cause() error + } + + for err != nil { + if stackTrace, ok := err.(stackTracer); ok { + frames = ([]Frame)(stackTrace.StackTrace()) + } + + if cause, ok := err.(causer); ok { + err = cause.Cause() + } else { + break + } + } + + return +} From bde06eed088a8e79b2c0c584ad92e4de2bbc4095 Mon Sep 17 00:00:00 2001 From: Yuki Iwanaga Date: Mon, 17 Apr 2017 18:45:56 +0900 Subject: [PATCH 4/4] Fix test --- stack_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stack_test.go b/stack_test.go index 510c27a9..fe9dca0f 100644 --- a/stack_test.go +++ b/stack_test.go @@ -33,7 +33,7 @@ func TestFrameLine(t *testing.T) { }} for _, tt := range tests { - got := tt.Frame.line() + got := tt.Frame.Line() want := tt.want if want != got { t.Errorf("Frame(%v): want: %v, got: %v", uintptr(tt.Frame), want, got)