zap是Uber开发的非常快的、结构化的,分日志级别的Go日志库。根据Uber-goZap的文档,它的性能比类似的结构化日志包更好,也比标准库更快。具体的性能测试可以去github上看到。
github地址:
参考:go语言中文文档:
创建实例通过调用()/()或者()创建一个Logger。这三个方法的区别在于它将记录的信息不同,参数只能是string类型
//代码varlog*=()log,_:=()log,_:=()("ThisisaDEBUGmessage")("ThisisanINFOmessage")//Example输出{"level":"debug","msg":"ThisisaDEBUGmessage"}{"level":"info","msg":"ThisisanINFOmessage"}//Development输出2018-10-30T17:14:22.459+0800DEBUGdevelopment/:7ThisisaDEBUGmessage2018-10-30T17:14:22.459+0800INFOdevelopment/:8ThisisanINFOmessage//Production输出{"level":"info","ts":1540891173.3190675,"caller":"production/:8","msg":"ThisisanINFOmessage"}{"level":"info","ts":1540891173.3191047,"caller":"production/:9","msg":"ThisisanINFOmessagewithfields","region":["us-west"],"id":2}三种创建方式对比:
Example和Production使用的是json格式输出,Development使用行的形式输出
Development从警告级别向上打印到堆栈中来跟踪始终打印包/文件/行(方法)在行尾添加任何额外字段作为json字符串以大写形式打印级别名称以毫秒为单位打印ISO8601格式的时间戳
Production调试级别消息不记录Error,Dpanic级别的记录,会在堆栈中跟踪文件,Warn不会始终将调用者添加到文件中以时间戳格式打印日期以小写形式打印级别名称
格式化输出zap有两种类型,分别是*和*,它们惟一的区别是,我们通过调用主logger的.Sugar()方法来获取一个SugaredLogger,然后使用SugaredLogger以printf格式记录语句,例如
varsugarLogger*(){logger,_:=()sugarLogger=()}funcmain(){InitLogger()()("ErrorfetchingURL%s:Error=%s",url,err)}写入文件默认情况下日志都会打印到应用程序的console界面,但是为了方便查询,可以将日志写入文件,但是我们不能再使用前面创建实例的3个方法,而是使用()
packagemainimport("/zap""/zap/zapcore""os")varlog*(){writeSyncer,_:=("./")//日志文件存放目录encoderConfig:=()//指定时间格式==:=(encoderConfig)//获取编码器,NewJSONEncoder()输出json格式,NewConsoleEncoder()输出普通文本格式core:=(encoder,writeSyncer,)//第三个及之后的参数为写入文件的日志级别,ErrorLevel模式只记录error级别的日志log=(core,())//AddCaller()为显示文件名和行号("helloworld")("helloworld")}日志文件输出结果:
2020-12-16T17:53:30.466+0800INFOgeth/:18helloworld2020-12-16T17:53:30.486+0800ERRORgeth/:19helloworld同时输出控制台和文件
如果需要同时输出控制台和文件,只需要改造一下即可,示例:
packagemainimport("/natefinch/lumberjack""/zap""/zap/zapcore""os")varlog*(){//获取编码器,NewJSONEncoder()输出json格式,NewConsoleEncoder()输出普通文本格式encoderConfig:=()=//指定时间格式=:=(encoderConfig)//文件writeSyncerfileWriteSyncer:=({Filename:"./",//日志文件存放目录MaxSize:1,//文件大小限制,单位MBMaxBackups:5,//最大保留日志文件数量MaxAge:30,//日志文件保留天数Compress:false,//是否压缩处理})fileCore:=(encoder,(fileWriteSyncer,()),)//第三个及之后的参数为写入文件的日志级别,ErrorLevel模式只记录error级别的日志log=(fileCore,())//AddCaller()为显示文件名和行号("helloworld")("helloworld")}文件切割日志文件会随时间越来越大,为了避免日志文件把硬盘空间占满,需要按条件对日志文件进行切割,zap包本身不提供文件切割的功能,但是可以用zap官方推荐的lumberjack包处理
//文件writeSyncerfileWriteSyncer:=({Filename:"./",//日志文件存放目录,如果文件夹不存在会自动创建MaxSize:1,//文件大小限制,单位MBMaxBackups:5,//最大保留日志文件数量MaxAge:30,//日志文件保留天数Compress:false,//是否压缩处理})按级别写入文件为了管理人员的查询方便,一般我们需要将低于error级别的放到,error及以上严重级别日志存放到文件中,我们只需要改造一下方法的第3个参数,然后将文件WriteSyncer拆成info和error两个即可,示例:
packagemainimport("/natefinch/lumberjack""/zap""/zap/zapcore""os")varlog*(){varcoreArr[]//获取编码器encoderConfig:=()//NewJSONEncoder()输出json格式,NewConsoleEncoder()输出普通文本格式=//指定时间格式=//按级别显示不同颜色,不需要的话取值就可以了//=//显示完整文件路径encoder:=(encoderConfig)//日志级别highPriority:=(func()bool{//error级别returnlev=})lowPriority:=(func()bool{//info和debug级别,debug级别是最低的=})//info文件writeSyncerinfoFileWriteSyncer:=({Filename:"./log/",//日志文件存放目录,如果文件夹不存在会自动创建MaxSize:1,//文件大小限制,单位MBMaxBackups:5,//最大保留日志文件数量MaxAge:30,//日志文件保留天数Compress:false,//是否压缩处理})infoFileCore:=(encoder,(infoFileWriteSyncer,()),lowPriority)//第三个及之后的参数为写入文件的日志级别,ErrorLevel模式只记录error级别的日志//error文件writeSyncererrorFileWriteSyncer:=({Filename:"./log/",//日志文件存放目录MaxSize:1,//文件大小限制,单位MBMaxBackups:5,//最大保留日志文件数量MaxAge:30,//日志文件保留天数Compress:false,//是否压缩处理})errorFileCore:=(encoder,(errorFileWriteSyncer,()),highPriority)//第三个及之后的参数为写入文件的日志级别,ErrorLevel模式只记录error级别的日志coreArr=app(coreArr,infoFileCore)coreArr=app(coreArr,errorFileCore)log=((coreArr),())//()为显示文件名和行号,可省略("helloinfo")("hellodebug")("helloerror")}这样修改之后,info和debug级别的日志就存放到,error级别的日志单独放到文件中了
控制台按级别显示颜色指定编码器的EncodeLevel即可,
//获取编码器encoderConfig:=()//NewJSONEncoder()输出json格式,NewConsoleEncoder()输出普通文本格式=//指定时间格式=//按级别显示不同颜色,不需要的话取值就可以了encoder:=(encoderConfig)显示文件路径和行号
前面说到要显示文件路径和行号,只需要方法添加参数()即可,如果要显示完整的路径,需要在编码器配置中指定
//获取编码器encoderConfig:=()//NewJSONEncoder()输出json格式,NewConsoleEncoder()输出普通文本格式=//指定时间格式=//按级别显示不同颜色,不需要的话取值就可以了=//显示完整文件路径encoder:=(encoderConfig)完整代码
packagemainimport("/natefinch/lumberjack""/zap""/zap/zapcore""os")varlog*(){varcoreArr[]//获取编码器encoderConfig:=()//NewJSONEncoder()输出json格式,NewConsoleEncoder()输出普通文本格式=//指定时间格式=//按级别显示不同颜色,不需要的话取值就可以了//=//显示完整文件路径encoder:=(encoderConfig)//日志级别highPriority:=(func()bool{//error级别returnlev=})lowPriority:=(func()bool{//info和debug级别,debug级别是最低的=})//info文件writeSyncerinfoFileWriteSyncer:=({Filename:"./log/",//日志文件存放目录,如果文件夹不存在会自动创建MaxSize:2,//文件大小限制,单位MBMaxBackups:100,//最大保留日志文件数量MaxAge:30,//日志文件保留天数Compress:false,//是否压缩处理})infoFileCore:=(encoder,(infoFileWriteSyncer,()),lowPriority)//第三个及之后的参数为写入文件的日志级别,ErrorLevel模式只记录error级别的日志//error文件writeSyncererrorFileWriteSyncer:=({Filename:"./log/",//日志文件存放目录MaxSize:1,//文件大小限制,单位MBMaxBackups:5,//最大保留日志文件数量MaxAge:30,//日志文件保留天数Compress:false,//是否压缩处理})errorFileCore:=(encoder,(errorFileWriteSyncer,()),highPriority)//第三个及之后的参数为写入文件的日志级别,ErrorLevel模式只记录error级别的日志coreArr=app(coreArr,infoFileCore)coreArr=app(coreArr,errorFileCore)log=((coreArr),())//()为显示文件名和行号,可省略("helloinfo")("hellodebug")("helloerror")}