东阳网站建设dyfwzx,四川旅游,网站中的打赏怎么做的,小程序开发哪里有《slog正式版来了#xff1a;Go日志记录新选择#xff01;[1]》一文发布后#xff0c;收到了很多读者的反馈#xff0c;意见集中在以下几点#xff1a; 基于slog如何将日志写入文件slog是否支持log轮转(rotation)#xff0c;如果slog不支持#xff0c;是否有好的log轮转… 《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.gopackage mainimport (log/slogos
)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.44178208:00,level:INFO,msg:greeting,say:hello} 这种方式应该可以满足大多数gopher的需求了。 2. 日志文件的管理 一旦将日志写入文件后续就要对日志文件进行管理比如日志文件的轮转、压缩、归档以及定期清理(腾出磁盘空间)等。 关于如何对日志文件管理的方案大致有这么几种。 第一种是借助外部工具比如在主流的Linux发行版上都有一个logrotate[5]工具程序应用程序可以借助该工具对应用输出的日志进行rotate、压缩、归档和删除历史归档日志这样可大幅简化应用的日志输出逻辑应用仅需要将日志输出到一个具名文件中即可其余都交给logrotate处理。关于如何使用logrotate我在《写Go代码时遇到的那些问题[第1期]》[6]中有详细说明感兴趣的朋友可以移步阅读一下这里就不赘述了。 第二种就是log包自身支持。大多数log包都没有将日志文件管理作为自己的功能featureslog包也是如此没有原生提供此功能。 第三种就是通过支持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.gopackage mainimport (log/sloggopkg.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核心技术并继续加强与星友的互动。欢迎大家加入 著名云主机服务厂商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微博2https://weibo.com/u/6484441286博客tonybai.comgithub: https://github.com/bigwhiteGopher Daily归档 - https://github.com/bigwhite/gopherdaily 商务合作方式撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。 参考资料 [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