slog实战:文件日志、轮转与kafka集成

这篇具有很好参考价值的文章主要介绍了slog实战:文件日志、轮转与kafka集成。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

《slog正式版来了:Go日志记录新选择![1]》一文发布后,收到了很多读者的反馈,意见集中在以下几点:

  • 基于slog如何将日志写入文件

  • slog是否支持log轮转(rotation),如果slog不支持,是否有好的log轮转插件推荐?

  • 如何与kafka集成

  • 日志输出有哪些最佳实践

这篇文章就是对上述问题进行补充说明的,供大家参考,希望能给大家带去帮助。

1. 输出日志到文件

之所以《slog正式版来了:Go日志记录新选择![2]》一文中使用的例子[3]都以os.Stdout(标准输出)为log输出目的地,主要是因为基于云原生微服务架构模式下,应用都跑在容器中(k8s[4]的pod中),基本都是将log输出到Stdout,而不会写入某个具体的本地文件。但如果应用是基于虚拟机或裸机部署,那么将日志写入文件仍然是第一选项。

其实,使用slog内置的TextHandler和JSONHandler可以非常方便的将结构化的日志写入文件,因为slog.NewXXXHandler函数的第一个参数是一个io.Writer,这样通过将一个文件的描述符传递给NewXXXHandler,即可创建一个向文件写入日志的Logger。我们看下面示例代码:

//slog-in-action/log2file/main.go

package main
  
import (
    "log/slog"
    "os"
)

func main() {
    f, err := os.Create("foo.log")
    if err != nil {
        panic(err)
    }
    defer f.Close()
    logger := slog.New(slog.NewJSONHandler(f, nil))
    slog.SetDefault(logger)
    slog.Info("greeting", "say", "hello")
}

在这个示例中,我们创建了目标日志文件foo.log,并将其描述符(*os.File)传给了NewJSONHandler函数,通过这种方式创建出来的Logger输出的日志内容将会被写入foo.log文件中:

$go run main.go
$cat foo.log
{"time":"2023-09-02T19:38:45.441782+08:00","level":"INFO","msg":"greeting","say":"hello"}

这种方式应该可以满足大多数gopher的需求了。

2. 日志文件的管理

一旦将日志写入文件,后续就要对日志文件进行管理,比如:日志文件的轮转、压缩、归档以及定期清理(腾出磁盘空间)等。

关于如何对日志文件管理的方案大致有这么几种。

第一种是借助外部工具,比如在主流的Linux发行版上都有一个logrotate[5]工具程序,应用程序可以借助该工具对应用输出的日志进行rotate、压缩、归档和删除历史归档日志,这样可大幅简化应用的日志输出逻辑,应用仅需要将日志输出到一个具名文件中即可,其余都交给logrotate处理。关于如何使用logrotate,我在《写Go代码时遇到的那些问题[第1期]》[6]中有详细说明,感兴趣的朋友可以移步阅读一下,这里就不赘述了。

第二种就是log包自身支持。大多数log包都没有将日志文件管理作为自己的功能feature,slog包也是如此,没有原生提供此功能。

第三种就是通过支持log包相关插件接口的一些扩展包来支持。lumberjack[7]就是这样的一个插件包,它支持与很多知名的log包集成在一起实现对log文件的管理,比如logrus、zap等。我曾在《写Go代码时遇到的那些问题[第3期] 》[8]和《一文告诉你如何用好uber开源的zap日志库》[9]两篇文章中分别讲解了logrus和zap与lumberjack集成在一起对日志文件进行管理的方法。如果你对lumberjack不是很熟悉,建议你在继续阅读下面内容之前,温习一下这两篇文章。

在这一篇文章中,我们用示例来简单说说如何将slog与lumberjack集成以实现对log文件的管理功能。看下面示例:

//slog-in-action/lumberjack/main.go

package main
  
import (
    "log/slog"

    "gopkg.in/natefinch/lumberjack.v2"
)

func main() {
    r := &lumberjack.Logger{
        Filename:   "./foo.log",
        LocalTime:  true,
        MaxSize:    1,
        MaxAge:     3,
        MaxBackups: 5,
        Compress:   true,
    }
    logger := slog.New(slog.NewJSONHandler(r, nil))
    slog.SetDefault(logger)

    for i := 0; i < 100000; i++ {
        slog.Info("greeting", "say", "hello")
    }
}

