Go 浅析主流日志库:从设计层学习如何集成日志轮转与切割功能

简介: 本文将探讨几个热门的 go 日志库如 logrus、zap 和官网的 slog,我将分析这些库的的关键设计元素,探讨它们是如何支持日志轮转与切割功能的配置。

前言

在现有的日志库中,包括 go 1.21.0 引入的 slog 日志库,它们通常都支持对日志文件进行轮转与切割,只不过这些功能并不直接被内置,而是需要我们主动配置来启用。

本文将探讨几个热门的日志库如 logruszap 和官网的 slog,我将分析这些库的的关键设计元素,探讨它们是如何支持日志轮转与切割功能的配置。

准备好了吗?准备一杯你最喜欢的咖啡或茶,随着本文一探究竟吧。


前段时间发布了一篇 Go slog 包:开启结构化日志的奇妙之旅 文章,有一位网友问我该日志库是否支持日志轮转与切割功能,此文章也算是解答他的一个疑惑。

6c35734c7ca835f16d5f7987d16a43c8.png

浅析 logrus、zap 和 slog 的设计

在对 logruszapslog 这几个日志库的设计进行对比分析时,一个显著的共同点是它们都包含了 io.Writer 这个关键的属性。这一属性在日志框架设计中起着核心作用,它决定了日志输出的目标位置。

logrus 日志库

logrus 是一个功能丰富的Go语言日志库,它提供了结构化日志记录、日志级别控制等功能。

当使用 logrus 时,可以调用 logrus.New() 函数来创建 Logger 实例。通过该实例我们执行很多操作,例如自定义日志输出的位置和打印日志等。我们看看下面的代码:

logger := logrus.New()
logger.Out = os.Stdout // 标准输出
// 或者定向到文件
//out, err := os.OpenFile("file.log", os.O_CREATE|os.O_WRONLY, 0666)
//if err != nil {
   
   
//    panic(err)
//}
//logger.Out = out

Logger 结构体的定义如下所示:

type Logger struct {
   
   
    Out io.Writer
    Hooks LevelHooks
    Formatter Formatter
    // 其他字段...
}

关键属性 Out,其类型为 io.Writer,这一属性用于指定日志的输出目标,无论是标准输出、文件,还是其他自定义的输出载体。

zap 日志库

zap 是一个性能极高的日志库。它提供了结构化日志记录、多级别日志控制,以及灵活的配置选项。

logrus 类似,zap 也允许支持通过配置来决定日志输出的位置,但实现方式略有不同。在 zap 中,日志输出是通过配置 zapcore.Core 实现的。在创建 zapcore.Core 实例时,需要指定一个 zapcore.WriteSyncer 接口实现作为参数,这个参数直接决定了日志的输出目标。要创建 zapcore.WriteSyncer 实例,通常使用 zapcore.AddSync() 函数,它接收一个类型为 io.Writer 的参数。

下面是一个使用 zap 创建日志实例的基本示例:

writer := zapcore.AddSync(os.Stdout) // 使用标准输出作为日志目标
core := zapcore.NewCore(
    zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()),
    writer,
    zap.InfoLevel,
)
logger := zap.New(core)
defer logger.Sync() // 刷新任何缓冲的日志条目

// 使用 logger 进行日志记录

关键在于 zapcore.AddSync() 函数,该函数接收一个类型为 io.Writer 的参数,这一参数用于指定日志的输出目标,无论是标准输出、文件,还是其他自定义的输出载体。

slog 日志库

slog 是在 go 1.21.0 版本引入的一个官网日志库,它提供了结构化日志。如果想要更详细地了解 slog 日志库,自荐一篇文章 Go slog 包:开启结构化日志的奇妙之旅

logruszap 类似,slog 也允许用户通过指定 io.Writer 参数来设置日志输出的目标。这一设置是在创建 slog.Handler 接口的实现时进行的。

textLogger := slog.New(slog.NewTextHandler(os.Stdout, nil))
jsonLogger := slog.New(slog.NewJSONHandler(os.Stdout, nil))

在这两个函数中,slog.NewTextHandlerslog.NewJSONHandler 第一个参数的类型都是 io.Writer

浅析总结

在对 logurszapslog 这三个主流日志库的分析中,我们可以发现一个关键的共同点:它们在处理日志输出时均依赖于 io.Writer 接口。这些日志库通过将 io.Writer接口作为关键参数的类型,以便设置日志的输出目标。

请在此添加图片描述

日志轮转与切割功能的实现机制与实践

