您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > Go语言

Go 语言怎么使用 Zap 日志库?

时间:2023-02-13 15:31:59  来源:51CTO  作者:frank
本文我们通过在 Gin 构建的应用中,使用 Zap 记录请求日志,介绍了 Zap 的使用方式,最后还通过 lumberjack 日志切割库进行切割日志。

​1、介绍

我们在之前的文章中介绍过标准库 log 包的使用方式,它虽然使用方便,但是它支持的功能比较简单。

本文我们介绍 uber 开源的日志库 zap​,首先使用 Gin 框架构建一个 Web 应用,然后通过在该 Web 应用中记录日志,来介绍 zap 的使用方式。

最后,我们再使用开源的日志切割库 lumberjack,进行日志切割。

2、使用 Gin 构建一个 Web 应用

本文重点不是介绍 gin 框架的使用方式,所以我们仅使用 gin 框架构建一个简单的 Web 应用,代码如下:

 
func main() {
 r := gin.Default()
 r.GET("/ping", ping)
 r.Run()
}

func ping(c *gin.Context) {
 c.JSON(http.StatusOK, gin.H{
  "message": "pong",
 })
}

阅读上面这段代码,访问 http://127.0.0.1:8080/ping​,返回结果是 {"message":"pong"}。

然后,我们使用 zap​ 记录 ping 函数的请求日志。

3、Gin 框架使用 zap 日志库

Zap 支持两种模式,分别是 SugaredLogger​ 和 Logger​,其中 SugaredLogger​ 模式比 Logger 模式执行速度更快。

SugaredLogger 模式

使用 Zap 日志库,首先需要使用 New​ 函数创建一个 Logger,代码如下:

 
func New(core zapcore.Core, options ...Option) *Logger

使用 New​ 函数,接收一个 zapcore.Core​ 类型的参数和一个 Option​ 类型的可选参数,返回一个 *Logger。

其中 zap.Core​ 类型的参数,可以使用 NewCore​ 函数创建,接收三个参数,分别是 zapcore.Encoder​ 类型,zapcore.WriteSyncer​ 类型和 zapcore.LevelEnabler 类型,分别用于指定日志格式、日志路径和日志级别。

 
func NewCore(enc Encoder, ws WriteSyncer, enab LevelEnabler) Core

其中 zapcore.Encoder​ 类型的参数,可以使用 NewProductionEncoderConfig 函数创建,返回一个用于生产环境的固定日志编码配置。

 
// NewProductionEncoderConfig returns an opinionated EncoderConfig for
// production environments.
func NewProductionEncoderConfig() zapcore.EncoderConfig {
 return zapcore.EncoderConfig{
  TimeKey:        "ts",
  LevelKey:       "level",
  NameKey:        "logger",
  CallerKey:      "caller",
  FunctionKey:    zapcore.OmitKey,
  MessageKey:     "msg",
  StacktraceKey:  "stacktrace",
  LineEnding:     zapcore.DefaultLineEnding,
  EncodeLevel:    zapcore.LowercaseLevelEncoder,
  EncodeTime:     zapcore.EpochTimeEncoder,
  EncodeDuration: zapcore.SecondsDurationEncoder,
  EncodeCaller:   zapcore.ShortCallerEncoder,
 }
}

我们可以修改任意配置选项的值。

其中 zapcore.WriteSyncer​ 类型的参数,可以使用 AddSync​ 函数创建,该函数接收一个 io.Writer 类型的参数。

 
func AddSync(w io.Writer) WriteSyncer

其中 zapcore.LevelEnabler​ 类型的参数,可以使用 zapcore​ 包定义的常量 zapcore.DebugLevel​,该常量是 zapcore.Level​ 类型,并且 zapcore.Level​ 类型实现了 zapcore.LevelEnabler 接口。

完整代码:

 
var sugaredLogger *zap.SugaredLogger

func main() {
 InitLogger()
 defer sugaredLogger.Sync()
 r := gin.Default()
 r.GET("/ping", ping)
 r.Run()
}

