Go-Zero 日志使用指南

一、日志基础使用

1.1 日志输出方法

go 复制代码
import "github.com/zeromicro/go-zero/core/logx"

// 普通日志
logx.Info("普通信息日志")
logx.Infof("格式化信息: %s", "内容")
logx.Infow("结构化日志", logx.Field("key", "value"))

// 错误日志
logx.Error("错误日志")
logx.Errorf("错误: %v", err)
logx.Errorw("结构化错误", logx.Field("error", err))

// 调试日志(需要开启 Debug 模式)
logx.Debug("调试日志")
logx.Debugf("调试: %s", "内容")

// 慢日志
logx.Slow("慢操作日志")
logx.Slowf("慢操作: %dms", 1000)
logx.Sloww("结构化慢日志", logx.Field("duration", "1s"))

// 统计日志
logx.Stat("统计信息")
logx.Statf("统计: %s", "内容")

// 严重错误日志
logx.Severe("严重错误")
logx.Severef("严重错误: %v", err)

1.2 带 Context 的日志

go 复制代码
// 推荐使用,可以追踪链路
logx.WithContext(ctx).Info("带上下文的日志")
logx.WithContext(ctx).Infow("结构化日志", logx.Field("user", "张三"))
logx.WithContext(ctx).Error("带上下文的错误日志")

二、日志配置

2.1 配置文件示例(yaml)

yaml 复制代码
Name: user-api
Host: 0.0.0.0
Port: 8888

Log:
  # 日志模式:console(控制台)、file(文件)、volume(容器卷)
  Mode: file
  
  # 日志级别:debug、info、error、severe
  Level: info
  
  # 编码格式:json 或 plain
  Encoding: json
  
  # 文件日志配置
  Path: logs                    # 日志文件存放目录
  MaxSize: 100                  # 单个日志文件最大大小(MB)
  MaxBackups: 5                 # 保留的旧日志文件最大数量
  MaxAge: 30                    # 保留旧日志文件的最大天数
  Compress: true                # 是否压缩旧日志文件
  
  # 日志打印调用位置
  KeepDays: 7                   # 日志保留天数
  
  # 是否记录调用堆栈
  StackCooldownMillis: 100      # 堆栈冷却时间(毫秒)

2.2 配置项详细说明

配置项 类型 默认值 说明
Mode string console console-控制台输出,file-文件输出,volume-容器卷
Level string info debug、info、error、severe,级别越低输出越详细
Encoding string json json-JSON格式,plain-纯文本格式
Path string logs 日志文件存放路径(相对或绝对路径)
MaxSize int 100 单个日志文件最大大小(MB)
MaxBackups int 5 保留的旧日志文件最大数量
MaxAge int 30 保留旧日志文件的最大天数
Compress bool false 是否压缩归档的日志文件
KeepDays int 7 日志保留天数(优先级高于MaxAge)
StackCooldownMillis int 100 堆栈冷却时间,避免频繁打印堆栈

2.3 不同环境的日志配置建议

开发环境

yaml 复制代码
Log:
  Mode: console       # 控制台输出,方便查看
  Level: debug        # 详细日志,便于调试
  Encoding: plain     # 纯文本,易读

测试环境

yaml 复制代码
Log:
  Mode: file          # 文件输出,方便问题追溯
  Level: info         # 标准日志级别
  Encoding: json      # JSON格式,便于日志分析
  Path: logs
  KeepDays: 3

生产环境

yaml 复制代码
Log:
  Mode: file          # 文件输出
  Level: info         # 只记录重要日志(或 error)
  Encoding: json      # JSON格式,便于日志收集系统解析
  Path: /var/log/app  # 绝对路径
  MaxSize: 500        # 大容量
  MaxBackups: 10
  MaxAge: 30
  Compress: true      # 压缩节省空间
  KeepDays: 30

三、配置与不配置 Log 的区别

3.1 不配置 Log(使用默认配置)

yaml 复制代码
# 配置文件中不写 Log 配置项
Name: user-api
Host: 0.0.0.0
Port: 8888

