Compare commits

..

2 Commits

Author SHA1 Message Date
AI Engineer
eff999f6f2 fix(log): merge extra callStacks into structured field, add isLogPkgFile for module-path compatibility
- Error() now merges callStacks from extra into entry.CallStacks
- New isLogPkgFile helper handles both local and module proxy paths

Co-Authored-By: deepseek-v4-pro[1m] <deepseek-ai@claude-code-best.win>
2026-06-20 22:08:49 +08:00
AI Engineer
ac6efeb1a9 chore: align infrastructure to v1.5.x (by AI) 2026-06-11 22:24:09 +08:00
4 changed files with 40 additions and 15 deletions

View File

@ -1,5 +1,14 @@
# Changelog # Changelog
## [1.5.7] - 2026-06-20
- **调用栈容错增强**:
- `Error` 方法现在支持通过 `extra` 参数传入 `callStacks` 字段,自动合并到结构化的 `CallStacks` 字段中,避免外部调用栈信息丢失。
- **模块路径兼容**:
- 新增 `isLogPkgFile` 辅助函数,统一处理本地路径 (`.../log/file.go`) 和 Go module 版本路径 (`.../log@v1.5.6/file.go`) 的文件匹配,确保在 module proxy 场景下调用栈过滤同样精准。
## [1.5.6] - 2026-06-20
- **基础设施对齐**: 内部依赖统一升级至 v1.5.x 语义版本。
## [1.5.5] - 2026-06-05 ## [1.5.5] - 2026-06-05
- **规范化: Warning 日志行为对齐**: - **规范化: Warning 日志行为对齐**:
- ** Convention 对齐**: 移除了 `Warning` 级别日志自动附带堆栈信息(`CallStacks`)的逻辑。 - ** Convention 对齐**: 移除了 `Warning` 级别日志自动附带堆栈信息(`CallStacks`)的逻辑。

18
go.mod
View File

@ -3,19 +3,19 @@ module apigo.cc/go/log
go 1.25.0 go 1.25.0
require ( require (
apigo.cc/go/cast v1.5.0 apigo.cc/go/cast v1.5.2
apigo.cc/go/config v1.5.0 apigo.cc/go/config v1.5.2
apigo.cc/go/file v1.5.0 apigo.cc/go/file v1.5.4
apigo.cc/go/id v1.5.0 apigo.cc/go/id v1.5.3
apigo.cc/go/shell v1.5.0 apigo.cc/go/shell v1.5.2
) )
require apigo.cc/go/jsmod v1.5.0 // indirect require apigo.cc/go/jsmod v1.5.2 // indirect
require ( require (
apigo.cc/go/encoding v1.5.0 // indirect apigo.cc/go/encoding v1.5.3 // indirect
apigo.cc/go/rand v1.5.0 // indirect apigo.cc/go/rand v1.5.2 // indirect
apigo.cc/go/safe v1.5.0 // indirect apigo.cc/go/safe v1.5.1 // indirect
golang.org/x/crypto v0.51.0 // indirect golang.org/x/crypto v0.51.0 // indirect
golang.org/x/sys v0.44.0 // indirect golang.org/x/sys v0.44.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect

View File

@ -282,6 +282,13 @@ func (logger *Logger) Error(message string, extra ...any) {
logger.FillError(entry, message) logger.FillError(entry, message)
if len(extra) > 0 { if len(extra) > 0 {
cast.FillMap(&entry.Extra, extra) cast.FillMap(&entry.Extra, extra)
// Merge extra callStacks into the structured CallStacks field
if stacks, ok := entry.Extra["callStacks"]; ok {
if s, ok := stacks.([]string); ok && len(s) > 0 {
entry.CallStacks = append(s, entry.CallStacks...)
}
delete(entry.Extra, "callStacks")
}
} }
logger.Log(entry) logger.Log(entry)
} }

View File

@ -52,6 +52,15 @@ func fixField(s string) string {
return strings.ToLower(s) return strings.ToLower(s)
} }
// isLogPkgFile checks whether a runtime.Caller file path belongs to the log
// package's internal implementation files. It handles both local paths
// (.../log/file.go) and Go module paths with version suffixes
// (.../log@v1.5.6/file.go).
func isLogPkgFile(file, name string) bool {
return strings.HasSuffix(file, "/log/"+name) ||
(strings.Contains(file, "/log@") && strings.HasSuffix(file, "/"+name))
}
// getCallStacks 获取调用栈 // getCallStacks 获取调用栈
func getCallStacks(truncations []string) []string { func getCallStacks(truncations []string) []string {
callStacks := make([]string, 0) callStacks := make([]string, 0)
@ -65,12 +74,12 @@ func getCallStacks(truncations []string) []string {
continue continue
} }
// 只有在 logger.go, extra.go 等核心实现文件中的帧才被认为是 "inLogger" // 只有在 logger.go, extra.go 等核心实现文件中的帧才被认为是 "inLogger"
// 这样可以保留测试文件 (xxx_test.go) 的调用栈 // 兼容本地路径 (.../log/file.go) 和 module 路径 (.../log@v1.5.6/file.go)
isLogInternal := (strings.Contains(file, "/log/logger.go") || isLogInternal := isLogPkgFile(file, "logger.go") ||
strings.Contains(file, "/log/utility.go") || isLogPkgFile(file, "utility.go") ||
strings.Contains(file, "/log/standard.go") || isLogPkgFile(file, "standard.go") ||
strings.Contains(file, "/log/default_logger.go") || isLogPkgFile(file, "default_logger.go") ||
strings.Contains(file, "/log/extra.go")) isLogPkgFile(file, "extra.go")
if isLogInternal { if isLogInternal {
if inLogger { if inLogger {