This repository has been archived by the owner on Dec 31, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
stack_helper.go
82 lines (70 loc) · 1.83 KB
/
stack_helper.go
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 log
import (
"runtime"
"strings"
"sync"
)
// CalcStackFrames _
func CalcStackFrames(skipFramesAtFirst int) (skipped int) {
// cache this package's fully-qualified name
callerInitOnce.Do(func() {
pcs := make([]uintptr, 2)
_ = runtime.Callers(0, pcs)
logPackage := "github.com/hedzr/log" // and logx, logex
logrusPackage := "github.com/sirupsen/logrus"
errorsPackage := "gopkg.in/hedzr/errors.v"
knownPackages = append(knownPackages, "runtime", "reflect", logPackage, logrusPackage, errorsPackage)
knownPathes = []string{"/usr/local/go/src/"}
})
// Restrict the lookback frames to avoid runaway lookups
pcs := make([]uintptr, maximumCallerDepth)
depth := runtime.Callers(skipFramesAtFirst+2 /*minimumCallerDepth*/ /*+skipFrames*/, pcs)
frames := runtime.CallersFrames(pcs[:depth])
skipped = 0
for f, again := frames.Next(); again; f, again = frames.Next() {
pkg := getPackageName(f.Function)
if !contains(knownPackages, pkg) && !containsPartialsOnly(knownPathes, f.File) {
break
}
skipped++
}
return
}
var (
knownPackages []string
knownPathes []string
callerInitOnce sync.Once
)
const (
maximumCallerDepth int = 25
)
// getPackageName reduces a fully qualified function name to the package name
// There really ought to be to be a better way...
func getPackageName(f string) string {
for {
lastPeriod := strings.LastIndex(f, ".")
lastSlash := strings.LastIndex(f, "/")
if lastPeriod > lastSlash {
f = f[:lastPeriod]
} else {
break
}
}
return f
}
func contains(names []string, name string) bool {
for _, n := range names {
if strings.EqualFold(n, name) {
return true
}
}
return false
}
func containsPartialsOnly(partialNames []string, testedString string) (contains bool) {
for _, n := range partialNames {
if strings.Contains(testedString, n) {
return true
}
}
return
}