...
1package errors
2
3import (
4 "fmt"
5 "runtime"
6 // "runtime/debug"
7 "strings"
8)
9
10type stacktrace struct {
11 frames *runtime.Frames
12}
13
14// returns a single line with the calling function immedialy preceding the function which invoked this one (copied from utils/not_impl.go)
15func callingFunction() (string, *stacktrace) {
16 pc := make([]uintptr, 128)
17 num := runtime.Callers(0, pc)
18 if num == 0 {
19 return "[no caller]", nil
20 }
21 pc = pc[:num] // pass only valid pcs to runtime.CallersFrames
22 frames := runtime.CallersFrames(pc)
23 st := &stacktrace{frames: frames}
24 res := "[unidentifiable caller]"
25 more := true
26 var frame runtime.Frame
27 for {
28 // Check whether there are more frames to process after this one.
29 if !more {
30 break
31 }
32 frame, more = frames.Next()
33 fmt.Printf("FUNCTION: %s:%d\n", frame.Function, frame.Line)
34 // Process this frame.
35 //
36 // To keep this example's output stable
37 // even if there are changes in the testing package,
38 // stop unwinding when we leave package runtime.
39 if strings.Contains(frame.File, "runtime/") {
40 continue
41 }
42 if strings.Contains(frame.Function, "golang.conradwood.net/go-easyops/errors") {
43 continue
44 }
45
46 name := frame.Function
47 n := strings.LastIndex(name, ".")
48 if n != -1 {
49 name = name[n+1:] + "()"
50 }
51 fname := frame.File
52 n = strings.LastIndex(fname, "/src/")
53 if n != -1 {
54 fname = fname[n+5:]
55 }
56 res = fmt.Sprintf("%s in %s:%d", name, fname, frame.Line)
57 break
58 // fmt.Printf("- more:%v | %s\n", more, frame.Function)
59
60 }
61 return res, st
62}
View as plain text