Files
slog/traceback.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
}