Golang

关注公众号 jb51net

关闭
首页 > 脚本专栏 > Golang > golang 日志库ZAP

golang 日志库ZAP[uber-go zap]示例详解

作者:nbplus_007

ZAP是由Uber开源的高性能Go语言日志库,支持多种日志级别及基本信息打印,虽然ZAP本身不支持日志分割,但可以结合lumberjack进行日志切割,实现日志按文件大小、时间或间隔切割等功能,ZAP提供Logger和SugaredLogger两种日志记录器

golang 日志库ZAP[uber-go zap] 

1. 简要说明

zap 是 uber 开源的 Go 高性能日志库,支持不同的日志级别, 能够打印基本信息等,但不支持日志的分割,这里我们可以使用 lumberjack 也是 zap 官方推荐用于日志分割,结合这两个库我们就可以实现以下功能的日志机制:

能够将事件记录到文件中,而不是应用程序控制台;日志切割能够根据文件大小、时间或间隔等来切割日志文件;支持不同的日志级别,例如 DEBUG , INFO , WARN , ERROR 等;能够打印基本信息,如调用文件、函数名和行号,日志时间等;官网地址:https://github.com/uber-go/zap

2. 下载安装

// 初始化go mod 通过mod管理扩展包
go mod init zaplog
//使用下面命令安装
go get -u go.uber.org/zap
//如果下载失败,则使用以下命令重新下载安装
go get github.com/uber-go/zap
//下载安装成功后还有如下提示:
package github.com/uber-go/zap: code in directory 
src/github.com/uber-go/zap expects import "go.uber.org/zap"

3. 配置 zap Logger

zap 提供了两种类型的日志记录器—和 Logger 和 Sugared Logger 。两者之间的区别是:

3.1 Logger

3.1.1 NewExample

//代码示例:
package main
import (
	"go.uber.org/zap"
)
func main() {
	log := 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")
}
//输出结果:
{"level":"debug","msg":"this is debug message"}
{"level":"info","msg":"this is info message"}
{"level":"info","msg":"this is info message with fileds","age":24,"agender":"man"}
{"level":"warn","msg":"this is warn message"}
{"level":"error","msg":"this is error message"}
{"level":"panic","msg":"this is panic message"}
panic: this is panic message

3.1.2 NewDevelopment

//代码示例:
func main() {
	log, _ := 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.DPanic("This is a DPANIC message")	
	// log.Panic("this is panic message")
	// log.Fatal("This is a FATAL message")
}
//输出结果:
2020-06-12T18:51:11.457+0800	DEBUG	task/main.go:9	this is debug message
2020-06-12T18:51:11.457+0800	INFO	task/main.go:10	this is info message
2020-06-12T18:51:11.457+0800	INFO	task/main.go:11	this is info message with fileds	{"age": 24, "agender": "man"}
2020-06-12T18:51:11.457+0800	WARN	task/main.go:13	this is warn message
main.main
	/home/wohu/GoCode/src/task/main.go:13
runtime.main
	/usr/local/go/src/runtime/proc.go:200
2020-06-12T18:51:11.457+0800	ERROR	task/main.go:14	this is error message
main.main
	/home/wohu/GoCode/src/task/main.go:14
runtime.main
	/usr/local/go/src/runtime/proc.go:200

3.1.3 NewProduction

代码示例:
func main() {
	log, _ := 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.DPanic("This is a DPANIC message")	
	// log.Panic("this is panic message")
	// log.Fatal("This is a FATAL message")
}
输出结果:
{"level":"info","ts":1591959367.316352,"caller":"task/main.go:10","msg":"this is info message"}
{"level":"info","ts":1591959367.3163702,"caller":"task/main.go:11","msg":"this is info message with fileds","age":24,"agender":"man"}
{"level":"warn","ts":1591959367.3163917,"caller":"task/main.go:13","msg":"this is warn message"}
{"level":"error","ts":1591959367.3163974,"caller":"task/main.go:14","msg":"this is error message","stacktrace":"main.main\n\t/home/wohu/GoCode/src/task/main.go:14\nruntime.main\n\t/usr/local/go/src/runtime/proc.go:200"}

3.1.4 对比总结

Example和Production使用的是 json 格式输出,Development 使用行的形式输出

日志记录器方法的语法是这样的:

func (log *Logger) MethodXXX(msg string, fields ...Field)