默认行为:

  • Mode: console - 日志输出到控制台
  • Level: info - 只输出 info 及以上级别的日志
  • Encoding: json - JSON 格式输出
  • 不会生成日志文件
  • 日志只在控制台显示,重启后丢失

3.2 配置 Log

yaml 复制代码
Name: user-api
Host: 0.0.0.0
Port: 8888
Log:
  Mode: file
  Level: info
  Path: logs

行为:

  • 日志输出到文件
  • 日志持久化保存
  • 可以配置日志轮转、压缩等
  • 可以通过日志收集系统统一管理

3.3 最佳实践

go 复制代码
// 在 main.go 中根据环境动态配置
var c config.Config
conf.MustLoad(*configFile, &c)

// 如果配置文件没有 Log 配置,可以代码中设置
if c.Log.Mode == "" {
    logx.MustSetup(logx.LogConf{
        Mode:     "file",
        Level:    "info",
        Encoding: "json",
        Path:     "logs",
    })
}

四、日志收集场景与位置

4.1 自动日志收集场景

1. HTTP 中间件自动收集

go 复制代码
// rest.Server 自动记录的日志
// 位置:rest/handler/loghandler.go

✅ 请求开始时间
✅ 请求方法和路径
✅ 请求耗时
✅ HTTP状态码
✅ 请求体大小
✅ 错误信息(如果有)

// 日志示例
{
  "@timestamp": "2025-12-29T10:30:00.123Z",
  "level": "info",
  "content": "GET /api/users/1",
  "duration": "15.2ms",
  "code": 200
}

2. RPC 中间件自动收集

go 复制代码
// zrpc.Server 自动记录的日志
// 位置:zrpc/internal/serverinterceptors/statinterceptor.go

✅ RPC方法名
✅ 调用耗时
✅ 错误信息
✅ 调用参数(可选)

3. 数据库操作日志

go 复制代码
// sqlx 自动记录慢查询
// 慢查询阈值:默认 500ms

✅ SQL语句
✅ 执行耗时
✅ 受影响行数

4. 缓存操作日志

go 复制代码
// redis/cache 自动记录慢操作
// 慢操作阈值:可配置

✅ Redis命令
✅ 执行耗时
✅ 缓存键

4.2 手动日志收集场景

go 复制代码
// 业务逻辑层
func (l *UserLogic) GetUser(req *types.GetUserReq) (*types.User, error) {
    // 关键业务操作记录
    logx.WithContext(l.ctx).Infow("开始获取用户信息",
        logx.Field("userId", req.UserId))
    
    user, err := l.svcCtx.UserModel.FindOne(l.ctx, req.UserId)
    if err != nil {
        // 错误日志
        logx.WithContext(l.ctx).Errorw("获取用户失败",
            logx.Field("userId", req.UserId),
            logx.Field("error", err.Error()))
        return nil, err
    }
    
    // 成功日志
    logx.WithContext(l.ctx).Infow("用户信息获取成功",
        logx.Field("userId", req.UserId),
        logx.Field("userName", user.Name))
    
    return &types.User{
        Id:   user.Id,
        Name: user.Name,
    }, nil
}

4.3 日志收集最佳实践

go 复制代码
// ✅ 推荐:关键业务节点记录
- 用户登录/登出
- 订单创建/支付
- 重要数据的增删改
- 外部API调用
- 异常错误

// ❌ 不推荐:过度日志
- 循环内的日志
- 高频调用的接口日志
- 敏感信息(密码、token等)

五、日志文件存储规则

5.1 日志文件命名规则

lua 复制代码
logs/
├── access.log          # 当前访问日志
├── error.log           # 当前错误日志
├── severe.log          # 当前严重错误日志
├── slow.log            # 当前慢日志
├── stat.log            # 当前统计日志
├── access.log.2025122901  # 归档的访问日志
├── access.log.2025122902
└── error.log.2025122901   # 归档的错误日志

5.2 日志分类存储

日志类型 文件名 触发条件 用途
access.log 访问日志 Info、Infof、Infow 记录正常业务流程
error.log 错误日志 Error、Errorf、Errorw 记录业务错误
severe.log 严重错误 Severe、Severef、Severew 记录系统级严重错误
slow.log 慢日志 Slow、Slowf、Sloww 记录耗时操作
stat.log 统计日志 Stat、Statf、Statw 记录统计信息

