Uber Zap Logger:如何在每个日志条目前面加上字符串

Iva*_*anD 5 go systemd systemd-journald go-zap

我将我的应用程序用作 SystemD 服务,并且需要在每条消息前添加<LEVEL>JournalD 的入门级别,例如:

<6> this is info
<7> this is debug
<4> this is warning
Run Code Online (Sandbox Code Playgroud)

否则,JournalD 将所有条目视为同一级别,我想使用其高级功能仅显示特定级别的日志。

<6>如何使用 uber-zap 库在每个日志条目前面添加正确的级别标签(例如 Info )?

编辑:这是我的记录器配置的相关部分:

<6> this is info
<7> this is debug
<4> this is warning
Run Code Online (Sandbox Code Playgroud)

bla*_*een 2

您可以使用嵌入zapcore.Encoder.

嵌入编码器可以让您使用现在拥有的相同配置“免费”实现所有方法。然后您可以仅EncodeEntry使用您需要的附加逻辑来实现。

注意:如果您Clone()计划使用结构化日志记录,例如logger.With(). 更多信息:为什么在 Uber Zap 中调用 logger.With 后自定义编码会丢失?

回到你的主要问题,这是一个有效的例子;请参阅代码中的注释以获取更多说明:

type prependEncoder struct {
    // embed a zapcore encoder
    // this makes prependEncoder implement the interface without extra work
    zapcore.Encoder

    // zap buffer pool
    pool buffer.Pool
}

// implementing only EncodeEntry
func (e *prependEncoder) EncodeEntry(entry zapcore.Entry, fields []zapcore.Field) (*buffer.Buffer, error) {
    // new log buffer
    buf := e.pool.Get()

    // prepend the JournalD prefix based on the entry level
    buf.AppendString(e.toJournaldPrefix(entry.Level))
    buf.AppendString(" ")

    // calling the embedded encoder's EncodeEntry to keep the original encoding format 
    consolebuf, err := e.Encoder.EncodeEntry(entry, fields)
    if err != nil {
        return nil, err
    }

    // just write the output into your own buffer
    _, err = buf.Write(consolebuf.Bytes())
    if err != nil {
        return nil, err
    }
    return buf, nil
}

// some mapper function
func (e *prependEncoder) toJournaldPrefix(lvl zapcore.Level) string {
    switch lvl {
    case zapcore.DebugLevel:
        return "<7>"
    case zapcore.InfoLevel:
        return "<6>"
    case zapcore.WarnLevel:
        return "<4>"
    }
    return ""
}
Run Code Online (Sandbox Code Playgroud)

稍后,您将构建一个具有使用自定义编码器的自定义核心的记录器。您可以使用您现在使用的相同编码器来初始化嵌入字段。您在下面看到的选项模仿您当前拥有的选项。

package main

import (
    "go.uber.org/zap"
    "go.uber.org/zap/buffer"
    "go.uber.org/zap/zapcore"
    "os"
)

func getConfig() zap.Config {
    // your current config options
    return config
}

func main() {
    cfg := getConfig()

    // constructing our prependEncoder with a ConsoleEncoder using your original configs
    enc := &prependEncoder{
        Encoder: zapcore.NewConsoleEncoder(cfg.EncoderConfig),
        pool:    buffer.NewPool(),
    }

    logger := zap.New(
        zapcore.NewCore(
            enc,
            os.Stdout,
            zapcore.DebugLevel,
        ),
        // this mimics the behavior of NewProductionConfig.Build
        zap.ErrorOutput(os.Stderr), 
    )

    logger.Info("this is info")
    logger.Debug("this is debug")
    logger.Warn("this is warn")
}
Run Code Online (Sandbox Code Playgroud)

测试运行输出(根据您的信息,INFO 以蓝色打印,DEBUG 以粉色打印,WARN 以黄色打印zapcore.CapitalColorLevelEncoder):

<6> INFO        this is info
<7> DEBUG       this is debug
<4> WARN        this is warn
Run Code Online (Sandbox Code Playgroud)