Go日志管理库zap

news/2024/9/27 19:27:07

一、zap介绍

在许多Go语言项目中,我们需要一个好的日志记录器能够提供下面这些功能:

1.能够将事件记录到文件中,而不是应用程序控制台。
2.日志切割-能够根据文件大小、时间或间隔等来切割日志文件。
3.支持不同的日志级别。例如INFO,DEBUG,ERROR等。
4.能够打印基本信息,如调用文件/函数名和行号,日志时间等。

二、安装及使用

2.1 安装

go get -u go.uber.org/zap

2.2 配置logger日志记录器

Zap提供了两种类型的日志记录器—Sugared Logger和Logger,一般使用Logger 。
2.2.1 初始化Logger

func InitLogger() *zap.Logger{logger ,_ := zap.NewProduction()return logger
}

2.2.2 初始化SugaredLogger

//在Logger基础上调用logger.Suger()
func InitLogger() *zap.SugaredLogger{logger ,_ := zap.NewProduction()return logger.Sugar()
}

而初始化logger调用的函数可以通过调用zap.NewProduction()/zap.NewDevelopment()或者zap.Example()创建一个Logger。区别就是一个是以json的格式返回,一个是以终端标准输出带有空格返回。
NewProducts()
image

NewDevelopment()
image

2.3 使用logger进行日志记录

使用logger的自带的方法进行日志记录,logger.info(),logger.error().logger.debug等等
这些方法的语法都是

func (log *Logger) MethodXXX(msg string, fields ...Field) 
例如:
logger.info("msg",zap.String("msg",v),zap.Error(err),)

完整代码

