128 lines
5.0 KiB
Markdown
128 lines
5.0 KiB
Markdown
|
|
---
|
|||
|
|
name: Fix caller detection v2
|
|||
|
|
overview: 重新设计 findCaller 的调用者过滤逻辑:(1) 删除 maxFrameworkDepth 提前退出 (2) 收窄 isHoTimeFrameworkFile 定义为仅跳过日志/DB执行管线,让框架业务文件(code/makecode.go、application.go、context.go 等)作为有意义的调用者返回。
|
|||
|
|
todos:
|
|||
|
|
- id: rewrite-findcaller
|
|||
|
|
content: 重写 findCaller:删除 maxFrameworkDepth、applicationFile 跟踪,简化为跳过基础设施 + 返回第一个业务文件
|
|||
|
|
status: completed
|
|||
|
|
- id: rewrite-framework-check
|
|||
|
|
content: 重命名 isHoTimeFrameworkFile 为 isInfrastructureFile,收窄到只匹配 log/db/cache/common/dri,移除 code/ 和 application.go 等
|
|||
|
|
status: completed
|
|||
|
|
isProject: false
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# 修复调用者智能识别(v2)
|
|||
|
|
|
|||
|
|
## 根因分析
|
|||
|
|
|
|||
|
|
用户看到 `[db/crud.go:149]`,实际调用者是 `code/makecode.go`。两个问题叠加:
|
|||
|
|
|
|||
|
|
**问题 A**: `maxFrameworkDepth = 10` 过低。zerolog 内部帧(~5) + log/logger.go(1) + db/query.go(3-4) + db/crud.go(1) 轻松达到 10,触发提前返回,根本没走到 `code/makecode.go`。
|
|||
|
|
|
|||
|
|
**问题 B**: 即使去掉 `maxFrameworkDepth`,`code/makecode.go` 在 `frameworkCoreDirs` 中被 `"code/"` + `"makecode.go"` 命中,也会被跳过。最终回退到 `applicationFile`(application.go)或 `lastFrameworkFile`,都不是用户想要的。
|
|||
|
|
|
|||
|
|
## 设计思路
|
|||
|
|
|
|||
|
|
用户原话:"应用层触发的就打印应用层的,如果是框架层的业务造成的就打印框架层对应位置的,但肯定不是 log/logger.go"。
|
|||
|
|
|
|||
|
|
核心区分:
|
|||
|
|
- **基础设施文件**(应跳过):日志管线(log/、zerolog/)、DB 执行管线(db/\*)、缓存中间件(cache/\*)、Go runtime、通用工具(common/\*)、数据库驱动(dri/\*)
|
|||
|
|
- **业务文件**(应返回):`code/makecode.go`、`application.go`、`context.go`、`session.go`、所有应用层代码
|
|||
|
|
|
|||
|
|
跳过基础设施,返回第一个业务文件。无论这个业务文件是应用层还是框架层。
|
|||
|
|
|
|||
|
|
## 具体修改
|
|||
|
|
|
|||
|
|
### 1. [log/logger.go](log/logger.go) -- `findCaller` 简化
|
|||
|
|
|
|||
|
|
- **删除** `maxFrameworkDepth` 常量(第 315 行)和 `frameworkCount >= maxFrameworkDepth` 提前退出(第 343-345 行)。`i < 20` 循环上限已足够保护。
|
|||
|
|
- **删除** `applicationFile` / `applicationLine` 跟踪及其回退逻辑(不再需要 application.go 特殊处理)。
|
|||
|
|
- **删除** `frameworkCount` 计数器(不再需要)。
|
|||
|
|
- 简化后的 `findCaller`:
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
func findCaller(origFile string, origLine int) string {
|
|||
|
|
var lastInfraFile string
|
|||
|
|
var lastInfraLine int
|
|||
|
|
|
|||
|
|
for i := 1; i < 20; i++ {
|
|||
|
|
_, file, line, ok := runtime.Caller(i)
|
|||
|
|
if !ok {
|
|||
|
|
break
|
|||
|
|
}
|
|||
|
|
shortFile := shortenPath(file)
|
|||
|
|
|
|||
|
|
if isInfrastructureFile(shortFile) {
|
|||
|
|
lastInfraFile = shortFile
|
|||
|
|
lastInfraLine = line
|
|||
|
|
continue
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return fmt.Sprintf("%s:%d", shortFile, line)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if lastInfraFile != "" {
|
|||
|
|
return fmt.Sprintf("%s:%d", lastInfraFile, lastInfraLine)
|
|||
|
|
}
|
|||
|
|
return fmt.Sprintf("%s:%d", shortenPath(origFile), origLine)
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. [log/logger.go](log/logger.go) -- 重命名 + 收窄 `isHoTimeFrameworkFile`
|
|||
|
|
|
|||
|
|
重命名为 `isInfrastructureFile`,仅匹配日志/DB/缓存/通用工具等"管道"文件:
|
|||
|
|
|
|||
|
|
```go
|
|||
|
|
func isInfrastructureFile(file string) bool {
|
|||
|
|
// 第三方日志库
|
|||
|
|
if strings.HasPrefix(file, "zerolog/") || strings.HasPrefix(file, "zerolog@") {
|
|||
|
|
return true
|
|||
|
|
}
|
|||
|
|
if strings.HasPrefix(file, "logrus/") || strings.HasPrefix(file, "logrus@") {
|
|||
|
|
return true
|
|||
|
|
}
|
|||
|
|
if strings.HasPrefix(file, "runtime/") {
|
|||
|
|
return true
|
|||
|
|
}
|
|||
|
|
// HoTime 日志包
|
|||
|
|
if strings.HasPrefix(file, "log/") {
|
|||
|
|
return true
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// DB 执行管线(db/ 下全部文件)
|
|||
|
|
infraPrefixes := []string{"db/", "cache/", "common/", "dri/"}
|
|||
|
|
for _, prefix := range infraPrefixes {
|
|||
|
|
if strings.HasPrefix(file, prefix) {
|
|||
|
|
return true
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 兼容路径含 hotime 的场景(module 全路径未被 shortenPath 完全截断时)
|
|||
|
|
lowerFile := strings.ToLower(file)
|
|||
|
|
if strings.Contains(lowerFile, "hotime") {
|
|||
|
|
infraDirs := []string{"db/", "cache/", "common/", "log/", "dri/"}
|
|||
|
|
for _, dir := range infraDirs {
|
|||
|
|
if strings.Contains(file, dir) {
|
|||
|
|
return true
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return false
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
关键变更:
|
|||
|
|
- `"code/"` 从所有列表中移除 -- `code/makecode.go` 不再被跳过
|
|||
|
|
- `application.go`、`context.go`、`session.go` 等单文件匹配全部移除 -- 框架业务文件不再被跳过
|
|||
|
|
- `frameworkCoreDirs` 中的 `"code/"` 及其文件名(makecode.go、template.go、config.go)移除
|
|||
|
|
|
|||
|
|
## 修复后效果
|
|||
|
|
|
|||
|
|
| 调用链 | 显示结果 |
|
|||
|
|
|--------|---------|
|
|||
|
|
| app/user.go -> db.GetMap -> logSQL | `app/user.go:XX` |
|
|||
|
|
| code/makecode.go -> db.GetList -> logSQL | `code/makecode.go:XX` |
|
|||
|
|
| application.go SetConfig -> db -> logSQL | `application.go:XX` |
|
|||
|
|
| context.go session -> db -> logSQL | `context.go:XX` |
|