日志库Zap
1、介绍
Zap提供了两种类型的日志记录器—Sugared Logger
和Logger
。
在性能很好但不是很关键的上下文中,使用SugaredLogger
。它比其他结构化日志记录包快4-10倍,并且支持结构化和printf风格的日志记录。
在每一微秒和每一次内存分配都很重要的上下文中,使用Logger
。它甚至比SugaredLogger
更快,内存分配次数也更少,但它只支持强类型的结构化日志记录。
2、logger的使用-使用默认方法
通过调用zap.NewProduction()
/zap.NewDevelopment()
或者zap.Example()
创建一个Logger。它们的区别在于记录的信息不同。production logger默认记录调用函数信息、日期和时间等。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | var logger *zap.Logger func main() { InitLogger() defer logger.Sync() simpleHttpGet( "www.google.com" ) simpleHttpGet( "http://www.google.com" ) } func InitLogger() { logger, _ = zap.NewProduction() } func simpleHttpGet(url string) { resp, err := http.Get(url) if err != nil { logger.Error( "Error fetching url.." , zap.String( "url" , url), zap.Error(err)) } else { logger.Info( "Success.." , zap.String( "statusCode" , resp.Status), zap.String( "url" , url)) resp.Body.Close() } } |
3、Sugared Logger的使用-使用默认方法
与logger的区别是,SugaredLogger
以printf
格式记录语句。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | var sugarLogger *zap.SugaredLogger func main() { InitLogger() defer sugarLogger.Sync() simpleHttpGet( "www.google.com" ) simpleHttpGet( "http://www.google.com" ) } func InitLogger() { logger, _ := zap.NewProduction() sugarLogger = logger.Sugar() } func simpleHttpGet(url string) { sugarLogger.Debugf( "Trying to hit GET request for %s" , url) resp, err := http.Get(url) if err != nil { sugarLogger.Errorf( "Error fetching URL %s : Error = %s" , url, err) } else { sugarLogger.Infof( "Success! statusCode = %s for URL %s" , resp.Status, url) resp.Body.Close() } } |
4、自定义logger的输出
1)将日志写入文件而不是终端
只需要修改上面代码的InitLogger()函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | func InitLogger() { writeSyncer := getLogWriter() encoder := getEncoder() core := zapcore.NewCore(encoder, writeSyncer, zapcore.DebugLevel) logger := zap.New(core) sugarLogger = logger.Sugar() } func getEncoder() zapcore.Encoder { return zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()) } func getLogWriter() zapcore.WriteSyncer { file, _ := os.Create( "./test.log" ) return zapcore.AddSync(file) } |
2)将JSON Encoder更改为普通的Log Encoder
将NewJSONEncoder()
更改为NewConsoleEncoder()
。
3)更改时间编码并添加调用者详细信息
修改时间编码器:
1 2 3 4 5 6 | func getEncoder() zapcore.Encoder { encoderConfig := zap.NewProductionEncoderConfig() encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder return zapcore.NewConsoleEncoder(encoderConfig) } |
4)添加将调用函数信息记录到日志中的功能,在zap.New(..)
函数中添加一个Option
:
1 | logger := zap.New(core, zap.AddCaller()) |
5)AddCallerSkip:
1 | logger := zap.New(core, zap.AddCaller(), zap.AddCallerSkip(1)) |
6)将日志输出到多个位置:
1 2 3 4 5 6 | func getLogWriter() zapcore.WriteSyncer { file, _ := os.Create( "./test.log" ) // 利用io.MultiWriter支持文件和终端两个输出目标 ws := io.MultiWriter(file, os.Stdout) return zapcore.AddSync(ws) } |
7)将err日志单独输出到文件:
1 2 3 4 5 6 7 8 9 10 11 12 | func InitLogger() { encoder := getEncoder() // test.log记录全量日志 logF, _ := os.Create( "./test.log" ) c1 := zapcore.NewCore(encoder, zapcore.AddSync(logF), zapcore.DebugLevel) // test.err.log记录ERROR级别的日志 errF, _ := os.Create( "./test.err.log" ) c2 := zapcore.NewCore(encoder, zapcore.AddSync(errF), zap.ErrorLevel) // 使用NewTee将c1和c2合并到core core := zapcore.NewTee(c1, c2) logger = zap.New(core, zap.AddCaller()) } |
完整代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | package main import ( "go.uber.org/zap/zapcore" "io" "net/http" "os" ) import ( "go.uber.org/zap" ) var sugarLogger *zap.SugaredLogger func main() { InitLogger() defer sugarLogger.Sync() simpleHttpGet( "www.google.com" ) simpleHttpGet( "http://www.google.com" ) } func InitLogger() { writeSyncer := getLogWriter() encoder := getEncoder() core := zapcore.NewCore(encoder, writeSyncer, zapcore.DebugLevel) logger := zap.New(core, zap.AddCaller(), zap.AddCallerSkip(1)) sugarLogger = logger.Sugar() } func getEncoder() zapcore.Encoder { encoderConfig := zap.NewProductionEncoderConfig() encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder return zapcore.NewConsoleEncoder(encoderConfig) } func getLogWriter() zapcore.WriteSyncer { file, _ := os.Create( "./test.log" ) // 利用io.MultiWriter支持文件和终端两个输出目标 ws := io.MultiWriter(file, os.Stdout) return zapcore.AddSync(ws) } func simpleHttpGet(url string) { resp, err := http.Get(url) if err != nil { sugarLogger.Error( "Error fetching url.." , zap.String( "url" , url), zap.Error(err)) } else { sugarLogger.Info( "Success.." , zap.String( "statusCode" , resp.Status), zap.String( "url" , url)) resp.Body.Close() } } |
参考:在Go语言项目中使用Zap日志库 | 李文周的博客 (liwenzhou.com)
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战