实现机制

在浅析了 logurszapslog 日志库的设计后,我们发现了它们的共同点。现在,让我们深入了解日志轮转与切割功能的实现机制。

为了实现 日志文件的轮转与切割,通常我们会借助第三方库,如 lumberjack,当然还有其他类似的库可供选择,这里就不一一列举了。

lumberjack 是一个专门设计用于日志轮转和切割的库,其作用可以类比于一个可插拔的组件。我们可以通过配置该组件,并将其 集成 到所选的日志库中,从而实现日志文件的轮转与切割功能。

初始化 lumberjack 组件的代码如下所示:

log := &lumberjack.Logger{
   
   
    Filename:   "/path/file.log", // 日志文件的位置
    MaxSize:    10, // 文件最大尺寸(以MB为单位)
    MaxBackups: 3, // 保留的最大旧文件数量
    MaxAge:     28, // 保留旧文件的最大天数
    Compress:   true, // 是否压缩/归档旧文件
    LocalTime:  true, // 使用本地时间创建时间戳
}

在这个例子中,我们创建了一个 lumberjack.Logger 实例,并设置了以下参数:

  • Filename:指定日志文件的存储路径。
  • MaxSize:日志文件达到多少 MB 后进行轮转。
  • MaxBackups:最多保留多少个旧日志文件。
  • MaxAge:旧文件保留的最长时间(天)。
  • Compress:是否压缩旧文件(如转换为.gz)。

需要特别注意的是, lumberjackLogger 结构体实现了 io.Writer 接口。这意味着所有关于日志文件的轮转与切割的核心逻辑都封装在 Write 方法中。这一实现也方便 Logger 结构体被集成到任何支持 io.Writer 参数的日志库中。

明白了这些,想必你已经知道如何实现日志轮转与切割的功能了吧。lumberjacklogger 结构体实现了 io.Writer 接口,因此将它传递到第三方库中,就能完成集成配置了。

实践

logrus 日志库的实现

log := &lumberjack.Logger{
   
   
    Filename:   "/path/file.log", // 日志文件的位置
    MaxSize:    10,               // 文件最大尺寸(以MB为单位)
    MaxBackups: 3,                // 保留的最大旧文件数量
    MaxAge:     28,               // 保留旧文件的最大天数
    Compress:   true,             // 是否压缩/归档旧文件
    LocalTime:  true,             // 使用本地时间创建时间戳
}
logger := logrus.New()
logger.Out = log

zap 日志库的实现

log := &lumberjack.Logger{
   
   
    Filename:   "/path/file.log", // 日志文件的位置
    MaxSize:    10,               // 文件最大尺寸(以MB为单位)
    MaxBackups: 3,                // 保留的最大旧文件数量
    MaxAge:     28,               // 保留旧文件的最大天数
    Compress:   true,             // 是否压缩/归档旧文件
    LocalTime:  true,             // 使用本地时间创建时间戳
}
writer := zapcore.AddSync(log)
core := zapcore.NewCore(
    zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()),
    writer,
    zap.InfoLevel,
)
logger := zap.New(core)
defer logger.Sync() // 刷新任何缓冲的日志条目

slog 日志库的实现

log := &lumberjack.Logger{
   
   
    Filename:   "/path/file.log", // 日志文件的位置
    MaxSize:    10,               // 文件最大尺寸(以MB为单位)
    MaxBackups: 3,                // 保留的最大旧文件数量
    MaxAge:     28,               // 保留旧文件的最大天数
    Compress:   true,             // 是否压缩/归档旧文件
    LocalTime:  true,             // 使用本地时间创建时间戳
}
textLogger := slog.New(slog.NewTextHandler(log, nil))
jsonLogger := slog.New(slog.NewJSONHandler(log, nil))

小结

本文对三个热门的日志库 logruszapslog 设计要素进行浅析,我们发现虽然它们在创建日志实例的细节上有所差异,但它们共同依赖于 io.Writer 接口参数来处理日志的输出。掌握如何配置 io.Writer 参数,并结合 lumberjack 库的使用,我们就可以实现日志文件的轮转与切割功能。

即使后面推出新的日志库,我们也可以通过类似的方法,快速地集成日志文件的轮转与切割功能。

如果本文对你有帮助,欢迎点赞收藏加关注,如果本文有错误的地方,欢迎指出!