func ping(c *gin.Context) {
 sugaredLogger.Debug("call func ping")
 c.JSON(http.StatusOK, gin.H{
  "message": "pong",
 })
}

func InitLogger() {
 core := zapcore.NewCore(enc(), ws(), enab())
 logger := zap.New(core)
 sugaredLogger = logger.Sugar()
}

func enc() zapcore.Encoder {
 cfg := zap.NewProductionEncoderConfig()
 cfg.TimeKey = "time"
 cfg.EncodeTime = zapcore.TimeEncoderOfLayout("2006-01-02 15:04:05")
 return zapcore.NewJSONEncoder(cfg)
}

func ws() zapcore.WriteSyncer {
 logFileName := fmt.Sprintf("./%v.log", time.Now().Format("2006-01-02"))
 logFile, err := os.Create(logFileName)
 if err != nil {
  log.Fatal(err)
 }
 return zapcore.AddSync(logFile)
}

func enab() zapcore.LevelEnabler {
 return zapcore.DebugLevel
}

运行程序,执行 curl http://127.0.0.1:8080/ping。

可以看到,生成的日志文件 xxx.log​,文件中是 json 格式的日志内容,我们可以根据实际需求修改为其他格式。

开发中,可能我们希望日志可以同时输出到日志文件和终端中,可以使用函数 NewMultiWriteSyncer,代码如下:

 
func wsV2() zapcore.WriteSyncer {
 return zapcore.NewMultiWriteSyncer(ws(), zapcore.AddSync(os.Stdout))
}

除了使用 zap.New()​ 创建 Logger​ 之外,Zap 还提供了开箱即用的三种创建 Logger​ 的方式,分别是函数 NewProduction,NewDevelopment​ 和 Example(),感兴趣的读者朋友们,可以试用一下。

Logger 模式

接下来,我们简单介绍一下 Logger​ 模式,它主要用于性能和类型安全比较重要的场景中,但是,它没有 SugaredLogger 模式简单易用,我们可以根据实际场景选择使用哪种模式。

我们修改一下现有代码,新创建 InitLoggerV2​ 函数,其中 enc,ws​ 和 enab​ 函数的代码与 SugaredLogger 模式保持一致。

 
var loggerV2 *zap.Logger

func main() {
 InitLoggerV2()
 defer loggerV2.Sync()
 r := gin.Default()
 r.GET("/ping", ping)
 r.Run()
}

func ping(c *gin.Context) {
 loggerV2.Debug("call func ping", zap.Int("code", 200))
 c.JSON(http.StatusOK, gin.H{
  "message": "pong",
 })
}

func InitLoggerV2() {
 core := zapcore.NewCore(enc(), ws(), enab())
 loggerV2 = zap.New(core)
}

阅读上面这段代码,我们可以发现,在使用 zap 记录日志时,我们需要显示指定数据类型,一般用于性能和类型安全比较重要的场景中。

4、zap 日志库使用 lumberjack 库进行日志切割

Zap 日志库也不支持日志切割的功能,我们可以使用 lumberjack​ 日志切割库进行日志切割,关于 lumberjack 库的使用方式,我们在之前的文章介绍过,此处不再重复介绍,直接上代码:

 
func wsV3() zapcore.WriteSyncer {
 logFileName := fmt.Sprintf("./%v.log", time.Now().Format("2006-01-02"))
 lumberjackLogger := &lumberjack.Logger{
  Filename:   logFileName,
  MaxSize:    1,
  MaxBackups: 3,
  MaxAge:     28,
  Compress:   false,
 }
 return zapcore.AddSync(lumberjackLogger)
}

lumberjack.Logger 的字段含义:

  • Filename 日志保存文件路径
  • MaxSize 日志文件大小,单位是 MB
  • MaxBackups 保留的日志文件数量
  • MaxAge 日志文件的最长保留时间,单位是天
  • Compress 日志文件是否需要压缩

5、总结

本文我们通过在 Gin 构建的应用中,使用 Zap 记录请求日志,介绍了 Zap 的使用方式,最后还通过 lumberjack 日志切割库进行切割日志。

