您的位置 首页 golang

golang高性能日志库zap的使用

摘要

zap Uber 开发的非常快的、结构化的,分日志级别的Go日志库。根据Uber-go Zap的文档,它的性能比类似的结构化日志包更好,也比标准库更快。具体的性能测试可以去 github 上看到。

github地址:

转自:

参考:go语言中文文档:www.topgoer.com

创建实例

通过调用 zap.NewProduction() / zap.NewDevelopment() 或者 zap.Example() 创建一个Logger。这三个方法的区别在于它将记录的信息不同,参数只能是 string 类型

 //代码
var log *zap.Logger
log = zap.NewExample()
log, _ := zap.New Development ()
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}
  

三种创建方式对比:

  • Example Production 使用的是 json 格式输出, Development 使用行的形式输出
  • Development 从警告级别向上打印到堆栈中来跟踪始终打印包/文件/行(方法)在行尾添加任何额外字段作为json字符串以大写形式打印级别名称以毫秒为单位打印ISO8601格式的时间戳
  • Production 调试级别消息不记录Error,Dpanic级别的记录,会在堆栈中跟踪文件,Warn不会始终将调用者添加到文件中以时间戳格式打印日期以小写形式打印级别名称

格式化输出

zap有两种类型,分别是 *zap.Logger *zap.SugaredLogger ,它们惟一的区别是,我们通过调用主logger的 . Sugar() 方法来获取一个 SugaredLogger ,然后使用 SugaredLogger printf 格式记录语句,例如

 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)
}
  

写入文件

默认情况下日志都会打印到应用程序的console界面,但是为了方便查询,可以将日志写入文件,但是我们不能再使用前面创建实例的3个方法,而是使用 zap.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")
}
  

日志文件输出结果:

 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
  

同时输出控制台和文件

如果需要同时输出控制台和文件,只需要改造一下 zapcore.NewCore 即可,示例:

 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")
}
  

文件切割

日志文件会随时间越来越大,为了避免日志文件把硬盘空间占满,需要按条件对日志文件进行切割,zap包本身不提供文件切割的功能,但是可以用zap官方推荐的 lumberjack 包处理

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

按级别写入文件

为了管理人员的查询方便,一般我们需要将低于error级别的放到info.log,error及以上严重级别日志存放到error.log文件中,我们只需要改造一下 zapcore.NewCore 方法的第3个参数,然后将文件 WriteSyncer 拆成 info error 两个即可,示例:

 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")
}
  

这样修改之后, info debug 级别的日志就存放到 info.log error 级别的日志单独放到 error.log 文件中了

控制台按级别显示颜色

指定编码器的 EncodeLevel 即可,

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

显示文件路径和行号

前面说到要显示文件路径和行号,只需要 zap.New 方法添加参数 zap.AddCaller() 即可,如果要显示完整的路径,需要在编码器配置中指定

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

完整代码

 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")
}  

文章来源:智云一二三科技

文章标题:golang高性能日志库zap的使用

文章地址:https://www.zhihuclub.com/91154.shtml

关于作者: 智云科技

热门文章

评论已关闭

29条评论

  1. 5, 150 mM NaCl, 5 mM EDTA, 1 Triton X100, protease inhibitor cocktail Roche Diagnostics, 50 mM NaF, 10 mM Na 3 VO 4, 1 mM PMSF

  2. An explorative laparotomy was performed, which revealed small bowel distention, an obstructive lesion of the ileocecal valve, three terminal ileum lesions, ascites, and heterogeneous ovaries Louisiana residents that have a love of bingo will find we have the most entertaining bingo sites listed on this page, many game enthusiasts want to have a casino mobile payments integrated with application

  3. Those levers are prioritizing protein, reducing added fat, fatty foods, and total energy, and adding fiber, micronutrient rich vegetables, whole food carbs, fermented foods, and daily time restricted eating

  4. Many expressed concerns that they were not sufficiently knowledgeable to have a view worth recording, or that it was simply not part of their zones of relevance Parsons and Atkinson 1992

  5. The reaction was cooled to ambient temperature, filtered through a silica gel pad and concentrated under reduced pressure to afford tert butyl 4 6 6 trifluoromethyl imidazo 1, 2 a pyridin 3 yl 2 pyridyl piperazine 1 carboxylate; ESV MS m z 448 geodon ofloxacin clobetasol propionate When asked if Duda, when healthy, would stay down in the minors like Ruben Tejada, Collins insisted that Гў

  6. Attending the weekly meetings showed the strongest correlation with weight loss out of the three tools

  7. I now drink de caf soda and herbal teas It discusses the importance of hypoglycemia, nutritional support, and imprecision in blood glucose testing in interpreting the results of these trials

  8. When using anabolic androgenic steroids, it is critical to understand the dangers associated with their use as well as the ways for avoiding these risks 0 mg dL were also excluded, as well as patients who received recent intravenous iodinated contrast

  9. In fact, one study found that even WITHOUT a PCT, patients testosterone levels returned to normal after a SARMs cycle 1 D, Example confocal images of ОІ3 tubulin GFP knock in cells using one to four GFP donors per vector

  10. It has also been shown that the cardiac contractility is reduced by thiamine deficiency 27

  11. The addition of hCG to clomiphene therapy may benefit women who respond to clomiphene therapy with rising LH, follicle stimulating hormone FSH, and estrogen levels but still fail to ovulate

  12. Unlike other synthetic and biologic DMARDs, HCQ is more readily available to patient due to its relative lower cost

  13. The sudden discontinuation of Seroquel may bring on withdrawal symptoms such as insomnia, nausea, and vomiting Serious Use Alternative 1 topiramate will decrease the level or effect of norethindrone acetate by affecting hepatic intestinal enzyme CYP3A4 metabolism

  14. flurbiprofen benazepril hydrochlorothiazide side effects Current and former administration officials, independent experts and business representatives say the three priorities are the creation of an online portal that will make it easy for consumers to compare insurance plans and enroll in coverage; the capacity to effectively process and deliver government subsidies that help consumers pay for the insurance; and retention of the law s individual mandate, which requires nearly all Americans to have health insurance when Obama s healthcare reform law comes into full force in 2014 However, there were no significant differences between letrozole and CC alone

  15. When physical evidence of hypovolemia is present, fluid resuscitation with normal saline is the first step in therapy PMID 26971303

网站地图