ETJava Beta | Java    注册   登录
  • 搜索:
  • Go日志管理库zap

    发表于      阅读(1)     博客类别:Crawler     转自:https://www.cnblogs.com/iruan/p/18411322
    如有侵权 请联系我们删除  (页面底部联系我们)  

    一、zap介绍

    在许多Go语言项目中,我们需要一个好的日志记录器能够提供下面这些功能:

    1.能够将事件记录到文件中,而不是应用程序控制台。
    2.日志切割-能够根据文件大小、时间或间隔等来切割日志文件。
    3.支持不同的日志级别。例如INFO,DEBUG,ERROR等。
    4.能够打印基本信息,如调用文件/函数名和行号,日志时间等。
    

    二、安装及使用

    2.1 安装

    go get -u go.uber.org/zap

    2.2 配置logger日志记录器

    Zap提供了两种类型的日志记录器—Sugared Logger和Logger,一般使用Logger 。
    2.2.1 初始化Logger

    func InitLogger() *zap.Logger{
    	logger ,_ := zap.NewProduction()
    	
    	return logger
    }
    

    2.2.2 初始化SugaredLogger

    //在Logger基础上调用logger.Suger()
    func InitLogger() *zap.SugaredLogger{
    	logger ,_ := zap.NewProduction()
    	
    	return logger.Sugar()
    }
    

    而初始化logger调用的函数可以通过调用zap.NewProduction()/zap.NewDevelopment()或者zap.Example()创建一个Logger。区别就是一个是以json的格式返回,一个是以终端标准输出带有空格返回。
    NewProducts()
    image

    NewDevelopment()
    image

    2.3 使用logger进行日志记录

    使用logger的自带的方法进行日志记录,logger.info(),logger.error().logger.debug等等
    这些方法的语法都是

    func (log *Logger) MethodXXX(msg string, fields ...Field) 
    例如:
    logger.info(
    	"msg",
    	zap.String("msg",v),
    	zap.Error(err),
    
    )
    

    完整代码

    点击查看代码
    package main
    
    import (
    	"net/http"
    
    	"go.uber.org/zap"
    )
    
    var Logger *zap.SugaredLogger
    func main() {
    	//初始化zap日志记录器
    	Logger = InitLogger()
    	defer Logger.Sync()
    	//模拟义务
    	Simplefunc("http://www.baidu.com")
    	Simplefunc("www.google.com")
    
    }
    func InitLogger() *zap.SugaredLogger{
    	logger ,_ := zap.NewDevelopment()
    	
    	return logger.Sugar()
    }
    
    func Simplefunc(url string) {
    	res,err:=http.Get(url)
    	if err!=nil {
    		//记录错误日志
    		Logger.Error(
    			"http get failed..",
    			zap.String("url:",url),
    			zap.Error(err),
    		)
    	}else {
    		//使用info记录成功日志。
    		Logger.Info(
    			"get success",
    			zap.String("status:",res.Status),
    			zap.String("url:",url),
    		)
    		res.Body.Close()
    	}
    	
    	
    }
    

    2.4 自定义logger记录器

    2.4.1 将日志写入文件而不是终端
    上述的官方提供的logger生成功能不是那么强大,项目需要将日志记录到文件和分割 的时候就需要自定义。
    zap自定义logger生成器使用zap.New():
    func New(core zapcore.Core, options ...Option) *Logger
    其中zapcore.Core需要设置三个参数Encoder,WriteSyncer,LogLevel
    Encoder:编译器,通俗说就是输出日志是什么格式,json or 终端格式。

    json格式就使用NewJSONEncoder(),并使用预先设置的ProductionEncoderConfig():
    zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig())
    终端格式就使用NewConsoleEncoder():
    zapcore.NewConsoleEncoder(zap.NewProductionEncoderConfig())
    

    WriteSyncer:将日志输出到哪。使用zapcore.AddSync()函数并且将打开的文件句柄传进去。

    file, _ := os.Create("./test.log")
    writeSyncer := zapcore.AddSync(file)
    

    LogLevel:将什么样级别的日志输出.

    代码实例:

    点击查看代码
    //使用自定义的zap logger
    func InitLogger() *zap.SugaredLogger{
    	//日志文件
    	logfile, _ :=os.OpenFile("zap_log.log",os.O_APPEND | os.O_CREATE|os.O_RDWR,0666)
    	//编码器
    	encoder := zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig())
    	//输出位置
    	writeSyncer := zapcore.AddSync(logfile)
    
    	//定义core
    	core := zapcore.NewCore(
    		encoder,
    		writeSyncer,
    		zapcore.DebugLevel,
    	)
    
    	//创建logger
    	logger:= zap.New(core)
    	
    	return logger.Sugar()
    }
    

    2.4.2 若输出到文件和终端,只需要更改WriteSyncer参数

    点击查看代码
    //使用自定义的zap logger
    func InitLogger() *zap.SugaredLogger{
    	//日志文件
    	logfile, _ :=os.OpenFile("zap_log.log",os.O_APPEND | os.O_CREATE|os.O_RDWR,0666)
    	//编码器
    	encoder := zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig())
    	//输出位置
    	// writeSyncer := zapcore.AddSync(logfile)
    	//输出多个位置
    	wc := io.MultiWriter(logfile,os.Stdout)
    	writeSyncer:= zapcore.AddSync(wc)
    
    	//定义core
    	core := zapcore.NewCore(
    		encoder,
    		writeSyncer,
    		zapcore.DebugLevel,
    	)
    
    	//创建logger
    	logger:= zap.New(core)
    	
    	return logger.Sugar()
    }
    
    
    效果: ![image](https://img2024.cnblogs.com/blog/3452880/202409/3452880-20240912221329852-1914127797.png)

    2.4.3 将输出的时间转化

    //设置日志编译器,什么类型的日志
    func getEncoder() zapcore.Encoder{
    	//encoder配置
    	encoderConfig := zap.NewProductionEncoderConfig()
    	//设置时间格式为2024-9-1-12.32
    	encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
    	encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
    	//json格式
    	// jsonencoder := zapcore.NewJSONEncoder(encoderConfig)
    
    	//终端形式
    	ConsoleEncoder := zapcore.NewConsoleEncoder(encoderConfig)
    	return ConsoleEncoder
    
    }
    

    2.4.4 记录不同级别的日志
    有时候日志可分为log.erro.log 记录错误级别日志,;log.success.log记录成功级别日志,zapcore.DebugLevel就全记录。

    	core1 := zapcore.NewCore(
    		encoder,
    		writeSyncer,
    		zapcore.DebugLevel,//全记录
    	)
    	//错误日志
    	core2 :=  zapcore.NewCore(
    		encoder,
    		getwriteSyncer("log.err.log"),
    		zapcore.ErrorLevel,
    	)
    	c:=zapcore.NewTee(core1,core2)
    	logger:= zap.New(c,zap.AddCaller())
    	return logger.Sugar()
    

    2.4.5 AddCaller详细记录调用的代码行,AddCallerSkip(1)调用链很多时直接跳过

    logger:= zap.New(core,zap.AddCaller(), zap.AddCallerSkip(1))
    

    image

    3. 记录全日志,错误日志文件,同步终端,标准时间,记录代码位置的自定义logger代码

    点击查看代码
    //使用自定义的zap logger
    func InitLogger() *zap.SugaredLogger{
    	
    	//编码器
    	encoder := getEncoder()
    	//输出位置
    	writeSyncer:= getwriteSyncer("log_all.log")
    
    	//定义core
    	core1 := zapcore.NewCore(
    		encoder,
    		writeSyncer,
    		zapcore.DebugLevel,//全记录
    	)
    	//错误日志
    	core2 :=  zapcore.NewCore(
    		encoder,
    		getwriteSyncer("log.err.log"),
    		zapcore.ErrorLevel,
    	)
    
    	//创建单个logger
    	// logger:= zap.New(core1,zap.AddCaller(), zap.AddCallerSkip(1)) //AddCaller详细记录调用的代码行,AddCallerSkip(1)调用链很多时直接跳过
    	// return logger.Sugar()
    
    	//创建双日志,全日志和错误日志
    	c:=zapcore.NewTee(core1,core2)
    	logger:= zap.New(c,zap.AddCaller())
    	return logger.Sugar()
    }
    
    //设置日志编译器,什么类型的日志
    func getEncoder() zapcore.Encoder{
    	//encoder配置
    	encoderConfig := zap.NewProductionEncoderConfig()
    	//设置时间格式为2024-9-1-12.32
    	encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
    	encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
    	//json格式
    	// jsonencoder := zapcore.NewJSONEncoder(encoderConfig)
    
    	//终端形式
    	ConsoleEncoder := zapcore.NewConsoleEncoder(encoderConfig)
    	return ConsoleEncoder
    
    }
    
    //设置输出位置
    func getwriteSyncer(logfilename string) zapcore.WriteSyncer {
    	//日志文件
    	logfile, _ :=os.OpenFile(logfilename,os.O_APPEND | os.O_CREATE|os.O_RDWR,0666)
    
    	//只输出到日志文件
    	// return zapcore.AddSync(logfile)
    
    	//也输出到终端
    	wc := io.MultiWriter(logfile,os.Stdout)
    	return zapcore.AddSync(wc)
    }
    
    
    

    [========]

    [========]

    4.使用Lumberjack进行日志切割归档

    //设置输出位置
    func getwriteSyncer(logfilename string) zapcore.WriteSyncer {
    	//日志文件
    	// logfile, _ :=os.OpenFile(logfilename,os.O_APPEND | os.O_CREATE|os.O_RDWR,0666)
    
    	//分割日志
    	
    	l, _ := rotatelogs.New(
    		logfilename+".%Y%m%d%H%M.log",
    		rotatelogs.WithMaxAge(30*24*time.Hour),    // 最长保存30天
    		rotatelogs.WithRotationTime(time.Hour*24), // 24小时切割一次
    	)
    
    	//也输出到终端
    	wc := io.MultiWriter(l,os.Stdout)
    	return zapcore.AddSync(wc)
    }
    

    5.上述完整代码

    点击查看代码
    package main
    
    import (
    	"io"
    	"net/http"
    	"os"
    	"time"
    	rotatelogs "github.com/lestrrat-go/file-rotatelogs"
    	// "gopkg.in/natefinch/lumberjack.v2"
    	"go.uber.org/zap"
    	"go.uber.org/zap/zapcore"
    )
    
    var Logger *zap.SugaredLogger
    func main() {
    	//初始化zap日志记录器
    	Logger = InitLogger()
    	defer Logger.Sync()
    	//模拟义务
    	Simplefunc("http://www.baidu.com")
    	Simplefunc("http://www.google.com")
    
    }
    //使用自定义的zap logger
    func InitLogger() *zap.SugaredLogger{
    	
    	//编码器
    	encoder := getEncoder()
    	//输出位置
    	writeSyncer:= getwriteSyncer("log_all")
    
    	//定义core
    	core1 := zapcore.NewCore(
    		encoder,
    		writeSyncer,
    		zapcore.DebugLevel,//全记录
    	)
    	//错误日志
    	core2 :=  zapcore.NewCore(
    		encoder,
    		getwriteSyncer("log.err"),
    		zapcore.ErrorLevel,
    	)
    
    	//创建单个logger
    	// logger:= zap.New(core1,zap.AddCaller(), zap.AddCallerSkip(1)) //AddCaller详细记录调用的代码行,AddCallerSkip(1)调用链很多时直接跳过
    	// return logger.Sugar()
    
    	//创建双日志,全日志和错误日志
    	c:=zapcore.NewTee(core1,core2)
    	logger:= zap.New(c,zap.AddCaller())
    	return logger.Sugar()
    }
    
    //设置日志编译器,什么类型的日志
    func getEncoder() zapcore.Encoder{
    	//encoder配置
    	encoderConfig := zap.NewProductionEncoderConfig()
    	//设置时间格式为2024-9-1-12.32
    	encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
    	encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
    	//json格式
    	// jsonencoder := zapcore.NewJSONEncoder(encoderConfig)
    
    	//终端形式
    	ConsoleEncoder := zapcore.NewConsoleEncoder(encoderConfig)
    	return ConsoleEncoder
    
    }
    
    //设置输出位置
    func getwriteSyncer(logfilename string) zapcore.WriteSyncer {
    	//日志文件
    	// logfile, _ :=os.OpenFile(logfilename,os.O_APPEND | os.O_CREATE|os.O_RDWR,0666)
    
    	//分割日志
    	
    	l, _ := rotatelogs.New(
    		logfilename+".%Y%m%d%H%M.log",
    		rotatelogs.WithMaxAge(30*24*time.Hour),    // 最长保存30天
    		rotatelogs.WithRotationTime(time.Hour*24), // 24小时切割一次
    	)
    
    	//也输出到终端
    	wc := io.MultiWriter(l,os.Stdout)
    	return zapcore.AddSync(wc)
    }
    
    
    
    
    func Simplefunc(url string) {
    	res,err:=http.Get(url)
    	if err!=nil {
    		//记录错误日志
    		Logger.Error(
    			"http get failed..",
    			zap.String("url:",url),
    			zap.Error(err),
    		)
    	}else {
    		//使用info记录成功日志。
    		Logger.Info(
    			"get success",
    			zap.String("status:",res.Status),
    			zap.String("url:",url),
    		)
    		res.Body.Close()
    	}
    	
    	
    }
    

    在gin框架中使用zap日志记录器