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 }