如何使用 uber-go/zap 根据日志级别记录到 stdout 或 stderr?

Yur*_*rov 4 logging go go-zap

我正在尝试使用这个包设置日志记录github.com/uber-go/zap。我需要写:

  • 信息记录到标准输出
  • 错误和致命日志记录到 stderr

zap.Config我尝试通过这样的设置和构建来做到这一点:

    cfg = &zap.Config{
        Encoding:         "json",
        Level:            zap.NewAtomicLevelAt(zapcore.DebugLevel),
        OutputPaths:      []string{"stdout"},
        ErrorOutputPaths: []string{"stderr"},
        EncoderConfig: zapcore.EncoderConfig{
            MessageKey: "message",

            LevelKey:    "level",
            EncodeLevel: zapcore.CapitalLevelEncoder,

            TimeKey:    "time",
            EncodeTime: zapcore.ISO8601TimeEncoder,

            CallerKey:    "caller",
            EncodeCaller: zapcore.ShortCallerEncoder,

            EncodeDuration: zapcore.MillisDurationEncoder,
        },
    }
Run Code Online (Sandbox Code Playgroud)

我也尝试过这种方式:

cfg = zap.NewProductionConfig()
    cfg.OutputPaths = []string{"stdout"}
    logger, err = cfg.Build(zap.AddCaller(), zap.AddCallerSkip(1))
Run Code Online (Sandbox Code Playgroud)

但所有日志都写入 stdoutstderr。我怎样才能将它分开?

bla*_*een 7

zapcore.NewTee与两个核心一起使用:

\n
    \n
  • zapcore.InfoLevel锁定到标准输出的一个
  • \n
  • 一个可以锁定zapcore.ErrorLevel并发zapcore.FatalLevel送到 stderr 的
  • \n
\n

这是一个演示用法的最小程序:

\n
package main\n\nimport (\n    "go.uber.org/zap"\n    "go.uber.org/zap/zapcore"\n    "os"\n)\n\nfunc main() {\n    // info level enabler\n    infoLevel := zap.LevelEnablerFunc(func(level zapcore.Level) bool {\n        return level == zapcore.InfoLevel\n    })\n\n    // error and fatal level enabler\n    errorFatalLevel := zap.LevelEnablerFunc(func(level zapcore.Level) bool {\n        return level == zapcore.ErrorLevel || level == zapcore.FatalLevel\n    })\n\n    // write syncers\n    stdoutSyncer := zapcore.Lock(os.Stdout)\n    stderrSyncer := zapcore.Lock(os.Stderr)\n\n    // tee core\n    core := zapcore.NewTee(\n        zapcore.NewCore(\n            zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()),\n            stdoutSyncer,\n            infoLevel,\n        ),\n        zapcore.NewCore(\n            zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()),\n            stderrSyncer,\n            errorFatalLevel,\n        ),\n    )\n\n    // finally construct the logger with the tee core\n    logger := zap.New(core)\n\n    logger.Info("info log")\n    logger.Error("error log")\n}\n
Run Code Online (Sandbox Code Playgroud)\n

请注意,上面的程序记录了两条消息,一条处于信息级别,一条处于错误级别。要查看它是否将两者都打印到正确的设备,请运行它并将 stdout 或 stderr 重定向到/dev/null\xe2\x80\x94 ,从而仅将另一个打印到控制台:

\n
$ go build main.go\n\n$ ./main 2>/dev/null # shows only stdout\n{"level":"info","ts":1626900981.520349,"msg":"info log"}\n\n$ ./main 1>/dev/null # shows only stderr\n{"level":"error","ts":1626901025.056065,"msg":"error log"}\n
Run Code Online (Sandbox Code Playgroud)\n