Use of golang high-performance log library zap

Author: Chen Jinjian
personal blog: HTTPS: //jian1098.github.io
CSDN blog: https: //blog.csdn.net/c_jian
Jane book: https: //www.jianshu.com/u/8ba9ac5706b6
Contact: jian1098 @qq.com

Summary

zapIt is Ubera very fast, structured, and log-level Go log library developed. According to the documentation of Uber-go Zap, its performance is better than similar structured log packages and faster than the standard library. The specific performance test can go githubto see.

github address:https://github.com/uber-go/zap

Create an instance

By calling zap.NewProduction()/ zap.NewDevelopment()or zap.Example()creating a Logger. The difference between these three methods is that it will record different information, and the parameters can only be stringtypes

//代码
var log *zap.Logger
log = zap.NewExample()
log, _ := zap.NewDevelopment()
log, _ := zap.NewProduction()
log.Debug("This is a DEBUG message")
log.Info("This is an INFO message")

//Example 输出
{
    
    "level":"debug","msg":"This is a DEBUG message"}
{
    
    "level":"info","msg":"This is an INFO message"}

//Development 输出
2018-10-30T17:14:22.459+0800    DEBUG    development/main.go:7    This is a DEBUG message
2018-10-30T17:14:22.459+0800    INFO    development/main.go:8    This is an INFO message

//Production 输出
{
    
    "level":"info","ts":1540891173.3190675,"caller":"production/main.go:8","msg":"This is an INFO message"}
{
    
    "level":"info","ts":1540891173.3191047,"caller":"production/main.go:9","msg":"This is an INFO message with fields","region":["us-west"],"id":2}

Comparison of three creation methods:

  • ExampleAnd Productionuse the jsonformat output, Developmentuse the form of line output
  • Development
    • Print up to the stack from the warning level to trace
    • Always print package/file/line (method)
    • Add any extra fields at the end of the line as a json string
    • Print level name in uppercase
    • Print the time stamp in ISO8601 format in milliseconds
  • Production
    • Debug level messages are not recorded
    • Error, Dpanic level records, will trace the file in the stack, Warn will not
    • Always add the caller to the file
    • Print date in timestamp format
    • Print level name in lowercase

Formatted output

There are two types of zap, *zap.Loggerand the *zap.SugaredLoggeronly difference between them is that we . Sugar()get one by calling the main logger method SugaredLogger, and then use SugaredLoggerthe printfformat to record the statement, for example

var sugarLogger *zap.SugaredLogger

func InitLogger() {
    
    
  logger, _ := zap.NewProduction()
    sugarLogger = logger.Sugar()
}

func main() {
    
    
    InitLogger()
    defer sugarLogger.Sync()
    sugarLogger.Errorf("Error fetching URL %s : Error = %s", url, err)
}

Write file

By default, the logs will be printed to the console interface of the application, but for the convenience of querying, the logs can be written to a file, but we can no longer use the 3 methods of creating an instance, but usezap.New()

package main

import (
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"os"
)

var log *zap.Logger
func main() {
    
    
	writeSyncer, _ := os.Create("./info.log")							//日志文件存放目录
	encoderConfig := zap.NewProductionEncoderConfig()					 //指定时间格式
	encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
	encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
	encoder := zapcore.NewConsoleEncoder(encoderConfig)					//获取编码器,NewJSONEncoder()输出json格式,NewConsoleEncoder()输出普通文本格式
	core := zapcore.NewCore(encoder, writeSyncer, zapcore.DebugLevel)	 //第三个及之后的参数为写入文件的日志级别,ErrorLevel模式只记录error级别的日志
	log = zap.New(core,zap.AddCaller())								   //AddCaller()为显示文件名和行号
	log.Info("hello world")
	log.Error("hello world")
}

Log file output results:

2020-12-16T17:53:30.466+0800	INFO	geth/main.go:18	hello world
2020-12-16T17:53:30.486+0800	ERROR	geth/main.go:19	hello world

Output console and file at the same time

If you need to output the console and files at the same time, you only need to modify it zapcore.NewCore. Example:

package main

import (
	"github.com/natefinch/lumberjack"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"os"
)

var log *zap.Logger

