iris.Logger() 返回的是轻量封装的 zerolog.Logger 实例,仅默认输出到 os.Stdout、无时间戳和调用位置,专用于框架启动/错误日志,不可直接作为业务通用日志器使用。

iris.Logger() 返回的是什么,能直接用吗
不能直接当通用日志器用。iris.Logger() 返回的是 zerolog.Logger 实例,但它是 Iris 内部封装过的、只写入标准输出(os.Stdout)且默认不带时间戳和调用位置的轻量版。它主要用于框架自身启动/错误日志,比如 app.Run() 的监听提示,不适合业务逻辑打点。
如果你在 handler 里写 iris.Logger().Info().Msg("user login"),确实能输出,但字段固定、不可定制,也难对接 ELK 或文件轮转。
- 它没有自动添加
request_id、path、status等 HTTP 上下文信息 - 不支持按 level 分文件(如 error.log / access.log 分离)
- 零配置下无法输出到文件,
SetOutput需手动接管底层io.Writer
如何接入 zerolog 并注入请求上下文
Iris 原生推荐并内置了 zerolog,所以最佳实践是复用它,但自己初始化一个带中间件注入能力的实例。关键在于:用 context.Context 携带日志对象,而非全局单例。
示例做法:
// 初始化一个带 caller 和 time 的 zerolog
logger := zerolog.New(os.Stdout).With().
Timestamp().
Caller().
Logger()
// 注入到每个请求的 context
app.Use(func(ctx iris.Context) {
// 把 logger 带上 request ID 和 path
reqID := uuid.NewString()
l := logger.With().
Str("req_id", reqID).
Str("path", ctx.Request().URL.Path).
Str("method", ctx.Request().Method).
Logger()
ctx.SetUserValue("logger", &l)
ctx.Next()
})
- 不要用
ctx.Values().Set(),它不是线程安全的;SetUserValue是 safe 的 - 避免在 middleware 外提前调用
logger.With(),否则所有请求共享同一字段缓存 - 如果要输出 JSON 到文件,把
os.Stdout换成os.File,并加zerolog.TimeFieldFormat = zerolog.TimeFormatUnix避免时区问题
怎么记录 HTTP 访问日志(access log)
Iris 没有开箱即用的 access log 中间件,但可以用 iris.Logger().Info() + 自定义 handler 模拟,更推荐用 zerolog 手动构造结构化日志。
典型 access 日志字段应包括:status、latency、bytes、user_agent、remote_ip。注意:Iris 的 ctx.GetStatusCode() 在 handler 执行完才可读,所以必须用 ctx.OnResponse 钩子。
app.Use(func(ctx iris.Context) {
start := time.Now()
ctx.OnResponse(func() {
status := ctx.GetStatusCode()
latency := time.Since(start).Microseconds()
logger.Info().
Int("status", status).
Int64("latency_us", latency).
Int("bytes", ctx.GetResponseBodyLen()).
Str("ip", ctx.RemoteAddr()).
Str("ua", ctx.GetHeader("User-Agent")).
Msg("http_access")
})
ctx.Next()
})
-
ctx.GetResponseBodyLen()只在响应已写入 buffer 后有效;若用了流式响应(如 SSE),该值可能为 0 - 别在
OnResponse里调用ctx.StatusCode(),它返回的是初始值,不是最终状态码 - 如果启用了 gzip,
bytes是压缩后大小,不是原始 body 长度
error log 怎么区分框架错误和业务错误
Iris 默认把 panic 和未捕获错误打到 iris.Logger(),但业务层抛出的 iris.ErrNotFound 或自定义 error 不会自动记录。你需要显式处理。
两种常用方式:
- 统一错误中间件:拦截
ctx.Next()后的ctx.GetErr(),对非nil错误调用logger.Error().Err(err).Msg("handler_error") - 业务 handler 内主动记录:比如数据库查询失败时,用
logger.Error().Err(err).Str("sql", query).Msg("db_query_failed")
重点:不要把 err.Error() 当字符串拼进日志字段,zerolog 的 .Err() 方法会自动展开堆栈(需启用 zerolog.ErrorStackMarshaler);否则你看到的只是 “failed to insert”,没有文件行号。
另外,iris.Application.SetErrors 设置的错误处理器只影响 ctx.StatusCode() 和模板渲染,不触发日志 —— 它和日志是正交的两件事。