在这个示例中,我们看到:*lumberjack.Logger实现了io.Writer接口,因为只要将实例化后的*lumberjack.Logger以参数形式传入NewXXXHandler即可完成slog与lumberjack的集成。至于日志文件的管理行为则是通过lumberjack.Logger实例化过程的字段赋值来定制的。比如这里我们指定了目标日志文件名(Filename)为"./foo.log",指定当文件达到1M字节时(MaxSize)进行rotate,对rotate后的文件进行压缩(Compress),最多保留5个归档文件(MaxBackups)以及归档文件最多保存3天(MaxAge)等。

运行上述示例程序后,我们将在当前目录想得到如下文件:

$go run main.go
$ls
foo-2023-09-02T08-24-20.854.log.gz  foo-2023-09-02T08-24-20.979.log.gz foo-2023-09-02T08-24-21.098.log.gz  go.mod  main.go
foo-2023-09-02T08-24-20.918.log.gz  foo-2023-09-02T08-24-21.041.log.gz foo.log        go.sum

foo.log是当前正在写入的日志文件,而其他带有时间戳、以gz为后缀的文件则是归档文件。由于有了lumberjack对日志文件的管理,我们就不用再担心日志文件size过大、归档文件过多没有清理而导致的磁盘被占满的问题了。

注:lumberjack.Logger的各个属性字段的配置要根据你的应用实际输出日志的情况、本地磁盘可用空间来确定。

3. 与kafka集成

在我们团队的一个生产项目中,日志是不落盘而直接写入kafka的,关于这个事情,我在《Go社区主流Kafka客户端简要对比》[10]一文中也曾提到过,并给出了基于zap和不同kafka客户端实现向kafka写入日志的方案。

slog与kafka集成的思路也是类似的,不同的是定制KafkaHandler的方法,基于slog,我们要让KafkaHandler实现slog.Handler接口。在《slog正式版来了:Go日志记录新选择![11]》一文中,我们给出了一个向channel写入结构化日志的示例[12],KakfaHandler完全可以借鉴其中的ChanHandler,也是通过字节切片来承接JSONHandler写出的日志,不同的是将写入Channel改为通过kafka client写入Kafka! 在这里我就不给出KakfaHandler的实现了,这个作业留给大家,记得实现KafkaHandler后,使用slog/slogtest对其正确性做一个测试!

注:注意在实现KakfaHandler时,考虑goroutine并发使用同一个基于KafkaHandler创建的slog.Logger的情况,也就是字节切片的并发访问和共享的问题。

4. 日志输出的实践建议

在《聊聊Go应用输出日志的工程实践[13]》一文中,我聊了一些在日常使用log时遇到的问题、解决方法以及Go团队对log支持上的问题。log/slog的正式发布,一定程度上解决或改善了那篇文章中提到的部分问题。

此外,在读者关心的日志输出内容方面有哪些实践建议,我也总结了以下几点:

1). 选择合适的日志级别。常见的日志级别包括 DEBUG、INFO、WARNING和ERROR。在生产环境中,我们通常将日志级别设置为WARNING或ERROR,最低是info,不能再低了,避免打印过多日志以影响应用性能。

2). 日志级别要支持热更新。在系统出现异常时,如果要做在线调试,支持热更新的日志级别就特别重要,我们可以在一个调试时间窗口将日志级别下调至info或debug,这样可以抓取到一段时间的详细日志,以供调试和诊断参考。

3). 优先选结构化日志。相对于文本日志更适合人类阅读,结构化日志更适于机器解析、索引和查询。大多数正常情况下,我们是不会去看日志的,日志都会被汇集到集中日志中心存储、管理并索引(比如常见的ELK方案、近来的grafana的PLG方案(Promtail, Loki and Grafana)[14]等),以便于后续做查询和展示。针对这样的情况,显然结构化日志更适合。

4). 无论使用结构化还是文本形式日志,日志格式都要清晰易读。每条日志至少要打印时间、日志级别、事件源、事件详情等信息,对于固定的字段,要用属性(attribute)来设置,以提高输出性能。

5). 考虑到排查和诊断业务问题,通常会为日志添加上下文信息。比如:在日志中增加关于当前用户、请求ID等上下文信息等。但不应该在日志中输出用户的隐私数据等敏感信息,要么移除,要么做打码处理。

6). 考虑到监控和告警的需要,有些时候我们会对错误日志进行监控,可能会在日志中放置一些具有监控意义的特征字段。

7). 对于日志写入文件的情况,就如本文前面提到的,要考虑日志文件的管理:设置合理的分割轮转日志文件策略以及日志文件的归档管理,避免日志文件的无限增长对磁盘带来的影响。

日志输出内容没有“固定标准”,需根据大家实际所处的业务环境以及相关要求确定。

5. 小结

