golang在ubuntu上的日志记录策略
小樊
32
2025-12-04 15:47:37
整体策略与分层
- 输出目标分层:容器与 systemd 场景优先输出到stdout/stderr,由journald统一采集;物理机/虚拟机可将关键业务日志同时写入文件便于落盘与审计。
- 日志格式:统一使用结构化日志(JSON),包含timestamp、level、msg、caller、trace_id/span_id、request_id等字段,便于检索与聚合。
- 日志级别:按环境区分,开发/预发可用DEBUG,生产默认INFO,异常时临时上调至DEBUG排查,事后回落。
- 采样与脱敏:对高频 DEBUG/TRACE 进行采样避免洪泛;对手机号、身份证、密码等敏感字段自动脱敏。
- 性能要点:优先选择高性能库(如zap、zerolog),必要时启用异步写入/批量写入,减少系统调用与锁竞争。
- 可运维性:通过运行时可调级别、日志轮转、集中采集与监控告警形成闭环。
日志库与级别设计
- 选型建议:
- 标准库 log:上手快、功能有限,适合简单工具或学习场景。
- logrus:功能丰富、插件化强,适合中大型项目快速落地结构化日志。
- zap:Uber 开源,高性能、低分配,适合高并发与低延迟场景。
- zerolog:以零分配 JSON著称,极致性能,适合对延迟敏感的服务。
- 级别使用规范:
- DEBUG:开发/排障细节,生产默认关闭或采样。
- INFO:关键业务流程、状态变更、重要里程碑。
- WARN:可恢复异常、降级策略触发、边界条件。
- ERROR:需要人工介入的错误,附带错误上下文与堆栈。
- FATAL/DPANIC:不可恢复错误,记录后立即退出。
- 常见误区:全局 logger 滥用导致日志混乱;级别设置不当造成信息缺失或过多;结构化字段过度冗余影响分析效率。
输出与轮转方案
- 应用内轮转(代码侧):使用 zap + lumberjack 管理文件滚动,典型参数:MaxSize=10MB、MaxBackups=3、MaxAge=28天、Compress=true,示例见下。
- 系统级轮转(运维侧):使用 logrotate 管理落盘日志,支持按日/按大小切割、压缩、保留天数、缺失不报错、按扩展名归档等;配置路径 /etc/logrotate.d/。
- 选择建议:容器化优先“stdout + journald”;物理机/VM 建议“文件 + logrotate”;若需应用内强一致的文件滚动与保留策略,再叠加 lumberjack。
与 Ubuntu 系统日志集成
- systemd 服务输出:将应用日志打印到stdout/stderr,通过 journald 采集;使用
journalctl -u <service> -f 实时查看,按时间/级别/单元过滤。
- 结构化增强:在 JSON 日志中保留level、msg、caller等字段,便于 journald 与后续日志系统解析。
- 服务示例(片段):
- [Service] 中
StandardOutput=journal、StandardError=journal
- 运行时动态调节级别(配合 zap 的 AtomicLevel 或信号/管理接口)。
监控、采样与脱敏
- 性能与问题定位:暴露 /metrics 端点,使用 Prometheus 采集指标,配合 Grafana 可视化;需要时开启 pprof 做 CPU/内存/阻塞分析。
- 采样与降噪:对高频路径的 DEBUG 进行采样,避免磁盘与网络压力;对异常尖峰设置速率限制。
- 上下文与链路:在日志中统一注入trace_id/span_id、request_id、user_id、client_ip等,便于端到端追踪。
- 安全合规:对敏感字段脱敏,避免将密钥、令牌、个人敏感信息写入日志;定期审计与清理历史日志。
快速落地示例
- 应用内文件日志(zap + lumberjack,JSON,轮转)
- 代码示例:
- go get go.uber.org/zap gopkg.in/natefinch/lumberjack.v2
- 要点:设置 Encoding=json、AtomicLevel、ISO8601 时间、启用 caller,并使用 lumberjack.Logger 控制滚动与保留。
- 系统级轮转(logrotate 配置示例)
- 新建:/etc/logrotate.d/myapp
- 内容:
- /var/log/myapp/*.log {
- daily
- rotate 7
- missingok
- notifempty
- compress
- dateext
- postrotate
- systemctl reload myapp.service >/dev/null 2>&1 || true
- endscript
- }
- 说明:按日切割、保留7天、压缩旧日志;如需通知应用重新打开日志文件,可在 postrotate 中执行服务 reload。