应使用 iris.withlogger() 注入自定义 *zerolog.logger 实例,如通过 lumberjack 实现文件写入与轮转;需在 iris.new() 后立即设置,避免中间件缓存旧输出。

如何用 iris.Logger() 替换默认日志器
Iris 默认使用 zerolog,但不直接暴露完整配置入口。想自定义格式或输出目标,不能只调用 app.Logger().SetLevel() —— 那只是改级别,底层 logger 实例仍绑定在内存中。必须在 iris.New() 后、app.Run() 前,用 app.Logger().SetOutput() 或完整替换整个 logger 实例。
推荐做法是创建一个带文件写入的 zerolog.Logger,再通过 iris.WithLogger() 注入:
import (
"os"
"github.com/iris-contrib/middleware/zap"
"github.com/rs/zerolog"
)
file, _ := os.OpenFile("app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
logger := zerolog.New(file).With().Timestamp().Logger()
app := iris.New(iris.WithLogger(&logger))
注意:&logger 必须取地址,因为 iris.WithLogger 接收的是 *zerolog.Logger 类型。
为什么 app.Logger().SetOutput() 有时不生效
常见错误是调用顺序不对:如果在 app.Use(...) 或路由注册之后才调用 SetOutput(),部分中间件(比如 iris.Logger() 自带的请求日志)可能已初始化并缓存了旧输出目标,导致新设置被忽略。
- 必须在
app := iris.New(...)之后立即设置,最好紧接在iris.WithLogger之后 - 避免在中间件里动态修改 logger 输出,Iris 不保证并发安全
- 如果用了
iris.Logger()中间件(非全局 logger),它会绕过 app 级 logger,需单独配置其输出
记录 HTTP 请求日志到文件的正确姿势
Iris 的 iris.Logger() 中间件默认只打屏,不写文件。要让它也进文件,不能只改 app.Logger(),而要给中间件传一个独立的 zerolog.Logger 实例:
reqLogger := zerolog.New(file).With().Str("component", "http").Logger()
app.Use(iris.Logger(&reqLogger))
关键点:
- 这个
reqLogger和 app 主 logger 可以是同一个文件句柄,但必须是不同 logger 实例(否则字段冲突) - 不要复用
app.Logger()返回的 logger 传给iris.Logger(),会导致 panic:Iris 检测到 logger 已被 app 占用 - 若需结构化请求日志(如 status、latency、path),建议用
iris.Traffic() + 自定义中间件,比硬塞字段更可控
Windows 下文件日志权限与滚动问题
直接用 os.OpenFile 写日志,在 Windows 上容易遇到“文件正由另一进程使用”错误,尤其配合 logrotate 或多实例部署时。
- 避免用
os.O_TRUNC,改用os.O_APPEND保证追加安全 - Iris 自身不提供日志轮转,需引入
gopkg.in/natefinch/lumberjack.v2封装 writer:
import "gopkg.in/natefinch/lumberjack.v2"
lumberjack := &lumberjack.Logger{
Filename: "app.log",
MaxSize: 10, // MB
MaxBackups: 3,
MaxAge: 7, // days
}
logger := zerolog.New(lumberjack).With().Timestamp().Logger()
app := iris.New(iris.WithLogger(&logger))
lumberjack 是线程安全的,且能自动处理 Windows 文件锁,比裸写 file 更稳妥。不过要注意:每次 rotate 后,lumberjack.Logger 内部会新建文件句柄,原 logger 实例无需重置 —— 这点和普通 os.File 不同。











