Compare commits

..

No commits in common. "eff999f6f27cd48db58ae0eac40c437a8a2a4c56" and "438a424d94969b99c25bb7e0bdf3e63d1cc3c783" have entirely different histories.

4 changed files with 15 additions and 40 deletions

View File

@ -1,14 +1,5 @@
# 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.2 apigo.cc/go/cast v1.5.0
apigo.cc/go/config v1.5.2 apigo.cc/go/config v1.5.0
apigo.cc/go/file v1.5.4 apigo.cc/go/file v1.5.0
apigo.cc/go/id v1.5.3 apigo.cc/go/id v1.5.0
apigo.cc/go/shell v1.5.2 apigo.cc/go/shell v1.5.0
) )
require apigo.cc/go/jsmod v1.5.2 // indirect require apigo.cc/go/jsmod v1.5.0 // indirect
require ( require (
apigo.cc/go/encoding v1.5.3 // indirect apigo.cc/go/encoding v1.5.0 // indirect
apigo.cc/go/rand v1.5.2 // indirect apigo.cc/go/rand v1.5.0 // indirect
apigo.cc/go/safe v1.5.1 // indirect apigo.cc/go/safe v1.5.0 // 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,13 +282,6 @@ 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,15 +52,6 @@ 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)
@ -74,12 +65,12 @@ func getCallStacks(truncations []string) []string {
continue continue
} }
// 只有在 logger.go, extra.go 等核心实现文件中的帧才被认为是 "inLogger" // 只有在 logger.go, extra.go 等核心实现文件中的帧才被认为是 "inLogger"
// 兼容本地路径 (.../log/file.go) 和 module 路径 (.../log@v1.5.6/file.go) // 这样可以保留测试文件 (xxx_test.go) 的调用栈
isLogInternal := isLogPkgFile(file, "logger.go") || isLogInternal := (strings.Contains(file, "/log/logger.go") ||
isLogPkgFile(file, "utility.go") || strings.Contains(file, "/log/utility.go") ||
isLogPkgFile(file, "standard.go") || strings.Contains(file, "/log/standard.go") ||
isLogPkgFile(file, "default_logger.go") || strings.Contains(file, "/log/default_logger.go") ||
isLogPkgFile(file, "extra.go") strings.Contains(file, "/log/extra.go"))
if isLogInternal { if isLogInternal {
if inLogger { if inLogger {