点击查看代码
package mainimport ("net/http""go.uber.org/zap"
)var Logger *zap.SugaredLogger
func main() {//初始化zap日志记录器Logger = InitLogger()defer Logger.Sync()//模拟义务Simplefunc("http://www.baidu.com")Simplefunc("www.google.com")}
func InitLogger() *zap.SugaredLogger{logger ,_ := zap.NewDevelopment()return logger.Sugar()
}func Simplefunc(url string) {res,err:=http.Get(url)if err!=nil {//记录错误日志Logger.Error("http get failed..",zap.String("url:",url),zap.Error(err),)}else {//使用info记录成功日志。Logger.Info("get success",zap.String("status:",res.Status),zap.String("url:",url),)res.Body.Close()}}

2.4 自定义logger记录器

2.4.1 将日志写入文件而不是终端
上述的官方提供的logger生成功能不是那么强大,项目需要将日志记录到文件和分割 的时候就需要自定义。
zap自定义logger生成器使用zap.New():
func New(core zapcore.Core, options ...Option) *Logger
其中zapcore.Core需要设置三个参数Encoder,WriteSyncer,LogLevel
Encoder:编译器,通俗说就是输出日志是什么格式,json or 终端格式。

json格式就使用NewJSONEncoder(),并使用预先设置的ProductionEncoderConfig():
zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig())
终端格式就使用NewConsoleEncoder():
zapcore.NewConsoleEncoder(zap.NewProductionEncoderConfig())

WriteSyncer:将日志输出到哪。使用zapcore.AddSync()函数并且将打开的文件句柄传进去。

file, _ := os.Create("./test.log")
writeSyncer := zapcore.AddSync(file)

LogLevel:将什么样级别的日志输出.

代码实例:

点击查看代码
//使用自定义的zap logger
func InitLogger() *zap.SugaredLogger{//日志文件logfile, _ :=os.OpenFile("zap_log.log",os.O_APPEND | os.O_CREATE|os.O_RDWR,0666)//编码器encoder := zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig())//输出位置writeSyncer := zapcore.AddSync(logfile)//定义corecore := zapcore.NewCore(encoder,writeSyncer,zapcore.DebugLevel,)//创建loggerlogger:= zap.New(core)return logger.Sugar()
}

2.4.2 若输出到文件和终端,只需要更改WriteSyncer参数

点击查看代码
//使用自定义的zap logger
func InitLogger() *zap.SugaredLogger{//日志文件logfile, _ :=os.OpenFile("zap_log.log",os.O_APPEND | os.O_CREATE|os.O_RDWR,0666)//编码器encoder := zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig())//输出位置// writeSyncer := zapcore.AddSync(logfile)//输出多个位置wc := io.MultiWriter(logfile,os.Stdout)writeSyncer:= zapcore.AddSync(wc)//定义corecore := zapcore.NewCore(encoder,writeSyncer,zapcore.DebugLevel,)//创建loggerlogger:= zap.New(core)return logger.Sugar()
}
效果: ![image](https://img2024.cnblogs.com/blog/3452880/202409/3452880-20240912221329852-1914127797.png)

2.4.3 将输出的时间转化

//设置日志编译器,什么类型的日志
func getEncoder() zapcore.Encoder{//encoder配置encoderConfig := zap.NewProductionEncoderConfig()//设置时间格式为2024-9-1-12.32encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoderencoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder//json格式// jsonencoder := zapcore.NewJSONEncoder(encoderConfig)//终端形式ConsoleEncoder := zapcore.NewConsoleEncoder(encoderConfig)return ConsoleEncoder}

2.4.4 记录不同级别的日志
有时候日志可分为log.erro.log 记录错误级别日志,;log.success.log记录成功级别日志,zapcore.DebugLevel就全记录。

	core1 := zapcore.NewCore(encoder,writeSyncer,zapcore.DebugLevel,//全记录)//错误日志core2 :=  zapcore.NewCore(encoder,getwriteSyncer("log.err.log"),zapcore.ErrorLevel,)c:=zapcore.NewTee(core1,core2)logger:= zap.New(c,zap.AddCaller())return logger.Sugar()

2.4.5 AddCaller详细记录调用的代码行,AddCallerSkip(1)调用链很多时直接跳过

logger:= zap.New(core,zap.AddCaller(), zap.AddCallerSkip(1))

image

3. 记录全日志,错误日志文件,同步终端,标准时间,记录代码位置的自定义logger代码

点击查看代码
//使用自定义的zap logger
func InitLogger() *zap.SugaredLogger{//编码器encoder := getEncoder()//输出位置writeSyncer:= getwriteSyncer("log_all.log")//定义corecore1 := zapcore.NewCore(encoder,writeSyncer,zapcore.DebugLevel,//全记录)//错误日志core2 :=  zapcore.NewCore(encoder,getwriteSyncer("log.err.log"),zapcore.ErrorLevel,)//创建单个logger// logger:= zap.New(core1,zap.AddCaller(), zap.AddCallerSkip(1)) //AddCaller详细记录调用的代码行,AddCallerSkip(1)调用链很多时直接跳过// return logger.Sugar()//创建双日志,全日志和错误日志c:=zapcore.NewTee(core1,core2)logger:= zap.New(c,zap.AddCaller())return logger.Sugar()
}//设置日志编译器,什么类型的日志
func getEncoder() zapcore.Encoder{//encoder配置encoderConfig := zap.NewProductionEncoderConfig()//设置时间格式为2024-9-1-12.32encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoderencoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder//json格式// jsonencoder := zapcore.NewJSONEncoder(encoderConfig)//终端形式ConsoleEncoder := zapcore.NewConsoleEncoder(encoderConfig)return ConsoleEncoder}//设置输出位置
func getwriteSyncer(logfilename string) zapcore.WriteSyncer {//日志文件logfile, _ :=os.OpenFile(logfilename,os.O_APPEND | os.O_CREATE|os.O_RDWR,0666)//只输出到日志文件// return zapcore.AddSync(logfile)//也输出到终端wc := io.MultiWriter(logfile,os.Stdout)return zapcore.AddSync(wc)
}

[========]

[========]

4.使用Lumberjack进行日志切割归档

//设置输出位置
func getwriteSyncer(logfilename string) zapcore.WriteSyncer {//日志文件// logfile, _ :=os.OpenFile(logfilename,os.O_APPEND | os.O_CREATE|os.O_RDWR,0666)//分割日志l, _ := rotatelogs.New(logfilename+".%Y%m%d%H%M.log",rotatelogs.WithMaxAge(30*24*time.Hour),    // 最长保存30天rotatelogs.WithRotationTime(time.Hour*24), // 24小时切割一次)//也输出到终端wc := io.MultiWriter(l,os.Stdout)return zapcore.AddSync(wc)
}

5.上述完整代码

点击查看代码
package mainimport ("io""net/http""os""time"rotatelogs "github.com/lestrrat-go/file-rotatelogs"// "gopkg.in/natefinch/lumberjack.v2""go.uber.org/zap""go.uber.org/zap/zapcore"
)var Logger *zap.SugaredLogger
func main() {//初始化zap日志记录器Logger = InitLogger()defer Logger.Sync()//模拟义务Simplefunc("http://www.baidu.com")Simplefunc("http://www.google.com")}
//使用自定义的zap logger
func InitLogger() *zap.SugaredLogger{//编码器encoder := getEncoder()//输出位置writeSyncer:= getwriteSyncer("log_all")//定义corecore1 := zapcore.NewCore(encoder,writeSyncer,zapcore.DebugLevel,//全记录)//错误日志core2 :=  zapcore.NewCore(encoder,getwriteSyncer("log.err"),zapcore.ErrorLevel,)//创建单个logger// logger:= zap.New(core1,zap.AddCaller(), zap.AddCallerSkip(1)) //AddCaller详细记录调用的代码行,AddCallerSkip(1)调用链很多时直接跳过// return logger.Sugar()//创建双日志,全日志和错误日志c:=zapcore.NewTee(core1,core2)logger:= zap.New(c,zap.AddCaller())return logger.Sugar()
}//设置日志编译器,什么类型的日志
func getEncoder() zapcore.Encoder{//encoder配置encoderConfig := zap.NewProductionEncoderConfig()//设置时间格式为2024-9-1-12.32encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoderencoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder//json格式// jsonencoder := zapcore.NewJSONEncoder(encoderConfig)//终端形式ConsoleEncoder := zapcore.NewConsoleEncoder(encoderConfig)return ConsoleEncoder}//设置输出位置
func getwriteSyncer(logfilename string) zapcore.WriteSyncer {//日志文件// logfile, _ :=os.OpenFile(logfilename,os.O_APPEND | os.O_CREATE|os.O_RDWR,0666)//分割日志l, _ := rotatelogs.New(logfilename+".%Y%m%d%H%M.log",rotatelogs.WithMaxAge(30*24*time.Hour),    // 最长保存30天rotatelogs.WithRotationTime(time.Hour*24), // 24小时切割一次)//也输出到终端wc := io.MultiWriter(l,os.Stdout)return zapcore.AddSync(wc)
}func Simplefunc(url string) {res,err:=http.Get(url)if err!=nil {//记录错误日志Logger.Error("http get failed..",zap.String("url:",url),zap.Error(err),)}else {//使用info记录成功日志。Logger.Info("get success",zap.String("status:",res.Status),zap.String("url:",url),)res.Body.Close()}}

在gin框架中使用zap日志记录器

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/59720.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

深度神经网络DNN、RNN、RCNN及多种机器学习金融交易策略研究|附数据代码

全文链接:https://tecdat.cn/?p=37668 原文出处:拓端数据部落公众号 分析师:Aijun Zhang 在当今的金融领域,量化交易正凭借其科学性和高效性逐渐成为主流投资方式之一。随着大数据技术的蓬勃发展,量化交易借助先进的数学模型和计算机分析能力,摒弃了人的主观判断,通过…

mybatis exists 中使用代替in关键字

使用场景,in适合数据量小的时候,exists适合数据量大的时候。<if test="torqueRecordPageDTO.vinList != null and torqueRecordPageDTO.vinList.size >0">and exists (select 1 from (<foreach collection="torqueRecordPageDTO.vinList" it…

图与网络——TSP问题精解

旅行商问题(Travelling Salesman Problem, TSP)是组合优化领域中的经典问题之一。TSP的概念最早可以追溯到18世纪,瑞士数学家欧拉在解决柯尼斯堡七桥问题时首次提出了关于图中遍历的问题。不过,作为一个优化问题,TSP在19世纪才开始形成系统的研究。1920年代,TSP被德国数学…

jackson 反序列化学习

jackson 反序列化学习 jackson 介绍 Jackson 是一个用于处理 JSON 数据的开源 Java 库。Spring MVC 的默认 json 解析器便是 Jackson。 Jackson 优点很多。 Jackson 所依赖的 jar 包较少,简单易用。与其他 Java 的 json 的框架 Gson 等相比, Jackson 解析大的 json 文件速度比…

LeetCode算法—递归

纵有疾风起;人生不言弃!一:递归 1、定义:函数直接或者间接的调用自己 2、四个要素 (1)接受的参数 (2)返回的值 (3)终止条件 (4)如何拆解 二:LeetCode 509 斐波那契数列 def func(n):if n<2:return nelse:return func(n-1)+func(n-2)n=int(input()) print(func(…

2024年9月最新Youtube转WAV高质量音频最新教程

​1.利用在线转换工具(最推荐的一种方式): YoutubeToWAV:打开浏览器,访问 https://www.youtubetowav.cc/的官方网站。在 YouTube 网站上找到您想要转换的视频,复制该视频的链接。回到网页,将复制的 YouTube 视频链接粘贴到指定的输入框中。点击Convert默认为audio标签的格…

[GDOUCTF 2023]ez_ze!

这题是一个jinja2的ssti模板注入,经过测试过滤了 _ {{}} . [] os popen getitem 输入{% print(lipsum|string|list) %}或者{% print(config|string|list) %}从这里面获取我们需要的字符 获取下划线和空格 {% set pop=dict(pop=1)|join %} {% set xia=(lipsum|string|list)|at…

java方法:什么是方法?

java方法是语句的集合,它们在一起执行一个功能:方法是解决一类问题的步骤的有序组合 方法包含于类或对象中 方法在程序中被创建,在其他地方被引用 例如:即 ______()是方法 设计方法的原则:方法的本意时功能块,就是实现某个功能块,就是实现某个功能的语句块的集合,所以…