在 Debian 上高效记录 Go 日志的实用技巧
一 选择日志库与输出格式
- 标准库 log:开箱即用,适合简单场景;可快速切到文件或 stdout。示例:
- 输出到文件并设置前缀:
- f, _ := os.OpenFile(“app.log”, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
- log.SetOutput(f); log.SetPrefix(“[APP]”)
- 结构化日志库:
- logrus:支持 JSON/文本、字段丰富,易于接入 ELK。
- logrus.SetFormatter(&logrus.JSONFormatter{})
- zap:Uber 开源,高性能,生产推荐;支持原子级别动态调整。
- logger := zap.NewProduction(); defer logger.Sync()
- zerolog:零分配 JSON,极致性能。
- zerolog.New(os.Stdout).With().Timestamp().Logger()
- 建议:开发环境用文本,生产环境优先 JSON;为所有日志统一 时间、级别、调用位置 等关键字段。
二 日志级别与上下文增强
- 合理设置级别:DEBUG/INFO/WARN/ERROR/FATAL;生产常用 INFO/ERROR,按需临时开启 DEBUG。
- logrus.SetLevel(logrus.InfoLevel)
- zap 可使用 AtomicLevel 动态降级/升级。
- 丰富上下文:在日志中携带 request_id、user_id、module、ip、func/file/line 等,便于追踪。
- 使用 logrus.WithFields 或 zap.With 添加上下文字段。
- 错误记录要点:记录错误本身、错误码、重试次数、调用栈(必要时)、相关输入参数;避免只打印 err 字符串。
三 性能与可靠性优化
- 减少阻塞:
- 使用 Sync() 或配置批量/缓冲写入(如 zap 的生产配置、批量编码器),降低系统调用次数。
- 高并发场景可考虑异步写入适配层,将日志写入与业务逻辑解耦。
- 避免性能陷阱:
- 避免在热路径拼接耗时字符串;优先结构化字段。
- 控制日志量:采样或降级高噪声模块的 DEBUG 日志。
四 文件轮转与系统日志集成
- 文件轮转(应用内):使用 lumberjack 控制单个日志文件大小、保留份数与压缩。
- MaxSize(MB)、MaxBackups、MaxAge(天)、Compress
- 系统级轮转:使用 logrotate 管理日志生命周期,适合 systemd 服务。
- 示例配置 /etc/logrotate.d/myapp:
- /var/log/myapp.log {
- daily; rotate 7; compress; missingok; notifempty
- create 0640 myapp adm
- postrotate: systemctl kill -s HUP myapp.service >/dev/null 2>&1 || true
- }
- 作为 systemd 服务时,优先输出到 stdout/stderr,用 journald 统一采集:
- 查看:journalctl -u myapp.service -f
- 按启动查看:journalctl -b
- 按关键字:journalctl -u myapp.service -e “timeout”
五 集中化观测与快速排查
- 集中化与分析:
- ELK Stack(Elasticsearch/Logstash/Kibana)或 EFK(加 Fluentd)做检索与可视化。
- Prometheus + Grafana 结合日志指标做告警与面板。
- GoAccess 快速分析访问类日志(如 Nginx)。
- 快速排查清单:
- 先定位服务实例与时间段:journalctl -u myapp -b -S “2025-11-14 10:00:00”
- 关键字检索:grep -n “timeout” /var/log/myapp.log
- 追踪请求链路:在日志中统一打印 trace_id/request_id,串联上下游。