在开发过程中 会使用到日志库去记录错误的日志,尤其是golang中 有无穷无尽的error 如果不记录,当你的代码出错,就无从排错了。zap 是开源的 Go 高性能日志库 主要有以下特点:
(资料图片)
官网:https://github.com/uber-go/zaphttps://pkg.go.dev/go.uber.org/zap#section-readme
安装go get -u go.uber.org/zap
zap只支持Go的两个最新小版本。
日志记录器 logger和 sugared loggerzap库的使用与其他的日志库非常相似。先创建一个logger,然后调用各个级别的方法记录日志而 zap库给我们提供两种模式的日志记录
LoggerSugared Logger至于你想问他们之间有什么区别,很简单,我们先来看代码这里我就直接用官网的例用代码了Loggerlogger, _ := zap.NewProduction()defer logger.Sync()logger.Info("failed to fetch URL",// Structured context as strongly typed Field values.zap.String("url", "https://www.baidu.com"),zap.Int("attempt", 3),zap.Duration("backoff", time.Second),)
说实话我是很不喜欢logger模式的日志的调用起来是真的麻烦 还要指定 int类型 string类型 这个类型那个类型但优点也很明显那就是快而且内存分配少,性能至上
Sugared Loggerlogger, _ := zap.NewProduction()defer logger.Sync() // flushes buffer, if anysugar := logger.Sugar()sugar.Infow("failed to fetch URL",// Structured context as loosely typed key-value pairs."url", "https://www.baidu.com","attempt", 3,"backoff", time.Second,)sugar.Infof("Failed to fetch URL: %s", "https://www.baidu.com")
这种就是printf风格的调用起来方便。即开即用。
Example 和 Production 以及developmentExamplelog := zap.NewExample()log.Debug("this is debug message")log.Info("this is info message")log.Info("this is info message with fileds",zap.Int("age", 24), zap.String("agender", "man"))log.Warn("this is warn message")log.Error("this is error message")log.Panic("this is panic message")
结果
Productionlog, _ := zap.NewProduction()log.Debug("this is debug message")log.Info("this is info message")log.Info("this is info message with fileds",zap.Int("age", 24), zap.String("agender", "man"))log.Warn("this is warn message")log.Error("this is error message")log.Panic("this is panic message")
结果
NewDevelopmentlog, _ := zap.NewDevelopment()log.Debug("this is debug message")log.Info("this is info message")log.Info("this is info message with fileds",zap.Int("age", 24), zap.String("agender", "man"))log.Warn("this is warn message")log.Error("this is error message")log.Panic("this is panic message")
结果
三者对比由上文可见Example和Production使用的是json格式而development使用行的形式除此之外Example和Production 所输出的多少也不一样。
具体如下:
Development
从警告级别向上打印到堆栈中来跟踪始终打印包/文件/行(方法)在行尾添加任何额外字段作为json字符串以大写形式打印级别名称以毫秒为单位打印ISO8601格式的时间戳Production
调试级别消息不记录Error,Dpanic级别的记录,会在堆栈中跟踪文件,warn不会始终将调用者添加到文件中以时间戳格式打印日期以小写形式打印级别名称调整日志输出的 格式如下文代码所示
func getEncoder() zapcore.Encoder { encoderConfig := zap.NewDevelopmentEncoderConfig() { // LevelKey值变为 level encoderConfig.LevelKey = "level" // MessageKey值变为 msg encoderConfig.MessageKey = "msg" // TimeKey值 变成time encoderConfig.TimeKey = "time" // 把输出的info 变成INFO 只需要丢对象 不许执行 encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder // 对时间进行格式化处理 encoderConfig.EncodeTime = func(t time.Time, encoder zapcore.PrimitiveArrayEncoder) { encoder.AppendString(t.Local().Format("2006-01-02 15:04:05")) } } return zapcore.NewJSONEncoder(encoderConfig)}
如上代码所示,可以调节任意位置,我注释也标的很清楚
使用lumberjack进行配合使用官网: https://pkg.go.dev/gopkg.in/natefinch/lumberjack.v2zap没有切割日志的功能,所以我们必须借助第三方库来实现
要将 lumberjack 与标准库的日志包一起使用,只需在应用程序启动时将其传递到 SetOutput 函数中即可。
log.SetOutput(&lumberjack.Logger{ Filename: "/var/log/myapp/foo.log", MaxSize: 500, // megabytes MaxBackups: 3, MaxAge: 28, //days Compress: true, // disabled by default})
如果要和Zap所结合的话 需要放入到zapcore.AddSync中
zapcore.AddSync(&lumberjack.Logger{ Filename: "/var/log/myapp/foo.log", MaxSize: 500, // megabytes MaxBackups: 3, MaxAge: 28, //days Compress: true, // disabled by default})
声明日志并且初始化使用我们上文以及配置好了日志的格式以及规定了日志输出的位置 也做好了 lumberjack日志的切割那我们该如何初始化呢只需要声明core 然后把这三个丢进去即可如下代码所示
core := zapcore.NewCore(getEncoder(), zapcore.NewMultiWriteSyncer(zapcore.AddSync(&lumberjack.Logger{ Filename: "/var/log/myapp/foo.log", MaxSize: 500, // megabytes MaxBackups: 3, MaxAge: 28, //days Compress: true, // disabled by default}) , zapcore.AddSync(os.Stdout)), zapcore.DebugLevel)zap.New(core).Sugar()
当然 会发现 我还加了一个值 zapcore.AddSync(os.Stdout))这句代码是代表除了输出到文件中还会输出到终端中,完成多个终端的输出
完整代码 日志库初始化组件package confimport ( "fmt" "github.com/natefinch/lumberjack" "github.com/spf13/viper" "go.uber.org/zap" "go.uber.org/zap/zapcore" "os" "path/filepath" "time")func InitLogger() *zap.SugaredLogger { logMode := zapcore.InfoLevel if viper.GetBool("model.development") { logMode = zapcore.DebugLevel } // 第一个参数是输出的格式 第二个参数 输出的位置 //zapcore.NewMultiWriteSyncer 输出到多个终端 比如 文件 console中 core := zapcore.NewCore(getEncoder(), zapcore.NewMultiWriteSyncer(getWriterSyncer(), zapcore.AddSync(os.Stdout)), logMode) return zap.New(core).Sugar()}// def 输出日志的格式func getEncoder() zapcore.Encoder { encoderConfig := zap.NewDevelopmentEncoderConfig() { // LevelKey值变为 level encoderConfig.LevelKey = "level" // MessageKey值变为 msg encoderConfig.MessageKey = "msg" // TimeKey值 变成time encoderConfig.TimeKey = "time" // 把输出的info 变成INFO 只需要丢对象 不许执行 encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder // 对时间进行格式化处理 encoderConfig.EncodeTime = func(t time.Time, encoder zapcore.PrimitiveArrayEncoder) { encoder.AppendString(t.Local().Format("2006-01-02 15:04:05")) } } return zapcore.NewJSONEncoder(encoderConfig)}// def 日志要输出到什么地方func getWriterSyncer() zapcore.WriteSyncer { stSeparator := string(filepath.Separator) stRootDir, _ := os.Getwd() stLogFilePath := stRootDir + stSeparator + "log" + stSeparator + time.Now().Format("2006-01-02") + ".log" fmt.Println(stLogFilePath) // 日志分割 hook := lumberjack.Logger{ Filename: stLogFilePath, // 日志文件路径,默认 os.TempDir() MaxSize: viper.GetInt("log.MaxSize"), // 每个日志文件保存500M,默认 100M MaxBackups: viper.GetInt("log.MaxBackups"), // 保留3个备份,默认不限 MaxAge: viper.GetInt("log.MaxAge"), // 保留28天,默认不限 Compress: viper.GetBool("log.Compress"), // 是否压缩,默认不压缩 } return zapcore.AddSync(&hook)}
从2月青绿片段在总台虎年春晚出圈,到4月在北京保利剧院连演18场,再到写进《新时代的中国青年》白皮书……《只此青绿》已然成为现象级舞台
中新网北京5月19日电(记者 陈杭)北京市疾病预防控制中心副主任刘晓峰在19日召开的北京新冠肺炎疫情防控工作新闻发布会上表示,4月22日
中新网北京5月19日电(记者 陈杭)北京市疾病预防控制中心副主任刘晓峰在19日召开的北京新冠肺炎疫情防控工作新闻发布会上表示,当前社
中新网北京5月19日电(记者 陈杭)北京市疾病预防控制中心副主任刘晓峰在19日召开的北京新冠肺炎疫情防控工作新闻发布会上表示,截至202
中新网长沙5月19日电 (记者 傅煜)今年以来,湖南共拦截诈骗电话375 1万次,封堵涉诈有害域名100 4万个,冻结涉案资金14 3亿元,劝阻2
X 关闭
X 关闭