Timberjack确实解决了Golang日志轮转中时间维度的重要需求。以下是一个基于Timberjack的完整示例,展示如何配置基于时间的日志轮转:
package main
import (
"log"
"gopkg.in/natefinch/timberjack.v2"
)
func main() {
// 创建Timberjack日志记录器
logger := &timberjack.Logger{
Filename: "/var/log/myapp/app.log",
MaxSize: 100, // 文件最大大小(MB)
MaxBackups: 30, // 保留的旧日志文件数量
MaxAge: 90, // 保留天数
Compress: true, // 是否压缩旧日志
LocalTime: true, // 使用本地时间
// Timberjack新增的时间轮转配置
RotationTime: 24, // 轮转间隔时间(小时)
RotationSize: 0, // 设为0表示仅按时间轮转
}
// 设置标准日志输出到Timberjack
log.SetOutput(logger)
// 示例日志记录
log.Println("应用程序启动")
log.Printf("当前日志文件: %s", logger.Filename)
// 模拟应用程序运行
for i := 0; i < 1000; i++ {
log.Printf("处理第 %d 个请求", i)
}
}
对于需要更细粒度控制的场景,可以结合标准库的log包使用:
package main
import (
"fmt"
"os"
"time"
"gopkg.in/natefinch/timberjack.v2"
)
type AppLogger struct {
*timberjack.Logger
}
func NewAppLogger() *AppLogger {
return &AppLogger{
Logger: &timberjack.Logger{
Filename: "./logs/app.log",
MaxSize: 50,
MaxBackups: 7,
MaxAge: 30,
Compress: true,
LocalTime: true,
RotationTime: 1, // 每小时轮转一次
RotationSize: 0,
},
}
}
func (l *AppLogger) Write(p []byte) (n int, err error) {
// 添加时间戳前缀
timestamp := time.Now().Format("2006-01-02 15:04:05")
formatted := fmt.Sprintf("[%s] %s", timestamp, p)
return l.Logger.Write([]byte(formatted))
}
func main() {
logger := NewAppLogger()
// 直接写入日志
logger.Write([]byte("应用程序初始化完成\n"))
// 同时输出到控制台和文件
multiWriter := io.MultiWriter(os.Stdout, logger)
fmt.Fprintln(multiWriter, "双重日志输出示例")
}
对于需要按天轮转的场景:
func setupDailyRotation() *timberjack.Logger {
return &timberjack.Logger{
Filename: "/var/log/myapp/daily.log",
MaxSize: 0, // 禁用大小轮转
MaxBackups: 365, // 保留一年日志
MaxAge: 0, // 不按天数删除
Compress: true,
LocalTime: true,
RotationTime: 24, // 每天轮转
RotationSize: 0,
}
}
Timberjack的轮转行为说明:
- 当
RotationTime > 0时,会按固定时间间隔轮转
- 当
RotationSize > 0时,会在达到指定大小时轮转
- 两者可同时启用,满足任一条件即触发轮转
- 轮转文件名会自动添加时间戳后缀,如
app.log-20250115-150000
这个库确实填补了Golang生态中时间轮转日志的空白,API设计保持了与Lumberjack的完全兼容,迁移成本极低。