mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-03-07 08:46:59 -05:00
107 lines
2.3 KiB
Go
107 lines
2.3 KiB
Go
package stdutil
|
|
|
|
import (
|
|
"path"
|
|
"runtime"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// some commonly consts
|
|
var (
|
|
DefStackLen = 10000
|
|
MaxStackLen = 100000
|
|
)
|
|
|
|
// GetCallStacks stacks is a wrapper for runtime.
|
|
// If all is true, Stack that attempts to recover the data for all goroutines.
|
|
//
|
|
// from glog package
|
|
func GetCallStacks(all bool) []byte {
|
|
// We don't know how big the traces are, so grow a few times if they don't fit.
|
|
// Start large, though.
|
|
n := DefStackLen
|
|
if all {
|
|
n = MaxStackLen
|
|
}
|
|
|
|
// 4<<10 // 4 KB should be enough
|
|
var trace []byte
|
|
for i := 0; i < 10; i++ {
|
|
trace = make([]byte, n)
|
|
bts := runtime.Stack(trace, all)
|
|
if bts < len(trace) {
|
|
return trace[:bts]
|
|
}
|
|
n *= 2
|
|
}
|
|
return trace
|
|
}
|
|
|
|
// GetCallerInfo get caller func name and with base filename and line.
|
|
//
|
|
// returns:
|
|
//
|
|
// github.com/gookit/goutil/stdutil_test.someFunc2(),stack_test.go:26
|
|
func GetCallerInfo(skip int) string {
|
|
skip++ // ignore current func
|
|
cs := GetCallersInfo(skip, skip+1)
|
|
|
|
if len(cs) > 0 {
|
|
return cs[0]
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// SimpleCallersInfo returns an array of strings containing
|
|
// the func name, file and line number of each stack frame leading.
|
|
func SimpleCallersInfo(skip, num int) []string {
|
|
skip++ // ignore current func
|
|
return GetCallersInfo(skip, skip+num)
|
|
}
|
|
|
|
// GetCallersInfo returns an array of strings containing
|
|
// the func name, file and line number of each stack frame leading.
|
|
// NOTICE: max should > skip
|
|
func GetCallersInfo(skip, max int) []string {
|
|
var (
|
|
pc uintptr
|
|
ok bool
|
|
line int
|
|
file, name string
|
|
)
|
|
|
|
callers := make([]string, 0, max-skip)
|
|
for i := skip; i < max; i++ {
|
|
pc, file, line, ok = runtime.Caller(i)
|
|
if !ok {
|
|
// The breaks below failed to terminate the loop, and we ran off the
|
|
// end of the call stack.
|
|
break
|
|
}
|
|
|
|
// This is a huge edge case, but it will panic if this is the case
|
|
if file == "<autogenerated>" {
|
|
break
|
|
}
|
|
|
|
fc := runtime.FuncForPC(pc)
|
|
if fc == nil {
|
|
break
|
|
}
|
|
|
|
if strings.ContainsRune(file, '/') {
|
|
name = fc.Name()
|
|
file = path.Base(file)
|
|
// eg: github.com/gookit/goutil/stdutil_test.someFunc2(),stack_test.go:26
|
|
callers = append(callers, name+"(),"+file+":"+strconv.Itoa(line))
|
|
}
|
|
|
|
// Drop the package
|
|
// segments := strings.Split(name, ".")
|
|
// name = segments[len(segments)-1]
|
|
}
|
|
|
|
return callers
|
|
}
|