前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >聊聊golang的zap的NewProduction

聊聊golang的zap的NewProduction

作者头像
code4it
发布2020-12-11 10:37:01
8930
发布2020-12-11 10:37:01
举报
文章被收录于专栏:码匠的流水账码匠的流水账

文主要研究一下uber的zap的NewProduction。

golang的log有zap、logrus等,不过logrus现在已经处于维护状态。

实例

SugaredLogger

代码语言:javascript
复制
func main() {
    logger, _ := zap.NewProduction()
    defer logger.Sync() // flushes buffer, if any
    sugar := logger.Sugar()
    url := "https://abc.com"
    sugar.Infow("failed to fetch URL",
        // Structured context as loosely typed key-value pairs.
        "url", url,
        "attempt", 3,
        "backoff", time.Second,
    )
}

SugaredLogger比普通的结构化logging包快4-10倍

输出

代码语言:javascript
复制
{"level":"info","ts":1607095287.638658,"caller":"log-demo/zap_demo.go:14","msg":"failed to fetch URL","url":"https://abc.com","attempt":3,"backoff":1}

Logger

代码语言:javascript
复制
func main() {
    logger, _ := zap.NewProduction()
    defer logger.Sync()
    url := "https://abc.com"
    logger.Info("failed to fetch URL",
        // Structured context as strongly typed Field values.
        zap.String("url", url),
        zap.Int("attempt", 3),
        zap.Duration("backoff", time.Second),
    )
}

当对性能和类型安全都要求比较高的场景就使用Logger,它比SugaredLogger速度更快,但是它只支持结构化logging

输出

代码语言:javascript
复制
{"level":"info","ts":1607095675.5623732,"caller":"log-demo/zap_demo.go:25","msg":"failed to fetch URL","url":"https://abc.com","attempt":3,"backoff":1}

NewProduction

zap@v1.16.0/logger.go

代码语言:javascript
复制
func NewProduction(options ...Option) (*Logger, error) {
    return NewProductionConfig().Build(options...)
}

NewProduction内部执行NewProductionConfig().Build方法

NewProductionConfig

zap@v1.16.0/config.go

代码语言:javascript
复制
func NewProductionConfig() Config {
    return Config{
        Level:       NewAtomicLevelAt(InfoLevel),
        Development: false,
        Sampling: &SamplingConfig{
            Initial:    100,
            Thereafter: 100,
        },
        Encoding:         "json",
        EncoderConfig:    NewProductionEncoderConfig(),
        OutputPaths:      []string{"stderr"},
        ErrorOutputPaths: []string{"stderr"},
    }
}

NewProductionConfig方法按默认参数创建了Config,其中encoding为json,output为std

NewProductionEncoderConfig

zap@v1.16.0/config.go

代码语言:javascript
复制
func NewProductionEncoderConfig() zapcore.EncoderConfig {
    return zapcore.EncoderConfig{
        TimeKey:        "ts",
        LevelKey:       "level",
        NameKey:        "logger",
        CallerKey:      "caller",
        FunctionKey:    zapcore.OmitKey,
        MessageKey:     "msg",
        StacktraceKey:  "stacktrace",
        LineEnding:     zapcore.DefaultLineEnding,
        EncodeLevel:    zapcore.LowercaseLevelEncoder,
        EncodeTime:     zapcore.EpochTimeEncoder,
        EncodeDuration: zapcore.SecondsDurationEncoder,
        EncodeCaller:   zapcore.ShortCallerEncoder,
    }
}

NewProductionEncoderConfig这里创建了zapcore.EncoderConfig

Build

zap@v1.16.0/config.go

代码语言:javascript
复制
func (cfg Config) Build(opts ...Option) (*Logger, error) {
    enc, err := cfg.buildEncoder()
    if err != nil {
        return nil, err
    }

    sink, errSink, err := cfg.openSinks()
    if err != nil {
        return nil, err
    }

    if cfg.Level == (AtomicLevel{}) {
        return nil, fmt.Errorf("missing Level")
    }

    log := New(
        zapcore.NewCore(enc, sink, cfg.Level),
        cfg.buildOptions(errSink)...,
    )
    if len(opts) > 0 {
        log = log.WithOptions(opts...)
    }
    return log, nil
}

Build方法执行cfg.buildEncoder()、cfg.openSinks()、zapcore.NewCore及New方法

New

zap@v1.16.0/logger.go

代码语言:javascript
复制
func New(core zapcore.Core, options ...Option) *Logger {
    if core == nil {
        return NewNop()
    }
    log := &Logger{
        core:        core,
        errorOutput: zapcore.Lock(os.Stderr),
        addStack:    zapcore.FatalLevel + 1,
    }
    return log.WithOptions(options...)
}

func NewNop() *Logger {
    return &Logger{
        core:        zapcore.NewNopCore(),
        errorOutput: zapcore.AddSync(ioutil.Discard),
        addStack:    zapcore.FatalLevel + 1,
    }
}

这里对于core为nil的返回的是NewNop,否则实例化Logger;NewNop返回的logger的core为zapcore.NewNopCore()

Logger

zap@v1.16.0/logger.go

代码语言:javascript
复制
type Logger struct {
    core zapcore.Core

    development bool
    name        string
    errorOutput zapcore.WriteSyncer

    addCaller bool
    addStack  zapcore.LevelEnabler

    callerSkip int
    onFatal    zapcore.CheckWriteAction // default is WriteThenFatal
}

Logger定义了core、development、name、errorOutput、addCaller、addStack、callerSkip、onFatal属性

小结

zap.NewProduction()通过创建NewProductionEncoderConfig再Build出Logger,其中Logger的New方法主要设置了core、errorOutput、addStack属性

doc

  • zap
  • How to implement level based logging in golang?
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-12-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码匠的流水账 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 实例
    • SugaredLogger
      • Logger
      • NewProduction
      • NewProductionConfig
      • NewProductionEncoderConfig
      • Build
      • New
      • Logger
      • 小结
      • doc
      相关产品与服务
      日志服务
      日志服务(Cloud Log Service,CLS)是腾讯云提供的一站式日志服务平台,提供了从日志采集、日志存储到日志检索,图表分析、监控告警、日志投递等多项服务,协助用户通过日志来解决业务运维、服务监控、日志审计等场景问题。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档