forked from codemodify/systemkit-callstack
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcallstack.go
More file actions
82 lines (69 loc) · 1.84 KB
/
callstack.go
File metadata and controls
82 lines (69 loc) · 1.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package callstack
import (
"encoding/json"
"runtime"
"strings"
)
// Frame -
type Frame struct {
File string `json:"file"`
Line int `json:"line"`
Func string `json:"function"`
}
// String - `stringer` interface
func (thisRef Frame) String() string {
data, _ := json.Marshal(thisRef)
return string(data)
}
// GetFrames - Gets the call stack with no frames skipped
func GetFrames() []Frame {
return GetFramesWithSkip(0)
}
// GetFramesWithSkip - Gets the call stack with N skipped frames
func GetFramesWithSkip(skip int) []Frame {
return GetFramesFromRawFrames(GetRawFrames(skip))
}
// GetRawFrames -
func GetRawFrames(skip int) []uintptr {
const callStackDepth = 50 // most relevant context seem to appear near the top of the stack
var callStackBuffer = make([]uintptr, callStackDepth)
callStackSize := runtime.Callers(skip, callStackBuffer)
return callStackBuffer[:callStackSize]
}
// GetFramesFromRawFrames -
func GetFramesFromRawFrames(callStack []uintptr) []Frame {
frames := []Frame{}
callStackFrames := runtime.CallersFrames(callStack)
for {
frame, ok := callStackFrames.Next()
if !ok {
break
}
pkg, fn := splitPackageFuncName(frame.Function)
if frameFilter(pkg, fn, frame.File, frame.Line) {
frames = frames[:0]
continue
}
frames = append(frames, Frame{
File: frame.File,
Line: frame.Line,
Func: fn,
})
}
return frames
}
func splitPackageFuncName(funcName string) (string, string) {
var packageName string
if ind := strings.LastIndex(funcName, "/"); ind > 0 {
packageName += funcName[:ind+1]
funcName = funcName[ind+1:]
}
if ind := strings.Index(funcName, "."); ind > 0 {
packageName += funcName[:ind]
funcName = funcName[ind+1:]
}
return packageName, funcName
}
func frameFilter(packageName, funcName string, file string, line int) bool {
return packageName == "runtime" && funcName == "panic"
}