-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstacktrace.go
More file actions
95 lines (80 loc) · 1.98 KB
/
Copy pathstacktrace.go
File metadata and controls
95 lines (80 loc) · 1.98 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
83
84
85
86
87
88
89
90
91
92
93
94
95
package errors
import (
"bytes"
"fmt"
"go/build"
"runtime"
"strconv"
"strings"
)
const (
stacktraceDepth = 16
)
var (
// nolint:gochecknoglobals
gopath = build.Default.GOPATH + "/src/"
// nolint:gochecknoglobals
goroot = runtime.GOROOT() + "/src/"
)
// stacktrace wraps a stacktrace of program counters.
type Stacktrace []uintptr
// newStacktrace returns a stacktrace.
func newStacktrace() Stacktrace {
s := make(Stacktrace, stacktraceDepth)
// Skipping 3 runtime callers:
// 0 - runtime.Callers()
// 1 - stacktrace.New()
// 2 - errors.newQueue()
// 3 - errors.Wrap()
n := runtime.Callers(3, s)
return s[0:n]
}
// Format prints the stacktrace.
func (s Stacktrace) Format(st fmt.State, _ rune) {
b := new(bytes.Buffer)
ff := runtime.CallersFrames([]uintptr(s))
var mainProcessed bool
for {
f, more := ff.Next()
file := sanitizeFilename(f.File)
line := strconv.Itoa(f.Line)
fun := sanitizeFuncName(f.Function)
// Don't print anything beyond main.main.
if mainProcessed && !strings.HasPrefix(fun, "main.") {
break
}
if !mainProcessed && fun == "main.main()" {
mainProcessed = true
}
b.WriteString("\t")
b.WriteString(file)
b.WriteString(":")
b.WriteString(line)
b.WriteString(" ")
b.WriteString(fun)
b.WriteString("\n")
if !more {
break
}
}
// nolint
_, _ = b.WriteTo(st)
}
// sanitizeFuncName trims fully qualified module path from the function name.
// Transforms:
// github.com/ameteiko/errors/stacktrace.New -> stacktrace.New()
func sanitizeFuncName(n string) string {
if n == "" {
return "unknown"
}
lastSlashIndex := strings.LastIndex(n, "/")
return n[lastSlashIndex+1:] + "()"
}
// sanitizeFilename trims GOROOT and GOPATH prefixes from the fully qualified file name.
// Transforms:
// /Users/ameteiko/Projects/go/src/github.com/ameteiko/errors/errors.go -> github.com/ameteiko/errors/errors.go
func sanitizeFilename(n string) string {
n = strings.TrimPrefix(n, gopath)
n = strings.TrimPrefix(n, goroot)
return n
}