85 lines
1.8 KiB
Go
85 lines
1.8 KiB
Go
package slog
|
|
|
|
import (
|
|
"runtime"
|
|
"strings"
|
|
)
|
|
|
|
var internalTracebackMethods = map[string]struct{}{
|
|
"Infof": {},
|
|
"Info": {},
|
|
"Infoln": {},
|
|
"Warnf": {},
|
|
"Warn": {},
|
|
"Warnln": {},
|
|
"Errorf": {},
|
|
"Error": {},
|
|
"Errorln": {},
|
|
"Fatalf": {},
|
|
"Fatal": {},
|
|
"Fatalln": {},
|
|
"Debugf": {},
|
|
"Debug": {},
|
|
"Debugln": {},
|
|
"print": {},
|
|
"println": {},
|
|
"reportWriterError": {},
|
|
"getTraceback": {},
|
|
"getFullTraceback": {},
|
|
}
|
|
|
|
func getTraceback() *MethodTraceback {
|
|
tracebacks := getFullTraceback(0)
|
|
if len(tracebacks) == 0 {
|
|
return nil
|
|
}
|
|
return tracebacks[0]
|
|
}
|
|
|
|
func getFullTraceback(skip int) []*MethodTraceback {
|
|
pc := make([]uintptr, 15)
|
|
n := runtime.Callers(skip+2, pc)
|
|
list := make([]*MethodTraceback, 0)
|
|
frames := runtime.CallersFrames(pc[:n])
|
|
for {
|
|
frame, more := frames.Next()
|
|
tb := buildMethodTraceback(frame.PC)
|
|
if tb != nil && !isInternalTraceback(tb) {
|
|
list = append(list, tb)
|
|
}
|
|
if !more {
|
|
break
|
|
}
|
|
}
|
|
return list
|
|
}
|
|
|
|
func buildMethodTraceback(pc uintptr) *MethodTraceback {
|
|
details := runtime.FuncForPC(pc)
|
|
if details == nil {
|
|
return nil
|
|
}
|
|
|
|
signature := details.Name()
|
|
path, line := details.FileLine(pc)
|
|
splitPath := strings.Split(path, "/")
|
|
splitSignature := strings.Split(signature, ".")
|
|
method := splitSignature[len(splitSignature)-1]
|
|
|
|
return &MethodTraceback{
|
|
Filename: splitPath[len(splitPath)-1],
|
|
FullPath: path,
|
|
Line: line,
|
|
Signature: signature,
|
|
Method: method,
|
|
}
|
|
}
|
|
|
|
func isInternalTraceback(tb *MethodTraceback) bool {
|
|
if strings.HasPrefix(tb.Signature, "runtime.") {
|
|
return true
|
|
}
|
|
_, ok := internalTracebackMethods[tb.Method]
|
|
return ok
|
|
}
|