本文是《slog正式版来了:Go日志记录新选择![15]》一文的“补充篇”,主要对将slog日志如何写入文件以及对文件的管理(轮转、归档、清理等方案)做了说明。对于将slog与外部系统(如kafka)进行集成的思路做了点拨,最后还给出了一些关于日志输出实践方面的参考意见,希望能帮助到大家!

本文涉及的示例代码可以在这里[16]下载。


“Gopher部落”知识星球[17]旨在打造一个精品Go学习和进阶社群!高品质首发Go技术文章,“三天”首发阅读权,每年两期Go语言发展现状分析,每天提前1小时阅读到新鲜的Gopher日报,网课、技术专栏、图书内容前瞻,六小时内必答保证等满足你关于Go语言生态的所有需求!2023年,Gopher部落将进一步聚焦于如何编写雅、地道、可读、可测试的Go代码,关注代码质量并深入理解Go核心技术,并继续加强与星友的互动。欢迎大家加入!

slog实战:文件日志、轮转与kafka集成,kafka,分布式slog实战:文件日志、轮转与kafka集成,kafka,分布式

slog实战:文件日志、轮转与kafka集成,kafka,分布式slog实战:文件日志、轮转与kafka集成,kafka,分布式

著名云主机服务厂商DigitalOcean发布最新的主机计划,入门级Droplet配置升级为:1 core CPU、1G内存、25G高速SSD,价格5$/月。有使用DigitalOcean需求的朋友,可以打开这个链接地址[18]:https://m.do.co/c/bff6eed92687 开启你的DO主机之路。

Gopher Daily(Gopher每日新闻) - https://gopherdaily.tonybai.com

我的联系方式:

  • 微博(暂不可用):https://weibo.com/bigwhite20xx

  • 微博2:https://weibo.com/u/6484441286

  • 博客:tonybai.com

  • github: https://github.com/bigwhite

  • Gopher Daily归档 - https://github.com/bigwhite/gopherdaily

slog实战:文件日志、轮转与kafka集成,kafka,分布式

商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。

参考资料

[1] 

slog正式版来了:Go日志记录新选择!: https://tonybai.com/2023/09/01/slog-a-new-choice-for-logging-in-go

[2] 

slog正式版来了:Go日志记录新选择!: https://tonybai.com/2023/09/01/slog-a-new-choice-for-logging-in-go

[3] 

使用的例子: https://github.com/bigwhite/experiments/tree/master/slog-examples-go121

[4] 

k8s: https://tonybai.com/tag/k8s

[5] 

logrotate: https://github.com/logrotate/logrotate

[6] 

《写Go代码时遇到的那些问题[第1期]》: https://tonybai.com/2018/01/13/the-problems-i-encountered-when-writing-go-code-issue-1st

[7] 

lumberjack: https://github.com/natefinch/lumberjack

[8] 

《写Go代码时遇到的那些问题[第3期] 》: https://tonybai.com/2018/04/06/the-problems-i-encountered-when-writing-go-code-issue-3rd

[9] 

《一文告诉你如何用好uber开源的zap日志库》: https://tonybai.com/2021/07/14/uber-zap-advanced-usage

[10] 

《Go社区主流Kafka客户端简要对比》: https://tonybai.com/2022/03/28/the-comparison-of-the-go-community-leading-kakfa-clients

[11] 

slog正式版来了:Go日志记录新选择!: https://tonybai.com/2023/09/01/slog-a-new-choice-for-logging-in-go

[12] 

向channel写入结构化日志的示例: https://github.com/bigwhite/experiments/tree/master/slog-examples-go121/demo4

[13] 

聊聊Go应用输出日志的工程实践: https://tonybai.com/2022/03/05/go-logging-practice

[14] 

grafana的PLG方案(Promtail, Loki and Grafana): https://www.cncf.io/blog/2020/07/27/logging-in-kubernetes-efk-vs-plg-stack/

[15] 

slog正式版来了:Go日志记录新选择!: https://tonybai.com/2023/09/01/slog-a-new-choice-for-logging-in-go

[16] 

这里: https://github.com/bigwhite/experiments/tree/master/slog-in-action

[17] 

“Gopher部落”知识星球: https://public.zsxq.com/groups/51284458844544

[18] 

链接地址: https://m.do.co/c/bff6eed92687文章来源地址https://www.toymoban.com/news/detail-696489.html

