CentOS 上 Golang 日志优化实践
一 核心优化策略
二 库与方案选型对比
| 维度 | slog(标准库) | zap(Uber) | zerolog | logrus |
|---|---|---|---|---|
| 结构化 | 原生 key=value | 结构化强,支持 Sugared | 强制结构化(链式 API) | 支持 Fields |
| 性能 | 中等 | 极高 | 极高(零分配倾向) | 中等 |
| 依赖 | 无 | 第三方 | 第三方 | 第三方 |
| 动态级别 | 需自定义 Handler | 原生 AtomicLevel | 支持 Level 接口 | 支持 SetLevel |
| 适用场景 | 新项目、少依赖 | 高并发/性能敏感 | 极致性能/内存敏感 | 旧项目兼容 |
选型建议:新项目优先 slog 或 zap;极致性能选 zerolog;存量项目可在保留 logrus 的同时逐步迁移到 zap/slog。
三 落地配置示例
package main
import (
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"gopkg.in/natefinch/lumberjack.v2"
"os"
)
func NewZapLogger(logPath string, level zapcore.Level) *zap.Logger {
encCfg := zapcore.EncoderConfig{
TimeKey: "ts",
LevelKey: "level",
CallerKey: "caller",
MessageKey: "msg",
EncodeLevel: zapcore.CapitalLevelEncoder,
EncodeTime: zapcore.ISO8601TimeEncoder,
EncodeCaller: zapcore.ShortCallerEncoder,
}
core := zapcore.NewCore(
zapcore.NewJSONEncoder(encCfg),
zapcore.AddSync(&lumberjack.Logger{
Filename: logPath,
MaxSize: 100, // MB
MaxBackups: 7, // 保留个数
MaxAge: 28, // 天
Compress: true, // 压缩旧日志
}),
level,
)
return zap.New(core, zap.AddCaller(), zap.AddStacktrace(zapcore.ErrorLevel))
}
func main() {
logger := NewZapLogger("./logs/app.log", zap.InfoLevel)
defer logger.Sync()
logger.Info("service started", zap.String("version", "1.2.3"))
}
// 级别控制:AtomicLevel 可在运行时调整
level := zap.NewAtomicLevelAt(zap.InfoLevel)
// 多输出:控制台(开发友好)+ 文件(生产归档)
consoleEnc := zapcore.NewConsoleEncoder(zap.NewDevelopmentEncoderConfig())
fileEnc := zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig())
console := zapcore.Lock(os.Stdout)
file := zapcore.AddSync(&lumberjack.Logger{
Filename: "./logs/app.log", MaxSize: 100, MaxBackups: 7, MaxAge: 28, Compress: true,
})
core := zapcore.NewTee(
zapcore.NewCore(consoleEnc, console, level),
zapcore.NewCore(fileEnc, file, level),
)
logger := zap.New(core, zap.AddCaller())
defer logger.Sync()
# /etc/logrotate.d/myapp
/var/log/myapp/*.log {
daily
rotate 7
compress
missingok
notifempty
copytruncate
dateext
}
# 建议:systemd 服务使用 StandardOutput=null; StandardError=journal+console
# 以避免与文件写入竞争
提示:在容器中优先让进程直接写文件并使用 lumberjack;在虚拟机/物理机上可叠加 logrotate 做合规归档。
四 系统层面优化
五 排查与优化清单