gpt4 book ai didi

go - 如何访问 zap Hooks 中的字段?

转载 作者:行者123 更新时间:2023-12-05 01:26:03 28 4
gpt4 key购买 nike

如何在 uber-zap 的 Hook 中访问有关日志记录事件的完整信息?

例如,我试图将 zapcore.Field 添加到日志记录事件中,但它没有显示在 zapcore.Entry 中。

如果不可能,我至少可以以某种方式获得完整格式的字符串吗?目标是在出现错误时发送电子邮件/自动消息/哨兵/等。

package main

import (
"log"

"github.com/davecgh/go-spew/spew"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)

func main() {
prodLogger, err := zap.NewProduction(zap.Hooks(func(entry zapcore.Entry) error {
if entry.Level == zapcore.ErrorLevel {
spew.Dump(entry) // fancy console printer
}

return nil
}))

if err != nil {
log.Fatal(err)
}

prodLogger.
Named("logger_name").
Error("something happened", zap.String("foo", "bar"))
}

输出 - 没有 foobar 的痕迹:

{"level":"error","ts":1640722252.899601,"logger":"logger_name","caller":"awesomep2/main.go:23","msg":"something happened","foo":"bar","stacktrace":"main.main\n\t/Users/xxx/GitHub/awesomep2/main.go:23\nruntime.main\n\t/usr/local/go/src/runtime/proc.go:255"}
(zapcore.Entry) {
Level: (zapcore.Level) error,
Time: (time.Time) 2021-12-28 13:10:52.899601 -0700 MST m=+0.000629089,
LoggerName: (string) (len=11) "logger_name",
Message: (string) (len=18) "something happened",
Caller: (zapcore.EntryCaller) /Users/xxx/GitHub/awesomep2/main.go:23,
Stack: (string) (len=103) "main.main\n\t/Users/xxx/GitHub/awesomep2/main.go:23\nruntime.main\n\t/usr/local/go/src/runtime/proc.go:255"
}

最佳答案

字段在 Zap Hook 中不可用。 zap.Hooks 的文档明确地说:

[...] Hooks are useful for simple side effects, like capturing metrics for the number of emitted logs. More complex side effects, including anything that requires access to the Entry's structured fields, should be implemented as a zapcore.Core instead. [...]

因此,要使用 go-spew 转储日志,您需要一个自定义核心。您有两个主要选择。

带有自定义编码器的自定义内核

这具有允许更多自定义的优势。

条目的字段在 zapcore.Encoder.EncodeEntry 中可用。与往常一样,该策略是将 zapcore.Encoder 嵌入到您的结构中并重新实现 EncodeEntry:

type spewDumpEncoder struct {
zapcore.Encoder
}

func (e *spewDumpEncoder) EncodeEntry(entry zapcore.Entry, fields []zapcore.Field) (*buffer.Buffer, error) {
if entry.Level == zapcore.ErrorLevel {
spew.Dump(entry, fields)
}
return e.Encoder.EncodeEntry(entry, fields)
}

如果您计划使用结构化日志记录,请记住还要实现 Clone()

使用 Write 的自定义核心

这样做的好处是允许更简单的初始化。

与第一个选项类似,zapcore.Core也是一个接口(interface),所以你可以通过嵌入到你的结构中来实现它,并且只重新实现Write:

type MyCore struct {
zapcore.Core
}

func (c *MyCore) Check(entry zapcore.Entry, checked *zapcore.CheckedEntry) *zapcore.CheckedEntry {
if c.Enabled(entry.Level) {
return checked.AddCore(entry, c)
}
return checked
}

func (c *MyCore) Write(entry zapcore.Entry, fields []zapcore.Field) error {
if entry.Level == zapcore.ErrorLevel {
spew.Dump(entry, fields)
}
return c.Core.Write(entry, fields)
}

并通过从默认的 zap 记录器中获取现有核心来实例化它:

    l, _ := zap.NewProduction()
logger := zap.New(&MyCore{Core: l.Core()})

关于go - 如何访问 zap Hooks 中的字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70512120/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com