关于golang中其他各种日志插件对比,这里不再赘述,直奔zap主题,理论小结+实战。
目录
前言
使用小结
动手实战
基于zap+file-rotatelogs实现按天分隔日志
基于zap+lumberjack实现按天分隔日志
写在最后
为什么选择zap:
zap是非常快的、结构化的,分日志级别的Go日志库它同时提供了结构化日志记录和printf风格的日志记录以下是Zap发布的基准测试信息
记录一条消息和10个字段:
PackageTimeTime % to zapObjects Allocated⚡️ zap862 ns/op+0%5 allocs/op⚡️ zap (sugared)1250 ns/op+45 allocs/opzerolog4021 ns/op+366v allocs/opgo-kit4542 ns/op+4275 allocs/opapex/log26785 ns/op+30075 allocs/oplogrus29501 ns/op+33225 allocs/oplog1529906 ns/op+33692 allocs/op哎,之前思考的少,都是拿来主义,就知道用别人写好的,自己搞,才发现不少细节。分享个小结:
日志按大小切割和备份个数、文件有效期,一般选zap+lumberjack日志按天或者小时切割,一般选zap+file-rotatelogszap中Logger和SugaredLogger的区别:
Zap提供了两种类型的日志记录器—SugaredLogger和Logger在性能很好但不是很关键的上下文中,使用SugaredLogger。它比其他结构化日志记录包快4-10倍,并且支持结构化和printf风格的日志记录在每一微秒和每一次内存分配都很重要的上下文中,使用Logger。它甚至比SugaredLogger更快,内存分配次数也更少,但它只支持强类型的结构化日志记录SugaredLogger是在Logger的基础上,提供了额外参数的格式化方式,提供更大的便利性以格式化具体的msg,在可能带来风险的同时,还会造成额外的内存分配实现功能点:
按照不同级别日志独立文件记录(可以参考info级别自己动手扩展下)日志按天分割只保留近30天的日志编码:
package main import ( rotatelogs "github.com/lestrrat-go/file-rotatelogs" "go.uber.org/zap" "go.uber.org/zap/zapcore" "io" "strings" "time" ) var errorLogger *zap.SugaredLogger func init() { encoder := zapcore.NewJSONEncoder(zapcore.EncoderConfig{ MessageKey: "msg", LevelKey: "level", EncodeLevel: zapcore.CapitalLevelEncoder, TimeKey: "ts", EncodeTime: func(t time.Time, enc zapcore.PrimitiveArrayEncoder) { enc.AppendString(t.Format("2006-01-02 15:04:05")) }, CallerKey: "call", EncodeCaller: zapcore.ShortCallerEncoder, EncodeDuration: func(d time.Duration, enc zapcore.PrimitiveArrayEncoder) { enc.AppendInt64(int64(d) / 1000000) }, }) infoLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool { return lvl >= zapcore.InfoLevel }) infoWriter := getWriter("console_info.log") core := zapcore.NewTee( zapcore.NewCore(encoder, zapcore.AddSync(infoWriter), infoLevel), ) //AddCallerSkip增加了调用者注释跳过的调用者数量 //大白话:就是显示调用打印日志的是哪一行的code行数,你可以改为0看看效果,哈哈 log := zap.New(core, zap.AddCaller(), zap.AddCallerSkip(1)) errorLogger = log.Sugar() } func getWriter(filename string) io.Writer { hook, err := rotatelogs.New( strings.Replace(filename, ".log", "", -1) + "-%Y-%m-%d.log", //文件最大寿命30天 rotatelogs.WithMaxAge(time.Hour*24*30), //每隔1天进行文件分割 rotatelogs.WithRotationTime(time.Hour*24), ) if err != nil { panic(err) } return hook } func Debug(args ...interface{}) { errorLogger.Debug(args...) } func Debugf(template string, args ...interface{}) { errorLogger.Debugf(template, args...) } func Info(args ...interface{}) { errorLogger.Info(args...) } func Infof(template string, args ...interface{}) { errorLogger.Infof(template, args...) } func Warn(args ...interface{}) { errorLogger.Warn(args...) } func Warnf(template string, args ...interface{}) { errorLogger.Warnf(template, args...) } func Error(args ...interface{}) { errorLogger.Error(args...) } func Errorf(template string, args ...interface{}) { errorLogger.Errorf(template, args...) } func DPanic(args ...interface{}) { errorLogger.DPanic(args...) } func DPanicf(template string, args ...interface{}) { errorLogger.DPanicf(template, args...) } func Panic(args ...interface{}) { errorLogger.Panic(args...) } func Panicf(template string, args ...interface{}) { errorLogger.Panicf(template, args...) } func Fatal(args ...interface{}) { errorLogger.Fatal(args...) } func Fatalf(template string, args ...interface{}) { errorLogger.Fatalf(template, args...) } func main() { Infof("Hello World") }效果如下:
实现功能点:
按照500M文件大小切割文件最多保留200个文件最多保留30天支持文件压缩编码:
package main import ( "go.uber.org/zap" "go.uber.org/zap/zapcore" "gopkg.in/natefinch/lumberjack.v2" ) // error logger var errorLogger *zap.SugaredLogger var levelMap = map[string]zapcore.Level{ "debug": zapcore.DebugLevel, "info": zapcore.InfoLevel, "warn": zapcore.WarnLevel, "error": zapcore.ErrorLevel, "dpanic": zapcore.DPanicLevel, "panic": zapcore.PanicLevel, "fatal": zapcore.FatalLevel, } func getLoggerLevel(lvl string) zapcore.Level { if level, ok := levelMap[lvl]; ok { return level } return zapcore.InfoLevel } //Filename: 日志文件的位置 //MaxSize:在进行切割之前,日志文件的最大大小(以MB为单位) //MaxBackups:保留旧文件的最大个数 //MaxAges:保留旧文件的最大天数 //Compress:是否压缩/归档旧文件 func init() { fileName := "console.log" level := getLoggerLevel("debug") syncWriter := zapcore.AddSync(&lumberjack.Logger{ Filename: fileName, MaxSize: 500, MaxBackups: 200, MaxAge: 30, LocalTime: true, Compress: true, }) encoder := zap.NewProductionEncoderConfig() encoder.EncodeTime = zapcore.ISO8601TimeEncoder core := zapcore.NewCore(zapcore.NewJSONEncoder(encoder), syncWriter, zap.NewAtomicLevelAt(level)) logger := zap.New(core, zap.AddCaller(), zap.AddCallerSkip(1)) errorLogger = logger.Sugar() } func Debug(args ...interface{}) { errorLogger.Debug(args...) } func Debugf(template string, args ...interface{}) { errorLogger.Debugf(template, args...) } func Info(args ...interface{}) { errorLogger.Info(args...) } func Infof(template string, args ...interface{}) { errorLogger.Infof(template, args...) } func Warn(args ...interface{}) { errorLogger.Warn(args...) } func Warnf(template string, args ...interface{}) { errorLogger.Warnf(template, args...) } func Error(args ...interface{}) { errorLogger.Error(args...) } func Errorf(template string, args ...interface{}) { errorLogger.Errorf(template, args...) } func DPanic(args ...interface{}) { errorLogger.DPanic(args...) } func DPanicf(template string, args ...interface{}) { errorLogger.DPanicf(template, args...) } func Panic(args ...interface{}) { errorLogger.Panic(args...) } func Panicf(template string, args ...interface{}) { errorLogger.Panicf(template, args...) } func Fatal(args ...interface{}) { errorLogger.Fatal(args...) } func Fatalf(template string, args ...interface{}) { errorLogger.Fatalf(template, args...) } func main() { Infof("Hello World") }效果如下:
上面的仅仅是zap的基本应用,想玩的更加顺手、深入,自己入门后多动手,遇到问题看看源码。
参考链接:
https://www.cnblogs.com/Golanguage/p/12285584.htmlhttps://www.jianshu.com/p/5f796e2afd45?utm_campaign=studygolang.com&utm_medium=studygolang.com&utm_source=studygolang.com