func main() {
    
    
	//获取编码器,NewJSONEncoder()输出json格式,NewConsoleEncoder()输出普通文本格式
	encoderConfig := zap.NewProductionEncoderConfig()
	encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder //指定时间格式
	encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
	encoder := zapcore.NewConsoleEncoder(encoderConfig)

	//文件writeSyncer
	fileWriteSyncer := zapcore.AddSync(&lumberjack.Logger{
    
    
		Filename:   "./info.log", //日志文件存放目录
		MaxSize:    1,            //文件大小限制,单位MB
		MaxBackups: 5,            //最大保留日志文件数量
		MaxAge:     30,           //日志文件保留天数
		Compress:   false,        //是否压缩处理
	})
	fileCore := zapcore.NewCore(encoder, zapcore.NewMultiWriteSyncer(fileWriteSyncer,zapcore.AddSync(os.Stdout)), zapcore.DebugLevel) //第三个及之后的参数为写入文件的日志级别,ErrorLevel模式只记录error级别的日志

	log = zap.New(fileCore, zap.AddCaller()) //AddCaller()为显示文件名和行号


	log.Info("hello world")
	log.Error("hello world")
}

File cutting

Log files will grow larger and larger over time. In order to prevent log files from filling up the hard disk space, log files need to be cut according to conditions. The zap package itself does not provide the function of file cutting, but it can be lumberjackprocessed with packages recommended by zap officials.

	//文件writeSyncer
	fileWriteSyncer := zapcore.AddSync(&lumberjack.Logger{
    
    
		Filename:   "./info.log", //日志文件存放目录,如果文件夹不存在会自动创建
		MaxSize:    1,            //文件大小限制,单位MB
		MaxBackups: 5,            //最大保留日志文件数量
		MaxAge:     30,           //日志文件保留天数
		Compress:   false,        //是否压缩处理
	})

Write files by level

In order to facilitate the query of management personnel, generally we need to store the logs below the error level in the info.log, and store the logs with the severity level of error and above in the error.log file. We only need to modify zapcore.NewCorethe third parameter of the method, and then add file WriteSyncersplit into info, and errortwo to the example:

package main

import (
	"github.com/natefinch/lumberjack"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"os"
)

var log *zap.Logger

func main() {
    
    
	var coreArr []zapcore.Core

	//获取编码器
	encoderConfig := zap.NewProductionEncoderConfig()				//NewJSONEncoder()输出json格式,NewConsoleEncoder()输出普通文本格式
	encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder 			//指定时间格式
	encoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder	//按级别显示不同颜色,不需要的话取值zapcore.CapitalLevelEncoder就可以了
	//encoderConfig.EncodeCaller = zapcore.FullCallerEncoder      	//显示完整文件路径
	encoder := zapcore.NewConsoleEncoder(encoderConfig)

	//日志级别
	highPriority := zap.LevelEnablerFunc(func(lev zapcore.Level) bool{
    
    	//error级别
		return lev >= zap.ErrorLevel
	})
	lowPriority := zap.LevelEnablerFunc(func(lev zapcore.Level) bool {
    
    	//info和debug级别,debug级别是最低的
		return lev < zap.ErrorLevel && lev >= zap.DebugLevel
	})

	//info文件writeSyncer
	infoFileWriteSyncer := zapcore.AddSync(&lumberjack.Logger{
    
    
		Filename:   "./log/info.log", 	//日志文件存放目录,如果文件夹不存在会自动创建
		MaxSize:    1,            		//文件大小限制,单位MB
		MaxBackups: 5,            		//最大保留日志文件数量
		MaxAge:     30,           		//日志文件保留天数
		Compress:   false,        		//是否压缩处理
	})
	infoFileCore := zapcore.NewCore(encoder, zapcore.NewMultiWriteSyncer(infoFileWriteSyncer,zapcore.AddSync(os.Stdout)), lowPriority) //第三个及之后的参数为写入文件的日志级别,ErrorLevel模式只记录error级别的日志
	//error文件writeSyncer
	errorFileWriteSyncer := zapcore.AddSync(&lumberjack.Logger{
    
    
		Filename:   "./log/error.log", 		//日志文件存放目录
		MaxSize:    1,            			//文件大小限制,单位MB
		MaxBackups: 5,            			//最大保留日志文件数量
		MaxAge:     30,           			//日志文件保留天数
		Compress:   false,        			//是否压缩处理
	})
	errorFileCore := zapcore.NewCore(encoder, zapcore.NewMultiWriteSyncer(errorFileWriteSyncer,zapcore.AddSync(os.Stdout)), highPriority) //第三个及之后的参数为写入文件的日志级别,ErrorLevel模式只记录error级别的日志

	coreArr = append(coreArr, infoFileCore)
	coreArr = append(coreArr, errorFileCore)
	log = zap.New(zapcore.NewTee(coreArr...), zap.AddCaller()) //zap.AddCaller()为显示文件名和行号,可省略

	log.Info("hello info")
	log.Debug("hello debug")
	log.Error("hello error")
}

