(基于这个问题:Uber Zap Logger: how to prepend each log entry with a string)
我用自定义的编码器替换了我的 uber-zap 记录器的编码器,以在每个日志条目前加上 SystemD 友好的错误级别 ( <LEVEL>
),但是现在在我使用带有附加字段 ( With(fields ...Field)
) 的记录器后,自定义的前置就消失了:
package main
import (
"os"
"go.uber.org/zap"
"go.uber.org/zap/buffer"
"go.uber.org/zap/zapcore"
)
func getConfig() zap.Config {
// your current config options
return zap.NewProductionConfig()
}
type prependEncoder struct {
// embed a zapcore encoder
// this makes prependEncoder implement the interface without extra work
zapcore.Encoder
// zap buffer pool
pool buffer.Pool
}
// EncodeEntry 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 ""
}
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")
logger = logger.With(zap.String("foo", "bar"))
logger.With(zap.String("foo", "bar")).Info("this does not have the prefix :(")
}
我得到的输出是:
<6> 1.640656130756576e+09 info this is info
<7> 1.640656130756611e+09 debug this is debug
<4> 1.640656130756615e+09 warn this is warn
1.6406561307566311e+09 info this does not have the prefix :( {"foo": "bar"}
我究竟做错了什么?