[uber-zap/part2]自定义记录器

小龙虾 · · 1192 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

说明

  • 之前翻译的一个教程(没有备份原地址,梯子被封了)。原地址找到后补上

正文

使用预设的记录器可以节省时间,但如果确定要调整记录器,需要探索自定义记录器的方法

使用zap配置结构体创建记录器

可以使用配置zap.Config创建记录器,这是一个结构体,可以使用需要的值填充结构体,然后调用结构体的.Build()方法来获取记录器

cfg := zap.Config{...}
logger, err := cfg.Build()

需要注意的是:zap.Config的结构体没有默认值,至少为zap需要的三个设置提供值

  • encoder: 只需要添加个Encoding:"XXX",使用json就会创建一个JSON的encoder,另一个值是console
  • 可以使用结构zapcore.EncoderConfig来自定义encoder(几乎肯定必须这样做,因为默认的不是很好用)
  • level enabler:这是一种接口类型,它允许zap确定是否应显示特定级别的消息。在zap配置结构中,可以使用Level字段中的AtomicLevel包装器提供此类型。
  • sink: 日志的输出目标,可以使用OutputPaths字段指定多个输出路径,输出讲发送到所有这些文件。像stderrstdout也是可以的

定制encoder

仅仅在配置结构体中设置encoder的类型是不够的,默认情况下,json仅仅输出日志消息中专门提供的字段。
以下是调用.Build()方法时候不会抛出错误的最少配置了

    logger, _ := zap.Config{
        Encoding:    "json",
        Level:       zap.NewAtomicLevelAt(zap.DebugLevel),
        OutputPaths: []string{"stdout"},
    }.Build()

    logger.Info("This is an INFO message with fileds", zap.String("region", "us-west"), zap.Int("id", 2))

输出

{"region":"us-west","id":2}

可以看出,日志信息没有打印出来!
要在json encoder中添加信息,需要特别指定将在输出中具有此值的json

    logger, _ := zap.Config{
        Encoding:    "json",
        Level:       zap.NewAtomicLevelAt(zap.DebugLevel),
        OutputPaths: []string{"stdout"},
        EncoderConfig: zapcore.EncoderConfig{
            MessageKey: "message", // <---
        },
    }.Build()

    logger.Info("This is an INFO message with fileds", zap.String("region", "us-west"), zap.Int("id", 2))

输出

{"message":"This is an INFO message with fileds","region":"us-west","id":2}

zap可以像消息中添加更多的元数据,比如:level name, timestamp, caller, stacktrace等等。除非明确指出与元数据对应的JSON键,否者不会显示。
注意:这些元数据名称必须与encoder匹配,否者zap会出错

示例:

    cfg := zap.Config{
        Encoding:         "json",
        Level:            zap.NewAtomicLevelAt(zap.DebugLevel),
        OutputPaths:      []string{"stdout"},
        ErrorOutputPaths: []string{"stderr"},
        EncoderConfig: zapcore.EncoderConfig{
            MessageKey: "message", // <---

            LevelKey:    "level",
            EncodeLevel: zapcore.CapitalLevelEncoder,

            TimeKey:    "time",
            EncodeTime: zapcore.ISO8601TimeEncoder,

            CallerKey:    "caller",
            EncodeCaller: zapcore.ShortCallerEncoder,
        },
    }
    logger, _ := cfg.Build()

    logger.Info("This is an INFO message with fileds", zap.String("region", "us-west"), zap.Int("id", 2))

输出

{"level":"INFO","time":"2018-10-31T14:59:45.238+0800","caller":"zap_config/main.go:29","message":"This is an INFO message with fileds","region":"us-west","id":2}

encoder 元数据字段的其他选项

每个encoder可以根据需要进行定制,以下是zap提供的不同实现

  • timestamp可以是ISO8601格式输出,可以是seconds,milliseconds甚至nanoseconds格式输出
  • level: 可以是capital或者lowercase,它们甚至有colored选项。需要注意,颜色选项在JSON编码器中没有意义
  • caller:可以以相对格式short和绝对格式full显示

动态改变记录器行为

可以从现有的记录器克隆记录器,并对其行为进行某些修改

  • logger.AddCaller() 添加调用者
  • logger.AddStacktrace() 为给定级别以及以上的消息添加堆栈跟踪
  • logger.Fields() 将指定字段添加到新记录器输出的所有消息中。这种方式相比于在实际日志调用期间指定字段,可以降低内存分配来加快日志记录
  • logger.WrapCore() 允许你修改甚至完全替换记录器中包含的encoderlevelsink。以下是示例
fmt.Printf("\n*** Using a JSON encoder, at debug level, sending output tu stuout, all possible keys specified\n\n")

    cfg := zap.Config{
        Encoding:         "json",
        Level:            zap.NewAtomicLevelAt(zapcore.DebugLevel),
        OutputPaths:      []string{"stderr"},
        ErrorOutputPaths: []string{"stderr"},
        EncoderConfig: zapcore.EncoderConfig{
            MessageKey: "message",

            LevelKey:    "level",
            EncodeLevel: zapcore.CapitalLevelEncoder,

            TimeKey:    "time",
            EncodeTime: zapcore.ISO8601TimeEncoder,

            CallerKey:    "caller",
            EncodeCaller: zapcore.ShortCallerEncoder,
        },
    }

    logger, _ := cfg.Build()

    logger.Info("This is an INFO message")

    fmt.Printf("\n*** Same logger with console loggin enable instead\n\n")

    logger.WithOptions(
        zap.WrapCore(
            func(zapcore.Core) zapcore.Core {
                return zapcore.NewCore(zapcore.NewConsoleEncoder(cfg.EncoderConfig), zapcore.AddSync(os.Stderr), zapcore.DebugLevel)
            })).Info("This is an INFO message")

输出

*** Using a JSON encoder, at debug level, sending output tu stuout, all possible keys specified

{"level":"INFO","time":"2018-11-01T08:59:12.984+0800","caller":"wrap_core/main.go:35","message":"This is an INFO message"}

*** Same logger with console loggin enable instead

2018-11-01T08:59:12.984+0800    INFO    wrap_core/main.go:43    This is an INFO message

有疑问加站长微信联系(非本文作者)

本文来自:Segmentfault

感谢作者:小龙虾

查看原文:[uber-zap/part2]自定义记录器

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1192 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传