...
1 package utils
2
3 import (
4 "fmt"
5 "runtime"
6 "runtime/debug"
7 "strings"
8 )
9
10 func NotImpl(format string, args ...interface{}) {
11 s := fmt.Sprintf(format, args...)
12 fmt.Printf("[goeasyops] Not Implemented: %s\n", s)
13 debug.PrintStack()
14 }
15
16
17 func PrintStack(format string, args ...interface{}) {
18 s := GetStack(format, args...)
19 fmt.Print(s)
20
21 }
22
23
24 func GetStack(format string, args ...interface{}) string {
25 sx := GetStackLines()
26 s := fmt.Sprintf("Stacktrace for: "+format+"\n", args...)
27 s = s + strings.Join(sx, "\n")
28 s = s + "---end stacktrace\n"
29 return s
30 }
31
32
33 func GetStackLines() []string {
34 var res []string
35 pc := make([]uintptr, 128)
36 num := runtime.Callers(0, pc)
37 if num == 0 {
38 return []string{"[nostack]"}
39 }
40 pc = pc[:num]
41 frames := runtime.CallersFrames(pc)
42
43 more := true
44 var frame runtime.Frame
45 ignore_functions := []string{
46 "golang.conradwood.net/go-easyops/utils.PrintStack",
47 "golang.conradwood.net/go-easyops/utils.GetStack",
48 }
49 for {
50
51 if !more {
52 break
53 }
54 frame, more = frames.Next()
55
56
57
58
59
60 if strings.Contains(frame.File, "runtime/") {
61 continue
62 }
63 ign := false
64 for _, ifu := range ignore_functions {
65 if strings.Contains(frame.Function, ifu) {
66 ign = true
67 break
68 }
69 }
70 if ign {
71 continue
72 }
73
74 name := frame.Function
75 n := strings.LastIndex(name, ".")
76 if n != -1 {
77 name = name[n+1:] + "()"
78 }
79 fname := frame.File
80 n = strings.LastIndex(fname, "/src/")
81 if n != -1 {
82 fname = fname[n+5:]
83 }
84 res = append(res, fmt.Sprintf(" %s in %s:%d\n", name, fname, frame.Line))
85 }
86 return res
87 }
88
89
90 func CallingFunction() string {
91 pc := make([]uintptr, 128)
92 num := runtime.Callers(0, pc)
93 if num == 0 {
94 return "[no caller]"
95 }
96 pc = pc[:num]
97 frames := runtime.CallersFrames(pc)
98 res := "[unidentifiable caller]"
99 more := true
100 var frame runtime.Frame
101 i := 0
102 for {
103
104 if !more {
105 break
106 }
107 frame, more = frames.Next()
108
109
110
111
112
113 if strings.Contains(frame.File, "runtime/") {
114 continue
115 }
116 if strings.Contains(frame.Function, "golang.conradwood.net/go-easyops/utils.CallingFunction") {
117 continue
118 }
119 i++
120 if i < 2 {
121 continue
122 }
123 name := frame.Function
124 n := strings.LastIndex(name, ".")
125 if n != -1 {
126 name = name[n+1:] + "()"
127 }
128 fname := frame.File
129 n = strings.LastIndex(fname, "/src/")
130 if n != -1 {
131 fname = fname[n+5:]
132 }
133 res = fmt.Sprintf("%s in %s:%d", name, fname, frame.Line)
134 break
135
136
137 }
138 return res
139 }
140
View as plain text