Zap logger 是不是支持转义字符 '\n' 和 '\t' 来打印换行错误verbose 或 stacktrace

Posted

技术标签:

【中文标题】Zap logger 是不是支持转义字符 \'\\n\' 和 \'\\t\' 来打印换行错误verbose 或 stacktrace【英文标题】:Does Zap logger support escape character '\n' and '\t' to print new line errorVerbose or stacktraceZap logger 是否支持转义字符 '\n' 和 '\t' 来打印换行错误verbose 或 stacktrace 【发布时间】:2021-12-11 18:58:17 【问题描述】:
func InitLogger() 
    loggerMgr, err := zap.NewProduction()
    if err != nil 
        log.Println("error")
    
    defer loggerMgr.Sync()
    logger := loggerMgr.Sugar()
    logger.Error("START!")

结果

"level":"error","ts":1635248463.347698,"caller":"cgw-go-utils/main.go:36","msg":"START!","stacktrace":" main.raiseError\n\t/Users/I053322/dev/repo/cgw-go-utils/main.go:36\nmain.main\n\t/Users/I053322/dev/repo/cgw-go-utils/ main.go:22\nruntime.main\n\t/usr/local/opt/go/libexec/src/runtime/proc.go:225"

我想通过转义得到结果

"level":"error","ts":1635248463.347698,"caller":"cgw-go-utils/main.go:36","msg":"START!","stacktrace":"main.raiseError
    /Users/I053322/dev/repo/cgw-go-utils/main.go:36
main.main
    /Users/I053322/dev/repo/cgw-go-utils/main.go:22
runtime.main
    /usr/local/opt/go/libexec/src/runtime/proc.go:225"

【问题讨论】:

是什么阻止您在错误消息中添加 \n 或 \t 以自行测试? 我没有添加\n \t它是zap框架添加的 【参考方案1】:

没有。

zap.NewProduction() 返回一个带有 JSON 编码的记录器,而 \n\t 的转义序列被逐字编码成 JSON。如果没有,它就不是有效的 JSON。

如果你真的必须,并且你可以生成无效的 JSON,你可以通过装饰现有的 zap JSON 编码器来实现你自己的编码器。

演示代码:

package main

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

func main() 
    core := zapcore.NewCore(
        &EscapeSeqJSONEncoder Encoder: zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()) ,
        os.Stdout,
        zapcore.InfoLevel,
    )
    logger := zap.New(core)
    logger.Info("foo", zap.String("some_field", "foo\nbar"))


type EscapeSeqJSONEncoder struct 
    zapcore.Encoder


func (enc *EscapeSeqJSONEncoder) Clone() zapcore.Encoder 
    return enc // TODO: change me


func (enc *EscapeSeqJSONEncoder) EncodeEntry(entry zapcore.Entry, fields []zapcore.Field) (*buffer.Buffer, error) 
    // call EncodeEntry on the embedded interface to get the 
    // original output
    b, err := enc.Encoder.EncodeEntry(entry, fields)
    if err != nil 
        return nil, err
    
    newb := buffer.NewPool().Get()

    // then manipulate that output into what you need it to be
    newb.Write(bytes.Replace(b.Bytes(), []byte("\\n"), []byte("\n"), -1))
    return newb, nil

输出:

"level":"info","ts":1635257984.618096,"msg":"foo","some_field":"foo
bar"

注意事项:函数zapcore.NewCore 接受一个zapcore.Encoder 参数,它是一个接口。这个接口实现起来很麻烦。想法是将其嵌入到您的自定义结构中,以便您免费获得所有方法。

【讨论】:

以上是关于Zap logger 是不是支持转义字符 '\n' 和 '\t' 来打印换行错误verbose 或 stacktrace的主要内容,如果未能解决你的问题,请参考以下文章

如何在 go-kit 中使用 zap logger?

Zap logger 打印到控制台和日志文件

如何在单元测试中正确捕获 zap logger 输出

golang zap_logger

如何测试从自定义配置构建的 zap Logger 的日志记录?

golang高性能日志库zap配置示例