refactor(log): 优化日志调用栈查找逻辑
- 添加最大框架层数限制防止误过滤应用层 - 新增 isHoTimeFrameworkFile 函数精确识别框架文件 - 实现更准确的框架文件过滤机制 - 替换原有的简单前缀匹配为复合条件判断 - 添加框架核心目录和文件的精确匹配规则 - 改进调用栈遍历算法提高查找准确性
This commit is contained in:
parent
d1b905b780
commit
f4760c5d3e
124
log/logrus.go
124
log/logrus.go
@ -2,12 +2,13 @@ package log
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetLog(path string, showCodeLine bool) *log.Logger {
|
func GetLog(path string, showCodeLine bool) *log.Logger {
|
||||||
@ -73,41 +74,98 @@ func (that *MyHook) Fire(entry *log.Entry) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 对caller进行递归查询, 直到找到非logrus包产生的第一个调用.
|
// 最大框架层数限制 - 超过这个层数后不再跳过,防止误过滤应用层
|
||||||
// 因为filename我获取到了上层目录名, 因此所有logrus包的调用的文件名都是 logrus/...
|
const maxFrameworkDepth = 10
|
||||||
// 因此通过排除logrus开头的文件名, 就可以排除所有logrus包的自己的函数调用
|
|
||||||
func findCaller(skip int) string {
|
|
||||||
file := ""
|
|
||||||
line := 0
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
file, line = getCaller(skip + i)
|
|
||||||
if !strings.HasPrefix(file, "logrus") {
|
|
||||||
j := 0
|
|
||||||
for true {
|
|
||||||
j++
|
|
||||||
if file == "common/error.go" {
|
|
||||||
file, line = getCaller(skip + i + j)
|
|
||||||
}
|
|
||||||
if file == "db/hotimedb.go" {
|
|
||||||
file, line = getCaller(skip + i + j)
|
|
||||||
}
|
|
||||||
if file == "code/makecode.go" {
|
|
||||||
file, line = getCaller(skip + i + j)
|
|
||||||
}
|
|
||||||
if strings.Index(file, "common/") == 0 {
|
|
||||||
file, line = getCaller(skip + i + j)
|
|
||||||
}
|
|
||||||
if strings.Contains(file, "application.go") {
|
|
||||||
file, line = getCaller(skip + i + j)
|
|
||||||
}
|
|
||||||
if j == 5 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break
|
// isHoTimeFrameworkFile 判断是否是 HoTime 框架文件
|
||||||
|
// 更精确的匹配:只有明确属于框架的文件才会被跳过
|
||||||
|
func isHoTimeFrameworkFile(file string) bool {
|
||||||
|
// 1. logrus 日志库内部文件
|
||||||
|
if strings.HasPrefix(file, "logrus/") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Go 运行时文件
|
||||||
|
if strings.HasPrefix(file, "runtime/") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. HoTime 框架核心文件 - 通过包含 "hotime" 或框架特有文件名来识别
|
||||||
|
// 检查路径中是否包含 hotime 框架标识
|
||||||
|
lowerFile := strings.ToLower(file)
|
||||||
|
if strings.Contains(lowerFile, "hotime") {
|
||||||
|
// 是 hotime 框架的一部分,检查是否是核心模块
|
||||||
|
frameworkDirs := []string{"/db/", "/common/", "/code/", "/cache/", "/log/", "/dri/"}
|
||||||
|
for _, dir := range frameworkDirs {
|
||||||
|
if strings.Contains(file, dir) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 框架核心文件(在 hotime 根目录下的 .go 文件)
|
||||||
|
if strings.HasSuffix(file, "application.go") ||
|
||||||
|
strings.HasSuffix(file, "context.go") ||
|
||||||
|
strings.HasSuffix(file, "session.go") ||
|
||||||
|
strings.HasSuffix(file, "const.go") ||
|
||||||
|
strings.HasSuffix(file, "type.go") ||
|
||||||
|
strings.HasSuffix(file, "var.go") ||
|
||||||
|
strings.HasSuffix(file, "mime.go") {
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 4. 直接匹配框架核心目录(用于没有完整路径的情况)
|
||||||
|
// 只匹配 "db/xxx.go" 这种在框架核心目录下的文件
|
||||||
|
frameworkCoreDirs := []string{"db/", "common/", "code/", "cache/"}
|
||||||
|
for _, dir := range frameworkCoreDirs {
|
||||||
|
if strings.HasPrefix(file, dir) {
|
||||||
|
// 额外检查:确保不是用户项目中同名目录
|
||||||
|
// 框架文件通常有特定的文件名
|
||||||
|
frameworkFiles := []string{
|
||||||
|
"query.go", "crud.go", "where.go", "builder.go", "db.go",
|
||||||
|
"dialect.go", "aggregate.go", "transaction.go", "identifier.go",
|
||||||
|
"error.go", "func.go", "map.go", "obj.go", "slice.go",
|
||||||
|
"makecode.go", "template.go", "config.go",
|
||||||
|
"cache.go", "cache_db.go", "cache_memory.go", "cache_redis.go",
|
||||||
|
}
|
||||||
|
for _, f := range frameworkFiles {
|
||||||
|
if strings.HasSuffix(file, f) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 对caller进行递归查询, 直到找到非框架层产生的第一个调用.
|
||||||
|
// 遍历调用栈,跳过框架层文件,找到应用层代码
|
||||||
|
// 使用层数限制确保不会误过滤应用层同名目录
|
||||||
|
func findCaller(skip int) string {
|
||||||
|
frameworkCount := 0 // 连续框架层计数
|
||||||
|
|
||||||
|
// 遍历调用栈,找到第一个非框架文件
|
||||||
|
for i := 0; i < 20; i++ {
|
||||||
|
file, line := getCaller(skip + i)
|
||||||
|
if file == "" {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if isHoTimeFrameworkFile(file) {
|
||||||
|
frameworkCount++
|
||||||
|
// 层数限制:如果已经跳过太多层,停止跳过
|
||||||
|
if frameworkCount >= maxFrameworkDepth {
|
||||||
|
return fmt.Sprintf("%s:%d", file, line)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// 找到非框架文件,返回应用层代码位置
|
||||||
|
return fmt.Sprintf("%s:%d", file, line)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果找不到应用层,返回最初的调用者
|
||||||
|
file, line := getCaller(skip)
|
||||||
return fmt.Sprintf("%s:%d", file, line)
|
return fmt.Sprintf("%s:%d", file, line)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user