[uber-zap/part3] custom recorder

Keywords: Go encoding

Explain

  • A previous translation of a tutorial (without backing up the original address, the ladder was sealed). Add the original address after finding it

text

The field coder provided by zap is not necessarily suitable for its own needs, such as: the output of log records is expected to be similar to syslog or other common log formats; the time stamp in the log may be expected to ignore seconds; the log is included in square brackets, etc., when a custom coder is needed.

Performance factor

You can customize the coder time,leve,caller, etc. It should be noted that the encoder should be as efficient as possible, because this is the memory and performance advantage of zap, after all, every log line calls these functions. So avoid creating temporary variables or doing any high-intensity calculations.

In other words, the following example is just a demonstration, not necessarily the best alternative to default functionality.

Custom timestamp format

This is a common implementation of syslog format

func SyslogTimeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
    enc.AppendString(t.Format("jan 2 15:04:05"))
}

func main() {
    cfg := zap.Config{
        Encoding:    "console",
        Level:       zap.NewAtomicLevelAt(zap.DebugLevel),
        OutputPaths: []string{"stderr"},

        EncoderConfig: zapcore.EncoderConfig{
            MessageKey: "message",

            TimeKey: "time",
        },
    }

    cfg.EncoderConfig.EncodeTime = SyslogTimeEncoder

    logger, _ := cfg.Build()
    logger.Info("This should have a syslog style timestamp")
}

output

jan 1 09:22:59  This should have a syslog style timestamp

It should be noted that the encoder should attach primitives to the object array. zap uses this array to efficiently encode output with minimal memory allocation

Custom Level Format

func CustomLevelEncoder(level zapcore.Level, enc zapcore.PrimitiveArrayEncoder) {
    enc.AppendString("[" + level.CapitalString() + "]")
}

func main() {
    cfg := zap.Config{
        Encoding:    "console",
        Level:       zap.NewAtomicLevelAt(zap.DebugLevel),
        OutputPaths: []string{"stderr"},

        EncoderConfig: zapcore.EncoderConfig{
            MessageKey: "message",

            LevelKey: "level",
        },
    }

    cfg.EncoderConfig.EncodeLevel = CustomLevelEncoder

    logger, _ := cfg.Build()
    logger.Info("This should have a bracketed level name")
}

output

[INFO]  This should have a bracketed level name

Note: In the above example, multiple substrings are spliced together to form a string and attached to an array. This may result in temporary memory allocation. I have to do this. If I attach substrings separately, zap treats them as separate fields in the output and separates them with spaces.

Posted by jsantama on Mon, 01 Apr 2019 02:15:29 -0700