Files
go-omni/logx/README.md

63 lines
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# logx
业务通过 `logx` 记录结构化日志,独立于 HTTP、队列和具体业务字段。普通 `context.Context` 继续由业务管理;框架不会约定或自动注入 userId、tenantId。
```go
logx.InfoContext(ctx, "order.created", "orderId", orderID)
logx.ErrorContext(ctx, "order.failed", "error", err)
// 可选:附上本次记录位置的当前 goroutine 堆栈。
logx.ErrorStackContext(ctx, "unexpected.failure", "error", err)
// 固定字段可使用子日志对象,无需重复传入。
logger := logx.With("component", "invoice")
logger.InfoContext(ctx, "invoice.saved", "invoiceId", invoiceID)
```
`Debug/Info/Warn/Error` 有包级和实例方法,也有带 Context 的方法。`requestId` 自动跟随 HTTP Context;接入 telemetry 后可带 `traceId`。不要在 Service 中改用 `context.Background()`,否则会丢失取消信号和关联字段。
## 文件轮转
```go
closeLog, err := logx.Setup(logx.Config{
Service: "billing-api", Environment: "production",
Level: "info", Format: "json", File: "./var/log/billing-api.log",
Rotation: logx.RotationConfig{
Enabled: true, MaxSizeMB: 100, MaxBackups: 10,
MaxAgeDays: 7, Compress: true,
},
RedactKeys: []string{"bankAccount", "identityNumber"},
})
if err != nil { return err }
defer closeLog()
```
`omni.WithLogConfig(...)` 只保存日志配置,`omni.New()` 不会因此创建或关闭 Logger。手写入口需要像上例一样调用 `logx.Setup` 并负责关闭,或使用 `logx.New`、`logx.SetDefault` 和 `app.OnShutdown(logger.Close)` 显式装配。生成的 API 项目已在入口完成这些步骤。子日志共用输出、级别和关闭状态;独立 `logx.New` 返回的实例由创建者负责关闭。
轮转显式开启;三个数值为 0 时分别取 100 MiB、10 份、7 天。超过大小后轮转,旧文件按份数/年龄清理,可 gzip 压缩;保留天数不表示每天定时切割。压缩和历史清理由底层异步执行,不承诺 Close 等待压缩完成。轮转使用 [lumberjack v2](https://github.com/natefinch/lumberjack/tree/v2.2.1),**一个日志文件只能由一个进程拥有**。容器通常直接用 stdout/stderr,让运行平台管理日志文件。
`rotation.enabled` 与自定义 Writer 不能同时使用;只设轮转但未提供 File 会报错。开启轮转时会创建父目录,并在初始化阶段检查文件可打开。自定义 Writer 的并发和生命周期由接入方负责。普通文件输出仍然是追加写入;未开启轮转不自动清理。
## 结构化脱敏
默认匹配 password、passwd、secret、clientSecret、token、accessToken、refreshToken、authorization、cookie、setCookie、apiKey、privateKey、signedUrl。匹配忽略大小写、下划线和连字符;`RedactKeys` 追加业务自行定义的键,不替换默认列表。
覆盖普通属性、With 属性、slog Group/LogValuer、嵌套字符串键 map、切片和导出 struct 字段。敏感值变为 `[REDACTED]`,不修改调用者的数据;循环/过深结构截断。嵌套字节数组隐藏为 `[BINARY]`,非字符串键 map 隐藏为 `[UNSUPPORTED MAP]`,不调用对象自定义 JSON 序列化方法。
**脱敏按字段名处理,不解析自由文本。** 把密码拼进 msg/error/URL 字符串,或使用不在列表中的字段名,仍可能泄露。签名链接、完整请求体和认证头不应写入日志。业务隐私字段自行放进 `RedactKeys`;日志中不会自动添加身份/租户约定。
## HTTP 异常与慢请求
```go
application := omni.New(
omni.WithLogger(true),
omni.WithSlowRequestThreshold(500*time.Millisecond),
)
```
`WithSlowRequestThreshold` 同时开启访问日志,0 禁用慢请求识别。也可以在 JSON/YAML 中配 `enableLogger: true`、`slowRequestThreshold: "500ms"`,或使用 `GO_OMNI_SLOW_REQUEST_THRESHOLD` 配合 `GO_OMNI_ENABLE_LOGGER=true`。
每个请求记录一条 `http.request`:方法、路径、匹配路由、实际状态码、耗时、客户端 IP 和关联字段。正常请求 INFO,超过阈值 WARN(`slow: true`),5xx ERROR;返回的 error 会记录到结构化字段。计时覆盖 Handler 调用,不包含框架之外的代理排队,也不自动计入 Handler 返回后继续写入的自管流。
Recovery 自动记录单独的 ERROR `http.panic` 和当前堆栈,再走原有统一错误响应;如果响应已提交,不改写已发送状态。客户端不会收到日志堆栈。普通业务 error 默认不抓堆栈,需要时显式使用 `ErrorStackContext`,它记录调用位置,不回溯 error 最初创建位置。
运行时可通过 `logger.SetLevel("debug")` 调整级别;文件轮转和脱敏配置属于静态设置,变更后重建实例/重启。当前不包含日志采样、异步缓冲、日志平台导出或慢 SQL 记录。