跳转到内容

结构化日志

Fox 提供请求日志中间件,以及基于 zerolog 的 logger 包。日志中间件会创建或复用 x-request-id,把请求日志器保存到 *fox.Context,并在处理器结束后输出一条请求日志。

r := fox.Default()
r.GET("/user/:id", func(ctx *fox.Context) (*User, error) {
log := ctx.Logger
id := ctx.Param("id")
log.WithField("user_id", id).Info("fetching user")
user, err := getUserByID(id)
if err != nil {
log.WithError(err).Error("failed to fetch user")
return nil, err
}
return user, nil
})

fox.Default() 会安装 fox.Logger()fox.NewXResponseTimer()fox.Recovery()。如果使用 fox.New(),需要显式添加中间件:

r := fox.New()
r.Use(fox.Logger())

Fox 使用 x-request-id 请求头作为 TraceID。如果请求没有携带该请求头,日志中间件会生成一个,并写回响应头。

r.GET("/trace", func(ctx *fox.Context) map[string]string {
return map[string]string{
"trace_id": ctx.TraceID(),
}
})

也可以从带有 TraceID 的 context 创建日志器:

log := logger.NewWithContext(ctx.Context)

在创建请求日志器之前,先配置全局 logger:

import "github.com/fox-gonic/fox/logger"
logger.SetConfig(&logger.Config{
LogLevel: logger.InfoLevel,
ConsoleLoggingEnabled: true,
EncodeLogsAsJSON: true,
})

Fox 可以通过 lumberjack 写入轮转日志文件:

logger.SetConfig(&logger.Config{
LogLevel: logger.InfoLevel,
ConsoleLoggingEnabled: false,
FileLoggingEnabled: true,
Filename: "./logs/app.log",
MaxSize: 100, // MB
MaxBackups: 7,
MaxAge: 30, // 天
EncodeLogsAsJSON: true,
})

如果开启文件日志但没有设置 Filename,Fox 会在临时目录中创建一个以进程名命名的日志文件。

使用 WithFieldWithFieldsWithError 添加上下文字段:

log := ctx.Logger.WithFields(map[string]any{
"user_id": req.UserID,
"action": "create_order",
})
order, err := createOrder(req)
if err != nil {
log.WithError(err).Error("order creation failed")
return nil, err
}
log.WithField("order_id", order.ID).Info("order created")

日志器也支持格式化消息:

ctx.Logger.Infof("created user %d", user.ID)

fox.Logger() 接收带 SkipPathsfox.LoggerConfig

r.Use(fox.Logger(fox.LoggerConfig{
SkipPaths: []string{"/health", "/metrics"},
}))

该中间件会记录 method、path、client IP、响应状态码、耗时,以及固定值为 ENGINEtype 字段。

github.com/fox-gonic/fox/logger 暴露这些级别:

  • logger.DebugLevel
  • logger.InfoLevel
  • logger.WarnLevel
  • logger.ErrorLevel
  • logger.FatalLevel
  • logger.PanicLevel
  1. 在 Fox 处理器中使用 ctx.Logger,让业务日志共享请求 TraceID。
  2. WithFieldWithFields 添加结构化字段,避免把值拼接到消息字符串中。
  3. 不要记录密码、令牌、密钥或敏感个人信息。
  4. 在应用启动时调用 logger.SetConfig,不要等到请求处理中再配置。
  5. 对健康检查、指标等高频端点使用 SkipPaths