mirror of
https://gitcode.com/flipped-aurora/gin-vue-admin.git
synced 2025-12-30 11:52:26 +00:00
79 lines
2.2 KiB
Go
79 lines
2.2 KiB
Go
|
|
package stacktrace
|
||
|
|
|
||
|
|
import (
|
||
|
|
"regexp"
|
||
|
|
"strconv"
|
||
|
|
"strings"
|
||
|
|
)
|
||
|
|
|
||
|
|
// Frame 表示一次栈帧解析结果
|
||
|
|
type Frame struct {
|
||
|
|
File string
|
||
|
|
Line int
|
||
|
|
Func string
|
||
|
|
}
|
||
|
|
|
||
|
|
var fileLineRe = regexp.MustCompile(`\s*(.+\.go):(\d+)\s*$`)
|
||
|
|
|
||
|
|
// FindFinalCaller 从 zap 的 entry.Stack 文本中,解析“最终业务调用方”的文件与行号
|
||
|
|
// 策略:自顶向下解析,优先选择第一条项目代码帧,过滤第三方库/标准库/框架中间件
|
||
|
|
func FindFinalCaller(stack string) (Frame, bool) {
|
||
|
|
if stack == "" {
|
||
|
|
return Frame{}, false
|
||
|
|
}
|
||
|
|
lines := strings.Split(stack, "\n")
|
||
|
|
var currFunc string
|
||
|
|
for i := 0; i < len(lines); i++ {
|
||
|
|
line := strings.TrimSpace(lines[i])
|
||
|
|
if line == "" {
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
if m := fileLineRe.FindStringSubmatch(line); m != nil {
|
||
|
|
file := m[1]
|
||
|
|
ln, _ := strconv.Atoi(m[2])
|
||
|
|
if shouldSkip(file) {
|
||
|
|
// 跳过此帧,同时重置函数名以避免错误配对
|
||
|
|
currFunc = ""
|
||
|
|
continue
|
||
|
|
}
|
||
|
|
return Frame{File: file, Line: ln, Func: currFunc}, true
|
||
|
|
}
|
||
|
|
// 记录函数名行,下一行通常是文件:行
|
||
|
|
currFunc = line
|
||
|
|
}
|
||
|
|
return Frame{}, false
|
||
|
|
}
|
||
|
|
|
||
|
|
func shouldSkip(file string) bool {
|
||
|
|
// 第三方库与 Go 模块缓存
|
||
|
|
if strings.Contains(file, "/go/pkg/mod/") {
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
if strings.Contains(file, "/go.uber.org/") {
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
if strings.Contains(file, "/gorm.io/") {
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
// 标准库
|
||
|
|
if strings.Contains(file, "/go/go") && strings.Contains(file, "/src/") { // e.g. /Users/name/go/go1.24.2/src/net/http/server.go
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
// 框架内不需要作为最终调用方的路径
|
||
|
|
if strings.Contains(file, "/server/core/zap.go") {
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
if strings.Contains(file, "/server/core/") {
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
if strings.Contains(file, "/server/utils/errorhook/") {
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
if strings.Contains(file, "/server/middleware/") {
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
if strings.Contains(file, "/server/router/") {
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
return false
|
||
|
|
}
|