Compare commits
2 Commits
438a424d94
...
eff999f6f2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eff999f6f2 | ||
|
|
ac6efeb1a9 |
@ -1,5 +1,14 @@
|
||||
# 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
|
||||
- **规范化: Warning 日志行为对齐**:
|
||||
- ** Convention 对齐**: 移除了 `Warning` 级别日志自动附带堆栈信息(`CallStacks`)的逻辑。
|
||||
|
||||
18
go.mod
18
go.mod
@ -3,19 +3,19 @@ module apigo.cc/go/log
|
||||
go 1.25.0
|
||||
|
||||
require (
|
||||
apigo.cc/go/cast v1.5.0
|
||||
apigo.cc/go/config v1.5.0
|
||||
apigo.cc/go/file v1.5.0
|
||||
apigo.cc/go/id v1.5.0
|
||||
apigo.cc/go/shell v1.5.0
|
||||
apigo.cc/go/cast v1.5.2
|
||||
apigo.cc/go/config v1.5.2
|
||||
apigo.cc/go/file v1.5.4
|
||||
apigo.cc/go/id v1.5.3
|
||||
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 (
|
||||
apigo.cc/go/encoding v1.5.0 // indirect
|
||||
apigo.cc/go/rand v1.5.0 // indirect
|
||||
apigo.cc/go/safe v1.5.0 // indirect
|
||||
apigo.cc/go/encoding v1.5.3 // indirect
|
||||
apigo.cc/go/rand v1.5.2 // indirect
|
||||
apigo.cc/go/safe v1.5.1 // indirect
|
||||
golang.org/x/crypto v0.51.0 // indirect
|
||||
golang.org/x/sys v0.44.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
|
||||
@ -282,6 +282,13 @@ func (logger *Logger) Error(message string, extra ...any) {
|
||||
logger.FillError(entry, message)
|
||||
if len(extra) > 0 {
|
||||
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)
|
||||
}
|
||||
|
||||
21
utility.go
21
utility.go
@ -52,6 +52,15 @@ func fixField(s string) string {
|
||||
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 获取调用栈
|
||||
func getCallStacks(truncations []string) []string {
|
||||
callStacks := make([]string, 0)
|
||||
@ -65,12 +74,12 @@ func getCallStacks(truncations []string) []string {
|
||||
continue
|
||||
}
|
||||
// 只有在 logger.go, extra.go 等核心实现文件中的帧才被认为是 "inLogger"
|
||||
// 这样可以保留测试文件 (xxx_test.go) 的调用栈
|
||||
isLogInternal := (strings.Contains(file, "/log/logger.go") ||
|
||||
strings.Contains(file, "/log/utility.go") ||
|
||||
strings.Contains(file, "/log/standard.go") ||
|
||||
strings.Contains(file, "/log/default_logger.go") ||
|
||||
strings.Contains(file, "/log/extra.go"))
|
||||
// 兼容本地路径 (.../log/file.go) 和 module 路径 (.../log@v1.5.6/file.go)
|
||||
isLogInternal := isLogPkgFile(file, "logger.go") ||
|
||||
isLogPkgFile(file, "utility.go") ||
|
||||
isLogPkgFile(file, "standard.go") ||
|
||||
isLogPkgFile(file, "default_logger.go") ||
|
||||
isLogPkgFile(file, "extra.go")
|
||||
|
||||
if isLogInternal {
|
||||
if inLogger {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user