5.3 什么时候会存文件

存文件条件:

  1. Log.Mode = "file""volume"
  2. 配置了 Log.Path

不存文件条件:

  1. Log.Mode = "console" - 只输出到控制台
  2. 不配置 Log - 默认 console 模式
yaml 复制代码
# ✅ 会存文件
Log:
  Mode: file
  Path: logs

# ✅ 会存文件(容器环境)
Log:
  Mode: volume
  Path: /var/log/app

# ❌ 不会存文件
Log:
  Mode: console

# ❌ 不会存文件(默认配置)
# 不配置 Log

5.4 日志轮转机制

yaml 复制代码
Log:
  Path: logs
  MaxSize: 100        # 单文件 100MB 后轮转
  MaxBackups: 5       # 最多保留 5 个备份
  MaxAge: 30          # 保留 30 天
  KeepDays: 7         # 优先级更高,保留 7 天
  Compress: true      # 压缩旧文件为 .gz

轮转触发条件(满足任一):

  • 文件大小超过 MaxSize
  • 文件创建时间超过 KeepDays
  • 达到每日午夜(自动轮转)

六、日志查看与问题排查

6.1 查看日志的方式

方式一:tail 实时查看

bash 复制代码
# 实时查看所有日志
tail -f logs/access.log

# 实时查看错误日志
tail -f logs/error.log

# 同时查看多个日志
tail -f logs/access.log logs/error.log

方式二:grep 过滤查看

bash 复制代码
# 查找特定用户的日志
grep "userId\":\"123" logs/access.log

# 查找错误日志
grep "error" logs/access.log

# 查找特定时间段的日志
grep "2025-12-29T10:" logs/access.log

# 查找并显示上下文
grep -C 5 "error" logs/access.log  # 显示前后5行

方式三:less 分页查看

bash 复制代码
# 分页查看日志
less logs/access.log

# 在 less 中搜索:按 / 然后输入关键词
# 下一个:n
# 上一个:N

方式四:cat 配合工具

bash 复制代码
# 查看最近100行
tail -n 100 logs/access.log

# 查看前100行
head -n 100 logs/access.log

# JSON格式美化
cat logs/access.log | jq '.'

6.2 通过 trace_id 追踪请求链路

