package logging import ( "fmt" "go/ast" "go/parser" "go/token" "os" "regexp" "strconv" "strings" ) type stackFrame struct { File string Line int Func string } var stackFileLinePattern = regexp.MustCompile(`\s*(.+\.go):(\d+)\s*$`) func finalApplicationCaller(stack string) (stackFrame, bool) { if stack == "" { return stackFrame{}, false } functionName := "" for _, raw := range strings.Split(stack, "\n") { line := strings.TrimSpace(raw) if line == "" { continue } matches := stackFileLinePattern.FindStringSubmatch(line) if matches == nil { functionName = line continue } lineNumber, _ := strconv.Atoi(matches[2]) if skipStackFile(matches[1]) { functionName = "" continue } return stackFrame{File: matches[1], Line: lineNumber, Func: functionName}, true } return stackFrame{}, false } func skipStackFile(filename string) bool { normalized := strings.ReplaceAll(filename, "\\", "/") for _, marker := range []string{ "/go/pkg/mod/", "/go.uber.org/", "/gorm.io/", "/pkg/logging/", "/internal/transport/middleware/", "/internal/transport/router/", "/internal/server/handler/", "/internal/server/middleware/", "/internal/server/router/", "/internal/server/httpx/", "/internal/server/middleware_", "/internal/server/route_", } { if strings.Contains(normalized, marker) { return true } } return strings.Contains(normalized, "/src/") && (strings.Contains(normalized, "/go/go") || strings.Contains(normalized, "/go/src/")) } func functionSourceAt(filename string, line int) (name, source string, startLine, endLine int, err error) { content, err := os.ReadFile(filename) if err != nil { return "", "", 0, 0, fmt.Errorf("read file failed: %w", err) } files := token.NewFileSet() parsed, err := parser.ParseFile(files, filename, content, parser.ParseComments) if err != nil { return "", "", 0, 0, fmt.Errorf("parse file failed: %w", err) } var target *ast.FuncDecl ast.Inspect(parsed, func(node ast.Node) bool { declaration, ok := node.(*ast.FuncDecl) if !ok { return true } start := files.Position(declaration.Pos()).Line end := files.Position(declaration.End()).Line if line >= start && line <= end { target, startLine, endLine = declaration, start, end return false } return true }) if target == nil { return "", "", 0, 0, fmt.Errorf("no function encloses line %d in %s", line, filename) } start := files.Position(target.Pos()).Offset end := files.Position(target.End()).Offset if start < 0 || end > len(content) || start >= end { return "", "", 0, 0, fmt.Errorf("invalid offsets for function: start=%d end=%d len=%d", start, end, len(content)) } return target.Name.Name, string(content[start:end]), startLine, endLine, nil }