我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
目录
相关文章
|
10月前
|
存储 监控 算法
防止员工泄密软件中文件访问日志管理的 Go 语言 B + 树算法
B+树凭借高效范围查询与稳定插入删除性能,为防止员工泄密软件提供高响应、可追溯的日志管理方案,显著提升海量文件操作日志的存储与检索效率。
295 2
|
11月前
|
XML 测试技术 API
利用C#开发ONVIF客户端和集成RTSP播放功能
利用C#开发ONVIF客户端和集成RTSP播放功能
4946 123
|
人工智能 监控 中间件
如何用go语言实现类似AOP的功能
本文介绍了如何在 Go 语言中借鉴 Java 的 AOP(面向切面编程)思想,通过 Gin 框架的中间件和函数包装机制实现日志记录、权限校验等横切关注点与业务逻辑的解耦。内容涵盖 AOP 的优点、Go 中的实现方式、Gin 中间件与 AOP 的异同,帮助开发者提升代码模块化与可维护性。
422 0
|
测试技术 数据处理 调度
Dataphin功能Tips系列(57)「预览」vs「运行」:离线集成的神奇按钮
在数据开发过程中,使用Dataphin处理离线集成任务时,可能遇到数据过滤和字段计算组件配置正确性的验证问题。通过「预览」功能,可快速验证处理逻辑而不影响目标表;对于需要调度的任务,担心资源占用和耗时超出预期时,可使用「运行」功能进行全流程测试,评估实际耗时与资源消耗。「预览」适合逻辑验证,「运行」用于真实环境模拟,两者结合助力高效开发与调试。
398 5
|
SQL Java 关系型数据库
Dataphin功能Tips系列(53)-离线集成任务如何合理配置JVM资源
本文探讨了将MySQL数据同步至Hive时出现OOM问题的解决方案。
475 5
|
11月前
|
SQL 运维 关系型数据库
【产品升级】Dataphin V5.0版本发布:助力出海业务、增全量一体集成、异步调用API等更多功能等你发现
Dataphin是瓴羊推出的智能数据建设与治理平台,基于阿里巴巴内部实践,提供一站式数据建设与治理能力。V5.0版本研发新增支持Databricks作为离线计算引擎、支持MySQL数据库一键增全量同步、支持管理Hudi、Delta Lake表等;资产运营与消费持续提效,支持批量编辑目录名称及描述、Quick BI仪表板的上架管理等功能,增加资产可用性与盘点效率。
505 8
|
存储 JSON 前端开发
Django集成图片验证码功能:基于django-simple-captcha实现
在Web应用开发中,验证码是防止恶意攻击、自动化脚本滥用的重要手段。本文将介绍如何使用django-simple-captcha库在Django项目中快速集成图片验证码功能,包括安装配置、核心实现代码及使用方法。
304 0
|
传感器 供应链 物联网
农业单亩价值创造功能技术集成的概念与内涵
农业单亩价值创造的技术集成,通过系统性创新打破传统单一模式,融合现代科技与生态理念,提升资源效率、经济效益和生态价值。其核心在于技术协同,实现精准农业、智能装备和生物强化等多维联动,推动经济、生态和社会价值统一。同时,注重资源集约化与循环化利用,延伸产业链并升级价值链,从短期高产转向长期可持续发展。政策与制度创新支撑技术普惠,未来需因地制宜解决技术适配性和成本收益平衡问题,重塑农业评价体系,实现高质量发展。
|
资源调度 安全 数据安全/隐私保护
Cyber Triage 3.14 发布,带来全新用户界面、Hayabusa 集成、基线设定等功能
Cyber Triage 3.14 发布,带来全新用户界面、Hayabusa 集成、基线设定等功能
279 0
Cyber Triage 3.14 发布,带来全新用户界面、Hayabusa 集成、基线设定等功能
|
监控 安全 Java
Java 开发中基于 Spring Boot 3.2 框架集成 MQTT 5.0 协议实现消息推送与订阅功能的技术方案解析
本文介绍基于Spring Boot 3.2集成MQTT 5.0的消息推送与订阅技术方案,涵盖核心技术栈选型(Spring Boot、Eclipse Paho、HiveMQ)、项目搭建与配置、消息发布与订阅服务实现,以及在智能家居控制系统中的应用实例。同时,详细探讨了安全增强(TLS/SSL)、性能优化(异步处理与背压控制)、测试监控及生产环境部署方案,为构建高可用、高性能的消息通信系统提供全面指导。附资源下载链接:[https://pan.quark.cn/s/14fcf913bae6](https://pan.quark.cn/s/14fcf913bae6)。
2758 0