一、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()
NewDevelopment()
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 mainimport ("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)//定义corecore := zapcore.NewCore(encoder,writeSyncer,zapcore.DebugLevel,)//创建loggerlogger:= 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)//定义corecore := zapcore.NewCore(encoder,writeSyncer,zapcore.DebugLevel,)//创建loggerlogger:= zap.New(core)return logger.Sugar()
}
2.4.3 将输出的时间转化
//设置日志编译器,什么类型的日志
func getEncoder() zapcore.Encoder{//encoder配置encoderConfig := zap.NewProductionEncoderConfig()//设置时间格式为2024-9-1-12.32encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoderencoderConfig.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))
3. 记录全日志,错误日志文件,同步终端,标准时间,记录代码位置的自定义logger代码
点击查看代码
//使用自定义的zap logger
func InitLogger() *zap.SugaredLogger{//编码器encoder := getEncoder()//输出位置writeSyncer:= getwriteSyncer("log_all.log")//定义corecore1 := 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.32encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoderencoderConfig.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 mainimport ("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")//定义corecore1 := 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.32encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoderencoderConfig.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()}}