如何向 ZAP 日志条目添加新列/字段?

Posted

技术标签:

【中文标题】如何向 ZAP 日志条目添加新列/字段?【英文标题】:How to add new columns/fields to a ZAP log entry? 【发布时间】:2018-12-17 02:20:50 【问题描述】:

我有以下日志结构:

[STDERR] 2018-07-09 11:06:16.003    INFO    some_pkg/main.go:232    Logging message 1   "pid": 8842, "process": "some_process"
[STDERR] 2018-07-09 11:06:16.006    DEBUG   some_pkg/main.go:291    Logging message 2   "pid": 8842, "process": "other_process"
[STDERR] 2018-07-09 11:06:16.009    INFO    some_pkg/main.go:345    Logging message 3   "pid": 8842, "process": "some_process"

在这个日志记录sn-p中可以看到有五种类型的信息。有日期/时间、日志级别、发生、消息和 JSON 字段([STDERR] 字段除外)。这意味着我的日志结构中有五列。我想添加一个带有键 pidprocess 的新列(来自 JSON)。我应该如何使用 ZAP 编码器和配置来做到这一点?我在 ZAP 文档中没有找到解决方案。

我使用以下代码将字段添加到日志记录:

logger = logger.With(zap.FieldKey: "pid", Type: zapcore.Int64Type, Integer: int64(os.Getpid()))

但是 pid 字段的值转到 JSON(您可以在上面看到),我希望在新列中看到它。 ZAP 中有一种简单的方法可以做到这一点吗?

在前面的例子中,我想要的结构如下:

[STDERR] 2018-07-09 11:06:16.003    INFO    some_pkg/main.go:232    Logging message 1   8842    some_process
[STDERR] 2018-07-09 11:06:16.006    DEBUG   some_pkg/main.go:291    Logging message 2   8836    other_process
[STDERR] 2018-07-09 11:06:16.009    INFO    some_pkg/main.go:345    Logging message 3   8842    some_process

【问题讨论】:

【参考方案1】:

没有很好的方法来做到这一点。这个答案提供了一个解释、一个非解决方案和一个 hack。

解释

首先让我澄清一下术语:您所说的日志“列”是zapcore.Entry的字段,即日志条目。列间距由zapcore.EncoderConfig 的字段ConsoleSeparator 给出,默认为\t

日志条目的格式发生在consoleEncoder 类型的EncodeEntry 方法中,但您无法自定义其行为:zapcore.Entry 是一个结构,在该实现中没有可以利用的钩子更改记录字段的内容和时间。向 zap 团队提出这个请求可能是值得的。

非解决方案

您剩下的第一个选项是实现自己的编码器并使用它来构造zapcore.Core

enc := &customEncoder 
logger := zap.New(zapcore.NewCore(enc, os.Stderr, zap.NewAtomicLevelAt(zap.DebugLevel)))

自定义编码器必须实现zapcore.Encoder。这带来了许多问题,例如日志条目字段的顺序、可能存在的堆栈跟踪、编码器的配置选项、代码重用等。不值得深入所有细节;我只想说,为这个用例实现zapcore.Encoder非常尴尬,并且可能不值得维护负担。

破解

默认控制台编码器打印的zapcore.Entry 的最后一个字段是Message。所以你可以做的是预先格式化消息:

pid := 8842
procname := "some_process"

msg := fmt.Sprintf("Logging message 1\t%d\t%s", pid, procname)
logger.Info(msg)

将打印:

[STDERR] 2018-07-09 11:06:16.003 INFO some_pkg/main.go:232 记录消息 1 8842 some_process

【讨论】:

【参考方案2】:

请求的日志记录样式将混合结构化日志记录 (json) 和非结构化日志记录(控制台中的所有其他字段)。

blackgreen 的回答应该使它成为可能并且它是一个很好的 hack,但我认为这里更大的问题是你正在与 zap 提供的东西作斗争(快速、结构化、Go 中的水平登录.).

推荐的方法是将所有内容放在 json 中,并在您使用的任何日志查看器中解析 json 键。生成的日志结构类似于:

"timeStamp": "2018-07-09 11:06:16.003", "level": "INFO", "source": "some_pkg/main.go:232", "msg": "Logging message 1", "pid": 8842, "process": "some_process"

【讨论】:

以上是关于如何向 ZAP 日志条目添加新列/字段?的主要内容,如果未能解决你的问题,请参考以下文章

如何向过滤查询中添加新字段

向 BigQuery 中的历史表添加新字段

Windows Universal现有应用程序向SQLite表添加新列

Python日志记录:如何向LogRecord添加自定义字段,并注册全局回调以设置其值

Rails 4 在模型中添加新列或字段

无法使用 dict 类型作为字段条目将数据添加到 InfluxDB