After this modification, infoand debuglevel log on to the store info.log, errorlevel log into a separate error.logfile in the

The console displays colors by level

Just specify the encoder EncodeLevel,

	//获取编码器
	encoderConfig := zap.NewProductionEncoderConfig()				//NewJSONEncoder()输出json格式,NewConsoleEncoder()输出普通文本格式
	encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder 			//指定时间格式
	encoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder	//按级别显示不同颜色,不需要的话取值zapcore.CapitalLevelEncoder就可以了
	encoder := zapcore.NewConsoleEncoder(encoderConfig)

Display file path and line number

As mentioned earlier, to display the file path and line number, you only need zap.Newto add parameters zap.AddCaller()to the method . If you want to display the complete path, you need to specify it in the encoder configuration

	//获取编码器
	encoderConfig := zap.NewProductionEncoderConfig()				//NewJSONEncoder()输出json格式,NewConsoleEncoder()输出普通文本格式
	encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder 			//指定时间格式
	encoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder	//按级别显示不同颜色,不需要的话取值zapcore.CapitalLevelEncoder就可以了
	encoderConfig.EncodeCaller = zapcore.FullCallerEncoder      	//显示完整文件路径
	encoder := zapcore.NewConsoleEncoder(encoderConfig)

Complete code

package main

import (
	"github.com/natefinch/lumberjack"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"os"
)

var log *zap.Logger

func main() {
    
    
	var coreArr []zapcore.Core

	//获取编码器
	encoderConfig := zap.NewProductionEncoderConfig()				//NewJSONEncoder()输出json格式,NewConsoleEncoder()输出普通文本格式
	encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder 			//指定时间格式
	encoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder	//按级别显示不同颜色,不需要的话取值zapcore.CapitalLevelEncoder就可以了
	//encoderConfig.EncodeCaller = zapcore.FullCallerEncoder      	//显示完整文件路径
	encoder := zapcore.NewConsoleEncoder(encoderConfig)

	//日志级别
	highPriority := zap.LevelEnablerFunc(func(lev zapcore.Level) bool{
    
    	//error级别
		return lev >= zap.ErrorLevel
	})
	lowPriority := zap.LevelEnablerFunc(func(lev zapcore.Level) bool {
    
    	//info和debug级别,debug级别是最低的
		return lev < zap.ErrorLevel && lev >= zap.DebugLevel
	})

	//info文件writeSyncer
	infoFileWriteSyncer := zapcore.AddSync(&lumberjack.Logger{
    
    
		Filename:   "./log/info.log", 	//日志文件存放目录,如果文件夹不存在会自动创建
		MaxSize:    2,            		//文件大小限制,单位MB
		MaxBackups: 100,            	//最大保留日志文件数量
		MaxAge:     30,           		//日志文件保留天数
		Compress:   false,        		//是否压缩处理
	})
	infoFileCore := zapcore.NewCore(encoder, zapcore.NewMultiWriteSyncer(infoFileWriteSyncer,zapcore.AddSync(os.Stdout)), lowPriority) //第三个及之后的参数为写入文件的日志级别,ErrorLevel模式只记录error级别的日志
	//error文件writeSyncer
	errorFileWriteSyncer := zapcore.AddSync(&lumberjack.Logger{
    
    
		Filename:   "./log/error.log", 		//日志文件存放目录
		MaxSize:    1,            			//文件大小限制,单位MB
		MaxBackups: 5,            			//最大保留日志文件数量
		MaxAge:     30,           			//日志文件保留天数
		Compress:   false,        			//是否压缩处理
	})
	errorFileCore := zapcore.NewCore(encoder, zapcore.NewMultiWriteSyncer(errorFileWriteSyncer,zapcore.AddSync(os.Stdout)), highPriority) //第三个及之后的参数为写入文件的日志级别,ErrorLevel模式只记录error级别的日志

	coreArr = append(coreArr, infoFileCore)
	coreArr = append(coreArr, errorFileCore)
	log = zap.New(zapcore.NewTee(coreArr...), zap.AddCaller()) //zap.AddCaller()为显示文件名和行号,可省略


	log.Info("hello info")
	log.Debug("hello debug")
	log.Error("hello error")
}

Reference article

Use the Zap log library in a Go language project-Zhihu (zhihu.com)

[ Golang high-performance log library zap configuration example-ExplorerMan-Blog Park (cnblogs.com) ] (https://zhuanlan.zhihu.com/p/88856378?utm_source=wechat_session)

Guess you like

Origin blog.csdn.net/C_jian/article/details/111315457