参考资料:

  1. https://Github.com/uber-go/zap
  2. https://pkg.go.dev/go.uber.org/zap


Tags:Go   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
Go Gin框架实现优雅地重启和停止
在Web应用程序中,有时候我们需要重启或停止服务器,无论是因为更新代码还是进行例行维护。在这种情景下,我们需要保证应用程序的可用性和数据的一致性。这就需要优雅地关闭和重...【详细内容】
2024-01-30  Search: Go  点击:(70)  评论:(0)  加入收藏
Go 内存优化与垃圾收集
Go提供了自动化的内存管理机制,但在某些情况下需要更精细的微调从而避免发生OOM错误。本文将讨论Go的垃圾收集器、应用程序内存优化以及如何防止OOM(Out-Of-Memory)错误。Go...【详细内容】
2024-01-15  Search: Go  点击:(64)  评论:(0)  加入收藏
PHP+Go 开发仿简书,实战高并发高可用微服务架构
来百度APP畅享高清图片//下栽のke:chaoxingit.com/2105/PHP和Go语言结合,可以开发出高效且稳定的仿简书应用。在实现高并发和高可用微服务架构时,我们可以采用一些关键技术。首...【详细内容】
2024-01-14  Search: Go  点击:(120)  评论:(0)  加入收藏
Go 语言不支持并发读写 Map,为什么?
Go语言的map类型不支持并发读写的主要原因是并发读写会导致数据竞态(data race),这意味着多个 goroutine 可能同时访问并修改同一个 map,从而引发不确定的结果。在Go语言的设计...【详细内容】
2024-01-05  Search: Go  点击:(83)  评论:(0)  加入收藏
Go 语言为什么建议多使用切片,少使用数组?
01 、介绍在 Go 语言中,数组固定长度,切片可变长度;数组和切片都是值传递,因为切片传递的是指针,所以切片也被称为“引用传递”。读者朋友们在使用 Go 语言开发项目时,或者在阅读...【详细内容】
2023-12-27  Search: Go  点击:(136)  评论:(0)  加入收藏
Go 语言使用 Echo 构建高性能 Web 应用
Echo提供了一个高性能且易用的框架,用于构建Go语言编写的Web应用。它具备灵活的路由功能、方便的请求处理、强大的中间件支持和简单的JSON操作,非常适合快速开发API服务和Web...【详细内容】
2023-12-26  Search: Go  点击:(137)  评论:(0)  加入收藏
Go 框架 Beego 真的有那么差劲吗
Beego 提供了一个完整的 MVC 框架,用于构建 Go 语言编写的 Web 应用。通过上述步骤,你可以设置模型、控制器、视图和路由来构建一个简单的 Beego 应用。Beego 的自动化工具和...【详细内容】
2023-12-26  Search: Go  点击:(132)  评论:(0)  加入收藏
Go 中 Goroutines 轻量级并发
并发是现代软件开发的一个基本概念,使程序能够同时执行多个任务。在 Go 编程领域,理解 Goroutines 是至关重要的。本文将全面概述 Goroutines,它们的轻量级特性,如何使用 go 关...【详细内容】
2023-12-22  Search: Go  点击:(147)  评论:(0)  加入收藏
如何使用 templ 在 Go 中编写 HTML 用户界面?
简介templ[1] 是一个在 Go 中编写 HTML 用户界面的语言。使用 templ,我们可以创建可呈现 HTML 片段的组件,并将它们组合起来创建屏幕、页面、文档或应用程序。安装我们可以通...【详细内容】
2023-12-21  Search: Go  点击:(174)  评论:(0)  加入收藏
Go 语言中并发的威力
发挥效率和响应能力并发是现代软件开发中的一个基本概念,它使程序能够同时执行多个任务,提高效率和响应能力。在本文中,我们将探讨并发在现代软件开发中的重要性,并深入了解 Go...【详细内容】
2023-12-21  Search: Go  点击:(118)  评论:(0)  加入收藏
▌简易百科推荐
宝藏级Go语言开源项目——教你自己动手开发互联网搜索引擎
DIYSearchEngine 是一个能够高速采集海量互联网数据的开源搜索引擎,采用 Go 语言开发。Github 地址:https://github.com/johnlui/DIYSearchEngine运行方法首先,给自己准备一杯...【详细内容】
2024-03-12  OSC开源社区    Tags:Go语言   点击:(29)  评论:(0)  加入收藏
Go Gin框架实现优雅地重启和停止
在Web应用程序中,有时候我们需要重启或停止服务器,无论是因为更新代码还是进行例行维护。在这种情景下,我们需要保证应用程序的可用性和数据的一致性。这就需要优雅地关闭和重...【详细内容】
2024-01-30  源自开发者  微信公众号  Tags:Go   点击:(70)  评论:(0)  加入收藏
如何让Go程序以后台进程或daemon方式运行
本文探讨了如何通过Go代码实现在后台运行的程序。最近我用Go语言开发了一个WebSocket服务,我希望它能在后台运行,并在异常退出时自动重新启动。我的整体思路是将程序转为后台...【详细内容】
2024-01-26  Go语言圈  微信公众号  Tags:Go程序   点击:(61)  评论:(0)  加入收藏
深入Go底层原理,重写Redis中间件实战
Go语言以其简洁、高效和并发性能而闻名,深入了解其底层原理可以帮助我们更好地利用其优势。在本文中,我们将探讨如何深入Go底层原理,以及如何利用这些知识重新实现一个简单的Re...【详细内容】
2024-01-25  547蓝色星球    Tags:Go   点击:(74)  评论:(0)  加入收藏
Go 内存优化与垃圾收集
Go提供了自动化的内存管理机制,但在某些情况下需要更精细的微调从而避免发生OOM错误。本文将讨论Go的垃圾收集器、应用程序内存优化以及如何防止OOM(Out-Of-Memory)错误。Go...【详细内容】
2024-01-15  DeepNoMind  微信公众号  Tags:Go   点击:(64)  评论:(0)  加入收藏
Go函数指针是如何让你的程序变慢的?
导读Go 语言的常规优化手段无需赘述,相信大家也能找到大量的经典教程。但基于 Go 的函数值问题,业界还没有太多深度讨论的内容分享。本文作者根据自己对 Go 代码的使用与调优...【详细内容】
2024-01-15  腾讯云开发者  微信公众号  Tags:Go函数   点击:(91)  评论:(0)  加入收藏
Go编程中调用外部命令的几种场景
在很多场合, 使用Go语言需要调用外部命令来完成一些特定的任务, 例如: 使用Go语言调用Linux命令来获取执行的结果,又或者调用第三方程序执行来完成额外的任务。在go的标准库...【详细内容】
2024-01-09  suntiger    Tags:Go编程   点击:(116)  评论:(0)  加入收藏
Go 语言不支持并发读写 Map,为什么?
Go语言的map类型不支持并发读写的主要原因是并发读写会导致数据竞态(data race),这意味着多个 goroutine 可能同时访问并修改同一个 map,从而引发不确定的结果。在Go语言的设计...【详细内容】
2024-01-05  Go语言圈  微信公众号  Tags:Go 语言   点击:(83)  评论:(0)  加入收藏
Go微服务入门到容器化实践
Go微服务入门到容器化实践Go 是一门高效、现代化、快速增长的编程语言,非常适合构建 Web 应用程序。而 Docker 是一种轻量级的容器化技术,能够使得您的应用程序在任何地方运行...【详细内容】
2024-01-01  大雷家吃饭    Tags:Go微服务   点击:(69)  评论:(0)  加入收藏
你是否想知道如何应对高并发?Go语言为你提供了答案!
并发编程是当前软件领域中不可忽视的一个关键概念。随着CPU等硬件的不断发展,我们都渴望让我们的程序运行速度更快、更快。而Go语言在语言层面天生支持并发,充分利用现代CPU的...【详细内容】
2023-12-29  灵墨AI探索室  微信公众号  Tags:Go语言   点击:(114)  评论:(0)  加入收藏
站内最新
站内热门
站内头条