1. 为什么使用zap
因为它很快,而且我写不出比他更快的日志库😭
当然他还有其他优点,比如:它同时提供了结构化日志记录和printf风格的日志记录
2. 安装zap
go get -u go.uber.org/zap
3. 配置zap
zap提供两种日志记录器,如下表
名称 优点 缺点 Sugared Logger 支持结构化和printf风格的日志记录 较Logger慢 Logger 较Sugared Logger快 只支持强类型的结构化日志记录
- 创建Logger
- zap.NewProduction()
- zap.NewDevelopment()
- zap.Example()
- 上述函数均可创建Logger只是输出信息不同
- 默认情况下日志会打印到控制台
举个例子
package main
import "go.uber.org/zap"
var logger *zap.Logger
func ProductionLogger(){
logger,_ = zap.NewProduction()
logger.Info("log info")
}
func DevelopmentLogger(){
logger,_ = zap.NewDevelopment()
logger.Info("log info")
}
func ExampleLogger(){
logger = zap.NewExample()
logger.Info("log info")
}
func main() {
ProductionLogger()
DevelopmentLogger()
ExampleLogger()
}
运行结果
{"level":"info","ts":1594976812.8990078,"caller":"go_zap/main.go:9","msg":"log info"}
2020-07-17T17:06:52.899+0800 INFO go_zap/main.go:14 log info
{"level":"info","msg":"log info"}
除DevelopmentLogger之外其余都是json格式输出
- 创建Sugared Logger
- 由Logger调用Sugar()方法获得
- 支持printf风格输出日志
举个例子
package main
import "go.uber.org/zap"
var sugarLogger *zap.SugaredLogger
func ProductionLogger(){
logger,_ := zap.NewProduction()
sugarLogger = logger.Sugar()
sugarLogger.Infof("sugar loger %s", "yes!")
}
func DevelopmentLogger(){
logger,_ := zap.NewDevelopment()
sugarLogger = logger.Sugar()
sugarLogger.Infof("sugar loger %s", "yes!")
}
func ExampleLogger(){
logger := zap.NewExample()
sugarLogger = logger.Sugar()
sugarLogger.Infof("sugar loger %s", "yes!")
}
func main() {
ProductionLogger()
DevelopmentLogger()
ExampleLogger()
}
运行结果
{"level":"info","ts":1594977351.4368348,"caller":"go_zap/main.go:10","msg":"sugar loger yes!"}
2020-07-17T17:15:51.436+0800 INFO go_zap/main.go:16 sugar loger yes!
{"level":"info","msg":"sugar loger yes!"}
输出结果和Logger类似,但是sugarLogger支持printf
4. 定制Logger
上面所介绍到的三个创建Logger的方法包含了一些预置的配置,如果我们想要完全自定义,那我们就需要自己写好自己需要的配置。
这些配置将被赋值给 zap.Config
结构体,然后这个结构体对象调用 Build
方法构造Logger,大概就像这样
config := zap.Config{
...
}
log, err := config.Build()
type Config struct {
// Level is the minimum enabled logging level. Note that this is a dynamic
// level, so calling Config.Level.SetLevel will atomically change the log
// level of all loggers descended from this config.
Level AtomicLevel json:"level" yaml:"level"
// Development puts the logger in development mode, which changes the
// behavior of DPanicLevel and takes stacktraces more liberally.
Development bool json:"development" yaml:"development"
// DisableCaller stops annotating logs with the calling function's file
// name and line number. By default, all logs are annotated.
DisableCaller bool json:"disableCaller" yaml:"disableCaller"
// DisableStacktrace completely disables automatic stacktrace capturing. By
// default, stacktraces are captured for WarnLevel and above logs in
// development and ErrorLevel and above in production.
DisableStacktrace bool json:"disableStacktrace" yaml:"disableStacktrace"
// Sampling sets a sampling policy. A nil SamplingConfig disables sampling.
Sampling *SamplingConfig json:"sampling" yaml:"sampling"
// Encoding sets the logger's encoding. Valid values are "json" and
// "console", as well as any third-party encodings registered via
// RegisterEncoder.
Encoding string json:"encoding" yaml:"encoding"
// EncoderConfig sets options for the chosen encoder. See
// zapcore.EncoderConfig for details.
EncoderConfig zapcore.EncoderConfig json:"encoderConfig" yaml:"encoderConfig"
// OutputPaths is a list of URLs or file paths to write logging output to.
// See Open for details.
OutputPaths []string json:"outputPaths" yaml:"outputPaths"
// ErrorOutputPaths is a list of URLs to write internal logger errors to.
// The default is standard error.
//
// Note that this setting only affects internal errors; for sample code that
// sends error-level logs to a different location from info- and debug-level
// logs, see the package-level AdvancedConfiguration example.
ErrorOutputPaths []string json:"errorOutputPaths" yaml:"errorOutputPaths"
// InitialFields is a collection of fields to add to the root logger.
InitialFields map[string]interface{} json:"initialFields" yaml:"initialFields"
}
我们需要特别注意的是 EncoderConfig
这个字段,它定义了我们输出的格式,根据他的提示我们来看看 zapcore.EncoderConfig
结构体
// An EncoderConfig allows users to configure the concrete encoders supplied by
// zapcore.
type EncoderConfig struct {
// Set the keys used for each log entry. If any key is empty, that portion
// of the entry is omitted.
MessageKey string json:"messageKey" yaml:"messageKey"
LevelKey string json:"levelKey" yaml:"levelKey"
TimeKey string json:"timeKey" yaml:"timeKey"
NameKey string json:"nameKey" yaml:"nameKey"
CallerKey string json:"callerKey" yaml:"callerKey"
StacktraceKey string json:"stacktraceKey" yaml:"stacktraceKey"
LineEnding string json:"lineEnding" yaml:"lineEnding"
// Configure the primitive representations of common complex types. For
// example, some users may want all time.Times serialized as floating-point
// seconds since epoch, while others may prefer ISO8601 strings.
EncodeLevel LevelEncoder json:"levelEncoder" yaml:"levelEncoder"
EncodeTime TimeEncoder json:"timeEncoder" yaml:"timeEncoder"
EncodeDuration DurationEncoder json:"durationEncoder" yaml:"durationEncoder"
EncodeCaller CallerEncoder json:"callerEncoder" yaml:"callerEncoder"
// Unlike the other primitive type encoders, EncodeName is optional. The
// zero value falls back to FullNameEncoder.
EncodeName NameEncoder json:"nameEncoder" yaml:"nameEncoder"
}
这些字段都不难理解,让我们来写一个例子吧
一般情况下我们都是用SugaredLogger因为它的速度足够快,而其功能更加强大,如果呢不知道该怎么选择不如就把两个都选上吧,就像这样
package main
import (
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
var Logger *zap.Logger
var SugarLogger *zap.SugaredLogger
func Init() error{
var err error
// 构造EncoderConfig
encoderConfig := zapcore.EncoderConfig{
TimeKey: "timestamp",
LevelKey: "severity",
NameKey: "logger",
CallerKey: "caller",
MessageKey: "message",
StacktraceKey: "stacktrace",
LineEnding: "\n",
EncodeLevel: zapcore.LowercaseLevelEncoder,
EncodeTime: zapcore.ISO8601TimeEncoder,
EncodeDuration: zapcore.SecondsDurationEncoder,
EncodeCaller: zapcore.FullCallerEncoder,
}
// 构造 Config
config := zap.Config{
Level: zap.NewAtomicLevelAt(zapcore.DebugLevel),
Development: true,
Encoding: "json",
EncoderConfig: encoderConfig,
InitialFields: map[string]interface{}{"MyName": "kainhuck"},
OutputPaths: []string{"stdout"},
ErrorOutputPaths: []string{"stdout"},
}
// 可以构造Logger了
Logger, err = config.Build()
if err != nil {
return err
}
// 然后是SugarLogger
SugarLogger = Logger.Sugar()
return nil
}
func main(){
err := Init()
if err != nil {
panic(err)
}
SugarLogger.Debugf("ohhhhhhh err:%s", "horika")
}
运行结果
{"severity":"debug","timestamp":"2020-07-17T17:58:56.626+0800","caller":"D:/Coding/go_module/go_zap/main.go:56","message":"ohhhhhhh err:horika","MyName":"kainhuck"}
Original: https://www.cnblogs.com/kainhuck/p/13333765.html
Author: KainHuck
Title: golang使用Zap日志库
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/564414/
转载文章受原作者版权保护。转载请注明原作者出处!