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
相关推荐
王中阳Go5 小时前
别再卷 Python 了!Go + 字节 Eino 框架,才是后端人转 AI 的降维打击(附源码)
后端·面试·go
踏浪无痕6 小时前
夜莺告警引擎内核:一个优雅的设计
运维·后端·go
Chasing__Dreams6 小时前
Go--2--垃圾回收
go
昵称为空C7 小时前
go+gin 入门指南
go·gin
小信啊啊1 天前
Go语言映射(Map)
golang·go
Lupino1 天前
从 Haskell 到 Go:记一次 RSA 加密协议移植与“字节陷阱”排查实录
go·haskell
Grassto2 天前
从 GOPATH 到 Go Module:Go 依赖管理机制的演进
开发语言·后端·golang·go
钟智强2 天前
红队实战复盘:如何运用【火尖枪】高效突破复杂登录防线
服务器·安全·web安全·http·go·php·bruteforce
Grassto2 天前
Go Module 基础概念全解析:module、version、sum 是什么
golang·go·go module