到了这里,关于slog实战:文件日志、轮转与kafka集成的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • JAVA微服务场景下分布式日志收集排查问题实战

    问题产生的根由?不同服务的日志存在哪里?我们怎么去排查线上问题? 问题场景:我们部署的java服务可能有几十个,不同的项目里面他是看不到别的服务的日志,只有服务的返回msg消息,相比传统的单体服务来说,排查问题和解决问题的原因相对比较复杂和麻烦,我们传

    2024年02月02日
    浏览(47)
  • 【Distributed】分布式ELK日志文件分析系统(一)

      日志主要包括系统日志、应用程序日志和安全日志。系统远维和开发人员可以通过日志了解服务器软硬件信息、检查配置过程中的错误及错误发生的原因。经常分析日志可以了解服务器的负荷,性能安全性,从而及时采取措施纠正错误。   往往单台机器的日志我们使用

    2024年02月15日
    浏览(42)
  • (实战)docker-compose部署分布式日志方案EFK(Elasticsearch+Fluentd+Kibana)

    目录 背景 技术架构 部署安装 环境准备 配置Logback并模拟产生日志 制作fluentd镜像 运行docker-compose 效果展示         在现代的软件开发和运维领域,监控和日志管理是至关重要的任务。随着应用程序规模的扩大和分布式系统的普及,有效地跟踪和分析日志数据成为了挑战

    2024年02月03日
    浏览(41)
  • Hadoop大数据从入门到实战(二)分布式文件系统HDFS

    头歌实践教学平台 教学课堂 大数据从入门到实战 - 第2章 分布式文件系统HDFS 任务描述 本关任务:使用 Hadoop 命令来操作分布式文件系统。 编程要求 在右侧命令行中启动 Hadoop ,进行如下操作。 在 HDFS 中创建 /usr/output/ 文件夹; 在本地创建 hello.txt 文件并添加内容:“ HDFS的

    2024年02月12日
    浏览(47)
  • 【头歌】大数据从入门到实战 - 第2章 分布式文件系统HDFS

    任务描述 本关任务:使用 Hadoop 命令来操作分布式文件系统。 编程要求 在右侧命令行中启动 Hadoop ,进行如下操作。 在 HDFS 中创建 /usr/output/ 文件夹; 在本地创建 hello.txt 文件并添加内容:“ HDFS 的块比磁盘的块大,其目的是为了最小化寻址开销。”; 将 hello.txt 上传至 H

    2024年02月05日
    浏览(118)
  • 全面掌握 Jaeger 分布式调用链路跟踪理论和实战,Go 为所有使用 go-resty 库发起 HTTP 请求集成链路跟踪 jaeger(附源码)

    全面掌握 Jaeger 分布式调用链路跟踪理论和实战,Go 为所有使用 go-resty 库发起 HTTP 请求集成链路跟踪 jaeger(附源码)。 介绍一个开源的分布式跟踪系统 Jaeger,首先从理论基础知识开始学习,将学习如何在 HTTP 请求中集成链路跟踪,以及如何在 GORM 框架实现,最后学习 go-ze

    2024年02月13日
    浏览(53)
  • 【分布式技术专题】「OSS中间件系列」Minio的文件服务的存储模型及整合Java客户端访问的实战指南

    Minio的元数据 数据存储 MinIO对象存储系统没有元数据数据库,所有的操作都是对象级别的粒度的,这种做法的优势是: 个别对象的失效,不会溢出为更大级别的系统失效。 便于实现\\\"强一致性\\\"这个特性。此特性对于机器学习与大数据处理非常重要。 数据管理 元数据与数据一起

    2024年02月11日
    浏览(59)
  • Golang 结构化日志包 log/slog 详解(三):属性字段和日志级别

    上一篇文章讲解了 log/slog 包中的 Handler 的使用方法,通过不同的 Handler  可以输出不同格式的日志。接下来看一下如何自定义日志的属性字段和日志级别。 许多日志都有一些通用的的字段,例如日志级别 level、日志记录时间 time、日志信息 msg 等,这些字段就是属性字段。

    2024年02月09日
    浏览(36)
  • 分布式日志

    1.1 日志管理方案 服务器数量较少时 直接登录到目标服务器捞日志查看 → 通过 rsyslog 或shell/python 等脚本实现日志搜集并集中保存到统一的日志服务器 服务器数量较多时 ELK 大型的日志系统,实现日志收集、日志存储、日志检索和分析 容器环境 EFK Loki+Granfana 1.2 使用ELK的原因

    2024年01月19日
    浏览(31)
  • 4.日志分布式-ELK

    ELK平台是一套完整的日志集中处理解决方案,将 ElasticSearch、Logstash 和 Kiabana 三个开源工具配合使用, 完成更强大的用户对日志的查询、排序、统计需求。 ElasticSearch:是基于Lucene(一个全文检索引擎的架构)开发的分布式存储检索引擎,用来存储各类日志。 Elasticsearch 是用

    2024年02月13日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包