zap日志框架

github:zap

Hello World

package main

import (
	"time"

	"go.uber.org/zap"
)

func main() {
	logger := zap.NewExample()
	defer logger.Sync() // zap底层 API 可以设置缓存,所以一般使用defer logger.Sync()将缓存同步到文件中

	url := "http://example.org/api"
	logger.Info("failed to fetch URL",
		zap.String("url", url),
		zap.Int("attempt", 3),
		zap.Duration("backoff", time.Second),
	)
}

由于fmt.Printf之类的方法大量使用interface{}和反射,会有不少性能损失,并且增加了内存分配的频次。zap为了提高性能、减少内存分配次数,没有使用反射,而且默认的Logger只支持强类型的、结构化的日志。必须使用zap提供的方法记录字段。

比如上述代码中的:

zap为 Go 语言中所有的基本类型和其他常见类型都提供了方法。这些方法的名称也比较好记忆,zap.TypeTypebool/int/uint/float64/complex64/time.Time/time.Duration/error等)就表示该类型的字段,zap.Typepp结尾表示该类型指针的字段,zap.Typess结尾表示该类型切片的字段。如:

  • zap.Bool(key string, val bool) Fieldbool字段

  • zap.Boolp(key string, val *bool) Fieldbool指针字段

  • zap.Bools(key string, val []bool) Fieldbool切片字段

其他特殊类型:

  • zap.Any(key string, value interface{}) Field:任意类型的字段

  • zap.Binary(key string, val []byte) Field:二进制串的字段

每个字段都使用方法包裹一层比较繁琐,所以zap提供了SugaredLogger,使用logger.Sugar()即可创建SugaredLogger

SugaredLogger

sugared的含义为糖,SugaredLogger的含义就是对Logger包装了一层语法糖,内部提供两种后缀的方法:

  • Infow,字段形式输出

  • Infofprintf方式输出

如下:

输出结果:

日志级别

zap共提供5中日志级别,分别为:

  • Debug

  • Info

  • Warn

  • Error,会打印出堆栈信息

  • Fatal,会打印出堆栈信息,并且调用os.Exit(1)退出程序

运行结果:

预定义配置Logger

zap提供了三个方法,用于快速创建logger

  • zap.NewExample():json格式,debug级别,适合用于测试代码中

  • zap.NewDevelopment():console格式,debug级别,人性化显示,用于开发环境

  • zap.NewProduction():json格式,info级别,方便解析,用于生产环境

  • zap.NewNop():不记录任何日志,直接丢弃

选项模式

NewExample()/NewDevelopment()/NewProduction()这 3 个函数可以传入若干类型为zap.Option的选项,从而定制Logger的行为。

option: 输出文件名以及行号

打印日志:

这里,字段caller打印的调用位置是main.go:11行,但是这行一般是打印语句执行的位置,定位到这一行通常没有什么用,需要向前查找。我们可以使用zap.AddCallerSkip(skip int)向上跳 1 层。

项目中一般会对日志框架调用进行封装,这时候,如果打印的行数是日志的行数,总会带来一定的困惑,所以,可以设置向上跳一层,查看方法调用方的行数,这样比较有用。

option: 输出调用堆栈

option: 预设字段

自定义配置Logger

通常情况下,上面的三种配置往往达不到我们的要求,这时通常自定义Logger。使用zap.Config结构体创建一个新的Logger配置,并调用他的Build方法,构建出一个Logger。

zap.Config支持的字段如下:

EncoderConfig的具体信息:

此外,针对各种Encoder,zap提供了一些内置的实现:

全局Logger

为了方便在项目中使用,zap提供了两个全局Logger,分别是

  • 全局的*zap.Logger对象,可以通过zap.L()获取

  • 全局的*zap.SugaredLogger对象,可以通过zap.S()获取

注意,这两个Logger默认不记录任何日志,因为他们都是调用zap.NewNop()方法生成的,要想使用全局Logger,需要使用zap.ReplaceGlobals(logger)函数替换全局Logger:

输出:

思考:这里可以使用全局Logger来封装项目的统一Logger。建立一个package,存放全局Logger配置,然后暴露统一的日志打印方法,既可以与日志框架分离,又可以集中控制日志配置

最后更新于

这有帮助吗?