其中 MethodXXX 是一个可变参数函数,可以是 Info / Error / Debug / Panic 等。每个方法都接受一个消息字符串和任意数量的 zapcore.Field 长参数。

每个 zapcore.Field 其实就是一组键值对参数。

3.2 Sugared Logger

默认的 zap 记录器需要结构化标签,即对每个标签,需要使用特定值类型的函数。

log.Info("this is info message with fileds",zap.Int("age", 24), zap.String("agender", "man"))

虽然会显的很长,但是对性能要求较高的话,这是最快的选择。也可以使用suger logger, 它基于 printf 分割的反射类型检测,提供更简单的语法来添加混合类型的标签。

我们使用 Sugared Logger 来实现相同的功能。

func main() {
	logger, _ := zap.NewDevelopment()
	slogger := logger.Sugar()
	slogger.Debugf("debug message age is %d, agender is %s", 19, "man")
	slogger.Info("Info() uses sprint")
	slogger.Infof("Infof() uses %s", "sprintf")
	slogger.Infow("Infow() allows tags", "name", "Legolas", "type", 1)
}
//输出结果:
2020-06-12T19:23:54.184+0800	DEBUG	task/main.go:11	debug message age is 19, agender is man
2020-06-12T19:23:54.185+0800	INFO	task/main.go:12	Info() uses sprint
2020-06-12T19:23:54.185+0800	INFO	task/main.go:13	Infof() uses sprintf
2020-06-12T19:23:54.185+0800	INFO	task/main.go:14	Infow() allows tags	{"name": "Legolas", "type": 1}

如果需要,可以随时使用记录器上的 .Desugar() 方法从 sugar logger 切换到标准记录器。

log := slogger.Desugar()
log.Info("After Desugar; INFO message")
log.Warn("After Desugar; WARN message")
log.Error("After Desugar; ERROR message")

4. 将日志写入文件

我们将使用zap.New(…)方法来手动传递所有配置,而不是使用像zap.NewProduction()这样的预置方法来创建 logger 。

func New(core zapcore.Core, options ...Option) *Logger

zapcore.Core需要三个配置——Encoder,WriteSyncer,LogLevel。

Encoder :编码器(如何写入日志)。我们将使用开箱即用的 NewConsoleEncoder() ,并使用预先设置的 ProductionEncoderConfig() 。

zapcore.NewConsoleEncoder(zap.NewProductionEncoderConfig())

WriterSyncer :指定日志将写到哪里去。我们使用 zapcore.AddSync() 函数并且将打开的文件句柄传进去。

file, _ := os.Create("./test.log") 
writeSyncer := zapcore.AddSync(file)

Log Level :哪种级别的日志将被写入。

// 代码示例:
package main
import (
	"os"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)
var sugarLogger *zap.SugaredLogger
func InitLogger() {
	encoder := getEncoder()
	writeSyncer := getLogWriter()
	core := zapcore.NewCore(encoder, writeSyncer, zapcore.DebugLevel)
	// zap.AddCaller()  添加将调用函数信息记录到日志中的功能。
	logger := zap.New(core, zap.AddCaller())
	sugarLogger = logger.Sugar()
}
func getEncoder() zapcore.Encoder {
	encoderConfig := zap.NewProductionEncoderConfig()
	encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder // 修改时间编码器
	// 在日志文件中使用大写字母记录日志级别
	encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
	// NewConsoleEncoder 打印更符合人们观察的方式
	return zapcore.NewConsoleEncoder(encoderConfig)
}
func getLogWriter() zapcore.WriteSyncer {
	file, _ := os.Create("./test.log")
	return zapcore.AddSync(file)
}
func main() {
	InitLogger()
	sugarLogger.Info("this is info message")
	sugarLogger.Infof("this is %s, %d", "aaa", 1234)
	sugarLogger.Error("this is error message")
	sugarLogger.Info("this is info message")
}
// 输出日志文件:
2020-06-16T09:01:06.192+0800	INFO	task/main.go:40	this is info message
2020-06-16T09:01:06.192+0800	INFO	task/main.go:41	this is aaa, 1234
2020-06-16T09:01:06.192+0800	ERROR	task/main.go:42	this is error message
2020-06-16T09:01:06.192+0800	INFO	task/main.go:43	this is info message

到此这篇关于golang 日志库ZAP[uber-go zap]详解的文章就介绍到这了,更多相关golang 日志库ZAP内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文