1。上一篇介绍了标准库日志包的使用。虽然使用方便,但支持的功能比较简单。在这篇文章中,我们介绍了uber的开源日志库zap。首先我们使用Gin框架搭建一个web应用,然后通过在web应用中记录日志来介绍如何使用zap。最后我们使用开源日志切割库lumberjack进行日志切割。2.使用Gin构建web应用本文的重点不是介绍如何使用gin框架,所以我们只使用gin框架构建一个简单的web应用,代码如下:funcmain(){r:=gin.Default()r.GET("/ping",ping)r.Run()}funcping(c*gin.Context){c.JSON(http.StatusOK,gin.H{"消息":"pong",})}阅读上面这段代码,访问http://127.0.0.1:8080/ping,返回结果为{"message":"pong"}。然后,我们使用zap来记录ping功能的请求日志。3、Gin框架使用zap日志库。Zap支持两种模式,分别是SugaredLogger和Logger。SugaredLogger模式比Logger模式执行得更快。SugaredLogger模式使用Zap日志库。首先,您需要使用New函数创建一个Logger。代码如下:funcNew(corezapcore.Core,options...Option)*Logger使用New函数,接收一个zapcore.Core类型的参数和一个Option类型的可选参数,返回一个*Logger。其中,zap.Core类型的参数可以使用NewCore函数创建,接收三个参数,分别是zapcore.Encodertype、zapcore.WriteSyncertype和zapcore.LevelEnabler类型,分别用于指定日志格式、日志路径和日志级别。funcNewCore(encEncoder,wsWriteSyncer,enabLevelEnabler)Core,其中zapcore.Encoder类型参数可以使用NewProductionEncoderConfig函数创建,返回生产环境的固定日志编码配置。//NewProductionEncoderConfig为//生产环境返回一个固定的编码器配置。funcNewProductionEncoderConfig()zapcore.EncoderConfig{returnzapcore.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.WriteSyncer类型的参数可以使用AddSync函数创建,该函数接收一个io.Writer类型的参数。funcAddSync(wio.Writer)WriteSyncer其中zapcore.LevelEnabler类型参数可以使用zapcore包定义的常量zapcore.DebugLevel,是zapcore.Level类型,zapcore.Level类型实现了zapcore。LevelEnabler接口。完整代码:varsugaredLogger*zap.SugaredLoggerfuncmain(){InitLogger()defersugaredLogger.Sync()r:=gin.Default()r.GET("/ping",ping)r.Run()}funcping(c*gin.Context){sugaredLogger.Debug("callfuncping")c.JSON(http.StatusOK,gin.H{"message":"pong",})}funcInitLogger(){core:=zapcore.NewCore(enc(),ws(),enab())logger:=zap.New(core)sugaredLogger=logger.Sugar()}funcenc()zapcore.Encoder{cfg:=zap.NewProductionEncoderConfig()cfg.TimeKey="时间"cfg.EncodeTime=zapcore.TimeEncoderOfLayout("2006-01-0215:04:05")返回zapcore.NewJONEncoder(cfg)}funcws()zapcore.WriteSyncer{logFileName:=fmt.Sprintf("./%v.log",time.Now().Format("2006-01-02"))logFile,err:=os.Create(logFileName)iferr!=nil{log.Fatal(err)}返回zapcore.AddSync(logFile)}funcenab()zapcore.LevelEnabler{returnzapcore.DebugLevel}运行程序,执行curlhttp://127.0.0.1:8080/ping。可以看到生成的日志文件xxx.log中包含了json格式的日志内容,我们可以根据实际需要修改为其他格式。在开发过程中,我们可能希望将日志同时输出到日志文件和终端。我们可以使用函数NewMultiWriteSyncer,代码如下:funcwsV2()zapcore.WriteSyncer{returnzapcore.NewMultiWriteSyncer(ws(),zapcore.AddSync(os.Stdout))}除了使用zap.New()为了创建Logger,Zap还提供了三种开箱即用的方式来创建Logger,分别是函数NewProduction、NewDevelopment和Example(),感兴趣的读者小伙伴们可以尝试一下。Logger模式接下来简单介绍一下Logger模式,主要用于对性能和类型安全比较看重的场景。但是,它不像SugaredLogger模式那样易于使用。我们可以根据实际场景选择使用哪种模式。我们修改现有代码,新建一个InitLoggerV2函数,其中enc、ws和enab函数的代码与SugaredLogger模式一致。varloggerV2*zap.Loggerfuncmain(){InitLoggerV2()deferloggerV2.Sync()r:=gin.Default()r.GET("/ping",ping)r.Run()}funcping(c*gin.Context){loggerV2.Debug("callfuncping",zap.Int("code",200))c.JSON(http.StatusOK,gin.H{"message":"pong",})}funcInitLoggerV2(){core:=zapcore.NewCore(enc(),ws(),enab())loggerV2=zap.New(core)}阅读上面的代码,我们可以发现,在使用zap进行log时,我们需要显示指定数据类型,一般用于对性能和类型安全比较看重的场景。4、zap日志库使用lumberjack库进行日志切割。Zap日志库不支持日志切割功能。我们可以使用lumberjack日志切割库进行日志切割。我们在之前的文章中介绍过lumberjack库的使用。这里不再重复介绍,直接上传代码:funcwsV3()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,}returnzapcore.AddSync(lumberjackLogger)}lumberjack.Logger字段含义:文件名logsavefilepathMaxSize日志文件大小,单位是MBMaxBackups保留的日志文件个数MaxAge日志文件最长保留时间,单位是天Compress日志文件是否需要压缩5.总结我学习了如何使用Zap,最后通过lumberjack日志切割库进行日志切割。参考资料:https://github.com/uber-go/zaphttps://pkg.go.dev/go.uber.org/zap