bash 复制代码
# 提取 trace_id 追踪整个请求链路
grep "trace:abc123" logs/*.log

# 输出示例:
# logs/access.log:{"@timestamp":"...","trace":"abc123","content":"GET /api/users"}
# logs/access.log:{"@timestamp":"...","trace":"abc123","content":"query user from db"}
# logs/error.log:{"@timestamp":"...","trace":"abc123","content":"user not found"}

6.3 性能问题排查

慢查询排查

bash 复制代码
# 查看慢日志
cat logs/slow.log

# 查找超过1秒的操作
grep "duration\":\"[0-9]\+s" logs/slow.log

# 统计最慢的10个操作
cat logs/slow.log | jq '.duration' | sort | tail -10

高频错误排查

bash 复制代码
# 统计错误类型
cat logs/error.log | jq '.error' | sort | uniq -c | sort -rn

# 查找特定错误
grep "connection timeout" logs/error.log

6.4 典型问题排查流程

问题1:接口响应慢

bash 复制代码
# 1. 查看 slow.log
tail -f logs/slow.log

# 2. 找到慢请求的 trace_id
grep "duration\":\"[0-9]\+s" logs/slow.log

# 3. 根据 trace_id 追踪完整链路
grep "trace:abc123" logs/*.log

# 4. 分析瓶颈:数据库?外部API?

问题2:接口返回 500 错误

bash 复制代码
# 1. 查看 error.log
tail -f logs/error.log

# 2. 找到错误信息和堆栈
grep -A 10 "500" logs/error.log

# 3. 根据时间和路径定位代码
# 4. 查看相关业务日志

问题3:找不到某个请求的日志

bash 复制代码
# 可能原因:
# 1. 日志级别太高(设置为 error,但请求是 info)
# 2. 日志已被轮转或删除
# 3. 时间不对(注意时区)

# 解决:
# 1. 检查 Log.Level 配置
# 2. 查看归档日志 access.log.2025122901
# 3. 检查服务器时区设置

七、日志使用建议

7.1 什么时候开启日志

场景 是否开启 建议配置
开发环境 ✅ 必须 Mode: console, Level: debug
测试环境 ✅ 必须 Mode: file, Level: info
预发环境 ✅ 必须 Mode: file, Level: info
生产环境 ✅ 必须 Mode: file, Level: info/error
性能测试 ⚠️ 可选 Mode: file, Level: error(减少IO)
压力测试 ⚠️ 可选 Level: error(减少日志量)

结论:建议一直开启日志,根据环境调整级别和输出方式。

7.2 日志级别选择

go 复制代码
// debug - 开发调试(生产不建议)
logx.Debug("调试信息:变量值为 xxx")

// info - 正常业务流程(推荐)
logx.Info("用户登录成功")

// error - 业务错误(必须)
logx.Error("获取用户信息失败")

// severe - 严重系统错误(必须)
logx.Severe("数据库连接失败")

7.3 日志性能优化

go 复制代码
// ❌ 不推荐:高频日志
for i := 0; i < 10000; i++ {
    logx.Info("处理中:", i)  // 会产生大量日志
}

// ✅ 推荐:批量记录
logx.Infof("批量处理完成,共处理 %d 条", 10000)

// ❌ 不推荐:复杂对象序列化
logx.Infow("用户信息", logx.Field("user", largeUserObject))

// ✅ 推荐:只记录关键字段
logx.Infow("用户信息", 
    logx.Field("userId", user.Id),
    logx.Field("userName", user.Name))

7.4 敏感信息处理

go 复制代码
// ❌ 危险:记录敏感信息
logx.Infow("用户登录", 
    logx.Field("password", password))  // 不要记录密码
logx.Infow("支付", 
    logx.Field("cardNo", cardNo))      // 不要记录完整卡号

// ✅ 安全:脱敏处理
logx.Infow("用户登录", 
    logx.Field("userId", userId))
logx.Infow("支付", 
    logx.Field("cardNo", maskCard(cardNo)))  // 如:**** **** **** 1234

八、常用日志工具

8.1 日志分析工具

ELK Stack(推荐生产环境)

yaml 复制代码
# Filebeat 配置示例
filebeat.inputs:
- type: log
  enabled: true
  paths:
    - /var/log/app/*.log
  json.keys_under_root: true
  json.add_error_key: true

output.elasticsearch:
  hosts: ["localhost:9200"]

Loki(轻量级推荐)

yaml 复制代码
# Promtail 配置示例
clients:
  - url: http://loki:3100/loki/api/v1/push

scrape_configs:
  - job_name: app
    static_configs:
      - targets:
          - localhost
        labels:
          __path__: /var/log/app/*.log

8.2 日志查看命令速查

bash 复制代码
# 实时查看
tail -f logs/access.log

# 查看最近100行
tail -n 100 logs/access.log

# 搜索关键词
grep "error" logs/*.log

# 搜索并高亮显示
grep --color "error" logs/access.log

# 统计日志行数
wc -l logs/access.log

# 按时间范围筛选
sed -n '/2025-12-29 10:00/,/2025-12-29 11:00/p' logs/access.log

# JSON 日志美化
cat logs/access.log | jq '.'

# 统计错误类型
cat logs/error.log | jq '.error' | sort | uniq -c

# 找出最慢的10个请求
cat logs/slow.log | jq '.duration' | sort -rn | head -10

九、完整配置示例

9.1 API 服务配置

yaml 复制代码
# api/etc/user.yaml
Name: user-api
Host: 0.0.0.0
Port: 8888

# 生产环境日志配置
Log:
  Mode: file
  Level: info
  Encoding: json
  Path: logs
  MaxSize: 500
  MaxBackups: 10
  MaxAge: 30
  Compress: true
  KeepDays: 30
  StackCooldownMillis: 100

# Telemetry 配置(链路追踪)
Telemetry:
  Name: user-api
  Endpoint: http://jaeger:14268/api/traces
  Sampler: 1.0
  Batcher: jaeger

9.2 RPC 服务配置

yaml 复制代码
# rpc/etc/user.yaml
Name: user-rpc
ListenOn: 0.0.0.0:8080

Log:
  Mode: file
  Level: info
  Encoding: json
  Path: logs
  KeepDays: 30

# RPC 超时配置
Timeout: 30000  # 30秒

# RPC 日志配置
RpcLog:
  Stat: true       # 开启统计日志
  Slow: true       # 开启慢日志

9.3 Docker 环境配置

yaml 复制代码
# docker-compose.yaml 中的日志配置
services:
  user-api:
    image: user-api:latest
    volumes:
      - ./logs:/app/logs  # 挂载日志目录
    environment:
      - LOG_MODE=file
      - LOG_LEVEL=info

十、总结与检查清单

✅ 日志配置检查清单

  • 是否配置了 Log.Mode(开发用console,生产用file)
  • 是否配置了合适的 Log.Level(开发用debug,生产用info)
  • 是否配置了 Log.Path(生产环境)
  • 是否配置了日志轮转(MaxSize、MaxBackups、KeepDays)
  • 是否开启了日志压缩(Compress: true)
  • 是否配置了链路追踪(Telemetry)

✅ 日志使用检查清单

  • 关键业务操作是否有日志记录
  • 错误处理是否记录了详细错误信息
  • 日志是否使用了 WithContext 以便链路追踪
  • 日志是否包含了足够的上下文信息
  • 是否避免了记录敏感信息
  • 高频操作是否控制了日志数量
  • 是否使用了结构化日志(Infow、Errorw)

✅ 问题排查检查清单

  • 是否能通过 trace_id 追踪完整请求链路
  • 是否能快速定位错误日志
  • 是否能分析慢查询和性能瓶颈
  • 是否配置了日志收集系统(生产环境)
  • 是否定期清理旧日志文件
  • 是否有日志监控告警(严重错误)

附录:常见问题

Q1: 日志文件太大怎么办?

  • 调整 MaxSize 和 KeepDays
  • 提高日志级别(info -> error)
  • 减少不必要的日志输出
  • 开启 Compress 压缩

Q2: 找不到某个请求的日志?

  • 检查日志级别配置
  • 确认日志是否被轮转
  • 检查时区是否正确
  • 确认该请求是否真的到达了服务

Q3: 日志乱码怎么办?

  • 确保使用 UTF-8 编码
  • 检查 Encoding 配置
  • 使用 cat -A 查看特殊字符

Q4: 如何在代码中动态修改日志级别?

go 复制代码
// 运行时修改日志级别(不推荐生产环境)
logx.SetLevel(logx.ErrorLevel)

Q5: 容器环境日志如何收集?

yaml 复制代码
# 使用 volume 模式
Log:
  Mode: volume
  Path: /var/log/app

# Docker 挂载
volumes:
  - ./logs:/var/log/app
相关推荐
研究司马懿1 小时前
【云原生】Gateway API高级功能
云原生·go·gateway·k8s·gateway api
梦想很大很大15 小时前
使用 Go + Gin + Fx 构建工程化后端服务模板(gin-app 实践)
前端·后端·go
lekami_兰20 小时前
MySQL 长事务:藏在业务里的性能 “隐形杀手”
数据库·mysql·go·长事务
却尘1 天前
一篇小白也能看懂的 Go 字符串拼接 & Builder & cap 全家桶
后端·go
ん贤1 天前
一次批量删除引发的死锁,最终我选择不加锁
数据库·安全·go·死锁
mtngt112 天前
AI DDD重构实践
go
Grassto3 天前
12 go.sum 是如何保证依赖安全的?校验机制源码解析
安全·golang·go·哈希算法·go module
Grassto5 天前
11 Go Module 缓存机制详解
开发语言·缓存·golang·go·go module
程序设计实验室6 天前
2025年的最后一天,分享我使用go语言开发的电子书转换工具网站
go
我的golang之路果然有问题6 天前
使用 Hugo + GitHub Pages + PaperMod 主题 + Obsidian 搭建开发博客
golang·go·github·博客·个人开发·个人博客·hugo