Fork me on GitHub

版权声明 本站原创文章 由 萌叔 发表
转载请注明 萌叔 | https://vearne.cc

1. 前言

uber开源的高性能日志库zap, 除了性能远超logrus之外,还有很多诱人的功能,比如支持数据采样、支持通过HTTP服务动态调整日志级别。

前些天有同事问我,zap默认打印的日志格式,我不喜欢,可否自定义一下。
这个是日志库应该有的功能,zap怎么可能不支持。

下面我们来谈谈如何自定义日志格式,在zap中,它被称为Encoder, 在日志库中logrus,被做Formatter

2. 默认格式

目前 zap只支持2种日志格式

2.1 console

1.5392310605133479e+09  info    golab/test_zap.go:34    Info log    {"name": "buick2008", "age": 15}

2.2 json

{"level":"info","ts":1539234945.009923,"caller":"golab/test_zap.go:34","msg":"Info log","name":"buick2008","age":15}

3. 实现

1) 为了实现自定义的Encoder 需要实现
zapcore.Encoder
zapcore.PrimitiveArrayEncoder
所定义的接口

大部分接口实现可以照抄zapcore.jsonEncoder的代码实现
真正需要改动的是

EncodeEntry(ent zapcore.Entry, fields [] zapcore.Field) (*buffer.Buffer, error)

2) 注册Encoder

    // 注册Encoder
    zap.RegisterEncoder("console2", MyEncoding)

用法示例

package main

import (
    "fmt"
    "go.uber.org/zap"
    "go.uber.org/zap/zapcore"
    "time"
    "github.com/vearne/golab/myencoder"
)


func MyEncoding(config zapcore.EncoderConfig) (zapcore.Encoder, error) {
    return myencoder.NewConsole2Encoder(config, true), nil
}


func main() {
    // 注册一个Encoder
    zap.RegisterEncoder("console2", MyEncoding)

    // 默认是Info级别
    logcfg := zap.NewProductionConfig()
    // 启用自定义的Encoding
    logcfg.Encoding = "console2"

    logger, err := logcfg.Build()
    if err != nil {
        fmt.Println("err", err)
    }

    defer logger.Sync()
    for i := 0; i < 3; i++ {
        time.Sleep(1 * time.Second)
        logger.Info("some message", zap.String("name", "buick2008"),
            zap.Int("age", 15))
    }
}

打印出的日志效果

"level": "info", "caller": "golab/test_zap.go:34", "msg": "some message"$$$ "name": "buick2008", "age": 15

这里用"$$$"分隔了msg 和 fields 这2部分

完整代码请见
vearne/golab
主要涉及的文件
test_zap.go
console2_encoder.go

注意 由于时间原因,笔者并没有完整实现
zapcore.Encoder
zapcore.PrimitiveArrayEncoder
所定义的接口,请勿直接在生产环境使用

推荐阅读


微信公众号

4 对 “玩转高性能日志库zap(4)–自定义日志格式”的想法;

    1. config := zap.NewProductionConfig()
      DefaultLogger, _ = config.Build()
      

      其中的Sampling就是设置采样的

      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"},
          }
      }
      
          // Sampling sets a sampling policy. A nil SamplingConfig disables sampling.
          Sampling *SamplingConfig `json:"sampling" yaml:"sampling"`
      

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注