11.zap日志包 01.日志模块介绍
1.1 介绍 在许多Go语言项目中,我们需要一个好的日志记录器能够提供下面这些功能
能够将事件记录到文件中,而不是应用程序控制台。
日志切割-能够根据文件大小、时间或间隔等来切割日志文件。
支持不同的日志级别。例如INFO,DEBUG,ERROR等。
能够打印基本信息,如调用文件/函数名和行号,日志时间等。
1.2 默认的Go Logger
实现一个Go语言中的日志记录器非常简单——创建一个新的日志文件,然后设置它为日志的输出位置。
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 package mainimport ( "log" "net/http" "os" )func SetupLogger () { logFileLocation, _ := os.OpenFile("./test.log" , os.O_CREATE|os.O_APPEND|os.O_RDWR, 0744 ) log.SetOutput(logFileLocation) }func simpleHttpGet (url string ) { resp, err := http.Get(url) if err != nil { log.Printf("Error fetching url %s : %s" , url, err.Error()) } else { log.Printf("Status Code for %s : %s" , url, resp.Status) resp.Body.Close() } }func main () { SetupLogger() simpleHttpGet("www.baidu.com" ) simpleHttpGet("http://www.baidu.com" ) }
1.3 Go Logger的优势和劣势
优势
它最大的优点是使用非常简单。
我们可以设置任何io.Writer作为日志记录输出并向其发送要写入的日志。
劣势
仅限基本的日志级别
只有一个Print选项。不支持INFO/DEBUG等多个级别。
缺乏日志格式化的能力——例如记录调用者的函数名和行号,格式化日期和时间格式。等等。
不提供日志切割的能力。
02.zap基本使用 2.1 zap介绍
Uber-go zap优势
它同时提供了结构化日志记录和printf风格的日志记录
它非常的快
安装
1 go get -u go.uber.org/zap
1
2.2 Sugared Logger和Logger
Zap提供了两种类型的日志记录器—Sugared Logger和Logger。
在性能很好但不是很关键的上下文中,使用SugaredLogger。
它比其他结构化日志记录包快4-10倍,并且支持结构化和printf风格的日志记录。
在每一微秒和每一次内存分配都很重要的上下文中,使用Logger。
它甚至比SugaredLogger更快,内存分配次数也更少,但它只支持强类型的结构化日志记录。
2.3 zap日志记录器Logger
通过调用zap.NewProduction()/zap.NewDevelopment()或者zap.Example()创建一个Logger。
唯一的区别在于它将记录的信息不同
例如production logger默认记录调用函数信息、日期和时间等。
通过Logger调用Info/Error等。
默认情况下日志都会打印到应用程序的console界面。
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 package mainimport ( "go.uber.org/zap" "net/http" )var logger *zap.Loggerfunc 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() } }func main () { InitLogger() defer logger.Sync() simpleHttpGet("www.google.com" ) simpleHttpGet("http://www.google.com" ) }
2.4 zap日志记录器Sugared Logger 现在让我们使用Sugared Logger来实现相同的功能。
大部分的实现基本都相同。
惟一的区别是,我们通过调用主logger的. Sugar()方法来获取一个SugaredLogger。
然后使用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 25 26 27 28 29 30 31 32 33 34 35 36 37 package mainimport ( "go.uber.org/zap" "net/http" )var sugarLogger *zap.SugaredLoggerfunc 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() } }func main () { InitLogger() defer sugarLogger.Sync() simpleHttpGet("www.google.com" ) simpleHttpGet("http://www.google.com" ) }
03.定制logger 3.1 测试定制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 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 60 61 62 63 64 65 66 package mainimport ( "github.com/natefinch/lumberjack" "go.uber.org/zap" "go.uber.org/zap/zapcore" "net/http" )var sugarLogger *zap.SugaredLoggerfunc getEncoder () zapcore.Encoder { encoderConfig := zap.NewProductionEncoderConfig() encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder return zapcore.NewConsoleEncoder(encoderConfig) }func getLogWriter () zapcore.WriteSyncer { lumberJackLogger := &lumberjack.Logger{ Filename: "./test.log" , MaxSize: 1 , MaxBackups: 5 , MaxAge: 30 , Compress: false , } return zapcore.AddSync(lumberJackLogger) }func InitLogger () { writeSyncer := getLogWriter() encoder := getEncoder() core := zapcore.NewCore(encoder, writeSyncer, zapcore.DebugLevel) logger := zap.New(core, zap.AddCaller()) 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() } }func main () { InitLogger() defer sugarLogger.Sync() simpleHttpGet("www.sogo.com" ) simpleHttpGet("http://www.sogo.com" ) }