Gin 无内置日志级别,需用 logrus 或 zap 实现多级日志;logrus 支持按级别分流输出,zap 性能更高且原生结构化;仅靠 Gin 内置 Logger 无法真正分级,仅能 hack 过滤。

Gin 本身没有内置的日志级别(debug/info/warn/error),所谓“多级别输出”必须靠自定义中间件或集成第三方日志库实现;直接调用 gin.Logger() 或 gin.Default() 只能输出统一格式的访问日志,无法按级别过滤或分流。
用 logrus 实现真正的多级别日志输出
logrus 是最常用且稳定的选择,它原生支持 Debugf/Infof/Warnf/Errorf 等方法,并可分别配置输出目标与格式。
- 安装:
go get github.com/sirupsen/logrus - 初始化时设置不同输出目标:比如
logrus.Debug写入 debug.log,logrus.Error单独写入 error.log - 关键点:不要把 logrus 实例塞进
gin.DefaultWriter——那是给 Gin 内置 Logger 用的,和 logrus 无关;应把 logrus 作为独立日志工具,在 handler 中显式调用 - 示例片段:
logger := logrus.New() logger.SetLevel(logrus.DebugLevel) file, _ := os.OpenFile("debug.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) logger.SetOutput(file)然后在路由中:c *gin.Context里写logger.Debugf("req from %s", c.ClientIP())
用 zap 替代 logrus 获取更高性能与结构化能力
zap 在高并发场景下比 logrus 更轻量,且默认输出 JSON,天然适配 ELK、Loki 等日志系统;但它的 API 更严格,不支持运行时动态改 level(需启动时确定)。
- 安装:
go get go.uber.org/zap - 推荐使用
zap.NewProduction()(带时间戳、level、caller)或zap.NewDevelopment()(带颜色、行号,仅限开发) - 若需多文件按 level 拆分(如 info.log / error.log),得配合
lumberjack.Logger+ 自定义WriteSyncer实现,不能只靠zap.Config - 注意:
zap.Sugar()接口虽方便,但会丢失结构字段;生产环境建议用zap.Logger原生接口传 field
绕过第三方、仅用 Gin 内置 Logger 模拟“级别”行为
这属于 hack 方式,仅适用于简单场景,比如只区分“慢请求”和“错误响应”,不推荐用于真实多级别需求。
立即学习“go语言免费学习笔记(深入)”;
- 利用
gin.LoggerWithConfig的Skip函数做粗粒度过滤:Skip: func(c *gin.Context) bool { return c.Writer.Status() < 400 // 只记录 4xx/5xx } - 或结合
Formatter输出不同前缀:"[ERROR] "/"[WARN] ",但本质仍是单一流,无法单独关闭某一级别 - 致命限制:无法拦截
panic后的 Recovery 日志——它走的是另一套路径,必须用gin.RecoveryWithWriter单独配置 - 权限与路径问题常被忽略:如果
os.OpenFile打开日志文件失败,Gin 不报错也不提示,日志会静默丢失
真正需要多级别,就别试图魔改 gin.Logger;logrus 或 zap 是事实标准,而 Gin 的角色只是 HTTP 路由器——它的日志中间件只负责请求链路快照,不该承担应用层日志分级职责。


















