使用 lumberjack 让 logrous 实现日志文件切割
logrus 的 hook 说明
hook 结构定义
type Hook struct {
Writer io.Writer // hook 自己 io.Writer,可以将 logrous 的日志推送到这里
LogLevels []log.Level // 触发 hook 的日志等级
}
接口函数
func (hook *Hook) Fire(entry *log.Entry) error
自定义 hook 的核心。当满足条件的日志,触发了 hook 操作时,就会调用 Fire 函数。比如要实现将 logrus 的日志发送给 syslog,则可以在这里实现定义
func (hook *Hook) Levels() []log.Level
定义 logrus 的哪些等级的日志会触发 hook 操作,也就是触发 Fire
使用 lumberjack 给 logrous 实现日志文件切割
lumberjack 是一个简单而有效的 Go 语言日志轮转库,它可以与标准库 log 或其他日志库(包括 logrus)结合使用来实现日志文件的切割。虽然 logrus 本身不直接支持日志轮转,但你可以通过编写一个自定义的钩子(hook)来将 lumberjack 集成到 logrus 中。
不过,通常不需要手动编写这样的钩子,因为社区可能已经提供了现成的解决方案。然而,在我最后的检查中,我没有找到一个直接集成 lumberjack 和 logrus 的官方或广泛认可的钩子库。但你可以按照以下步骤手动实现这一功能:
- 安装
logrus和lumberjack。 - 创建一个自定义的
logrus钩子,该钩子使用lumberjack来处理日志输出。 - 将这个钩子添加到
logrus实例中。
下面是一个简单的示例,展示了如何实现这一过程:
package main
import (
"github.com/sirupsen/logrus"
"gopkg.in/natefinch/lumberjack.v2"
"os"
)
// CustomHook 是一个自定义的 logrus 钩子,它使用 lumberjack 进行日志轮转。
type CustomHook struct {
logger *lumberjack.Logger
}
// NewCustomHook 创建一个新的 CustomHook 实例。
func NewCustomHook(filename string, maxSize int, maxBackups int, maxAge int, compress bool) *CustomHook {
return &CustomHook{
logger: &lumberjack.Logger{
Filename: filename,
MaxSize: maxSize, // MB
MaxBackups: maxBackups,
MaxAge: maxAge, // days
Compress: compress,
},
}
}
// Fire 是 logrus 钩子接口的一部分,当日志事件发生时会被调用。
func (hook *CustomHook) Fire(entry *logrus.Entry) error {
// 将日志条目格式化为字符串并写入 lumberjack 日志记录器。
line, err := entry.String()
if err != nil {
return err
}
_, err = hook.logger.Write([]byte(line + "\n"))
return err
}
// Levels 定义了该钩子应该监听哪些日志级别。
func (hook *CustomHook) Levels() []logrus.Level {
return logrus.AllLevels
}
func main() {
// 创建一个自定义的 logrus 钩子,配置日志轮转参数。
hook := NewCustomHook("logs/myapp.log", 10, 3, 28, true)
// 配置 logrus 使用自定义钩子。
logger := logrus.New()
logger.Hooks.Add(hook)
logger.SetFormatter(&logrus.TextFormatter{
TimestampFormat: "2006-01-02 15:04:05",
FullTimestamp: true,
})
logger.SetLevel(logrus.DebugLevel)
// 测试日志输出。
logger.Info("This is an info message.")
logger.Warn("This is a warning message.")
logger.Error("This is an error message.")
// 模拟一些工作以生成更多日志。
for i := 0; i < 100; i++ {
logger.Infof("This is log message %d\n", i)
// 为了演示日志轮转,这里应该有一个延迟,但请注意在实际应用中不要阻塞主线程。
// 使用 goroutine 或其他异步机制来生成日志可能更合适。
// time.Sleep(time.Minute * 10) // 例如,每10分钟生成一条日志(这里为了演示而注释掉)。
}
// 注意:在实际应用中,通常不会在主函数中阻塞以等待日志生成。
// 日志生成通常是由应用程序的其他部分(如处理请求的 goroutine)负责的。
// 这里只是为了演示如何配置和使用 logrus 与 lumberjack。
}
重要提示:
- 在上面的示例中,
time.Sleep被注释掉了,因为在实际应用中,你不应该在主函数中阻塞以等待日志生成。相反,你应该让应用程序的其他部分(如处理请求的 goroutine)负责生成日志。 - 为了确保日志轮转正常工作,你的应用程序需要持续运行并生成足够的日志以触发轮转条件(如文件大小达到限制)。
- 上面的代码示例是一个简单的演示,并没有处理所有可能的错误情况和边界条件。在生产环境中使用时,请确保添加适当的错误处理和日志记录。
- 请注意,
lumberjack会在达到指定的文件大小限制时创建新的日志文件,并根据配置保留旧的文件。但是,它不会立即删除或压缩旧文件;这些操作会在下一次写入新日志时发生(如果配置了压缩)。
PS:
以上代码来自大模型结果。对我的项目而言,将 luberjack 当做 logrous 的 hook 后,logrous 会写一次日志,luberjack 也会写一次日志,这样就会造成一份日志写两次。因此需要将 Fire 重写成如下结果
func (hook *CustomHook) Fire(entry *logrus.Entry) error {
// 触发 lumberjack 日志切割。
_, err := hook.logger.Write([]byte(""))
return err
}

浙公网安备 33010602011771号