Zap记录器将日志同时输出到控制台和日志文件

6

我已经将Zap集成到我的Go应用程序中,我们有两个日志文件打印日志,我还使用Lumberjack进行日志轮换。但是我也想在控制台上显示日志,但是目前没有成功。以下是我的logger.go代码:

var (
    Logger *zap.Logger
    N2n    *zap.Logger
)

type WriteSyncer struct {
    io.Writer
}

func (ws WriteSyncer) Sync() error {
    return nil
}

func InitLogging(mode string) {
    var cfg zap.Config
    var logName = "abc.log"
    var slogName = "n2n.log"

    if mode == "production" {
        cfg = zap.NewProductionConfig()
        cfg.DisableCaller = true
    } else {
        cfg = zap.NewDevelopmentConfig()
        cfg.EncoderConfig.LevelKey = "level"
        cfg.EncoderConfig.NameKey = "name"
        cfg.EncoderConfig.MessageKey = "msg"
        cfg.EncoderConfig.CallerKey = "caller"
        cfg.EncoderConfig.StacktraceKey = "stacktrace"
    }

    cfg.Encoding = "json"
    cfg.EncoderConfig.TimeKey = "timestamp"
    cfg.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
    cfg.OutputPaths = []string{logName}
    sw := getWriteSyncer(logName)
    swSugar := getWriteSyncer(slogName)

    l, err := cfg.Build(SetOutput(sw, cfg))
    if err != nil {
        panic(err)
    }
    defer l.Sync()

    ls, err := cfg.Build(SetOutput(swSugar, cfg))
    if err != nil {
        panic(err)
    }
    defer ls.Sync()

    Logger = l
    N2n = ls
}

// SetOutput replaces existing Core with new, that writes to passed WriteSyncer.
func SetOutput(ws zapcore.WriteSyncer, conf zap.Config) zap.Option {
    var enc zapcore.Encoder
    switch conf.Encoding {
    case "json":
        enc = zapcore.NewJSONEncoder(conf.EncoderConfig)
    case "console":
        enc = zapcore.NewConsoleEncoder(conf.EncoderConfig)
    default:
        panic("unknown encoding")
    }

    return zap.WrapCore(func(core zapcore.Core) zapcore.Core {
        return zapcore.NewCore(enc, ws, conf.Level)
    })
}

func getWriteSyncer(logName string) zapcore.WriteSyncer {
    var ioWriter = &lumberjack.Logger{
        Filename:   logName,
        MaxSize:    10, // MB
        MaxBackups: 3,  // number of backups
        MaxAge:     28, //days
        LocalTime:  true,
        Compress:   false, // disabled by default
    }
    var sw = WriteSyncer{
        ioWriter,
    }
    return sw
}

我尝试过附加输出路径,但并没有起作用。

4个回答

12

由于这是在谷歌上搜索后出现的第一件事,因此这里提供了一个简单的示例,演示如何在控制台和日志文件中显示日志,可以使用任何io.Writer作为lumberjack使用的那个:

func logInit(d bool, f *os.File) *zap.SugaredLogger {

    pe := zap.NewProductionEncoderConfig()

    fileEncoder := zapcore.NewJSONEncoder(pe)

    pe.EncodeTime = zapcore.ISO8601TimeEncoder # The encoder can be customized for each output
    consoleEncoder := zapcore.NewConsoleEncoder(pe)

    level := zap.InfoLevel
    if d {
        level = zap.DebugLevel
    }

    core := zapcore.NewTee(
        zapcore.NewCore(fileEncoder, zapcore.AddSync(f), level),
        zapcore.NewCore(consoleEncoder, zapcore.AddSync(os.Stdout), level),
    )

    l := zap.New(core) # Creating the logger

    return l.Sugar()
}

我使用了默认的ProductionEncoderConfig,但也可以使用自定义的配置,例如OP代码中的那个。


6

我发现zapcore有zapcore.NewMultiWriteSyncer,它可以将日志写入文件并使用zapcore.addSync(os.stdout)在控制台上输出。

例如:

swSugar := zapcore.NewMultiWriteSyncer(
    zapcore.AddSync(os.Stdout), 
    getWriteSyncer(logfileName),
)

0

你也可以使用 zap.CombineWriteSyncers

CombineWriteSyncers 是一个实用程序,它将多个 WriteSyncer 组合成单个、锁定的 WriteSyncer。如果没有输入被提供,则返回一个空操作的 WriteSyncer。

它仅作为一种便利提供;结果与分别使用 zapcore.NewMultiWriteSyncer 和 zapcore.Lock 没有区别。

    syncer := zap.CombineWriteSyncers(os.Stdout, getWriteSyncer(logfileName))

    core := zapcore.NewCore(enc, syncer, zap.NewAtomicLevelAt(zap.InfoLevel))
    zap.New(core)

0

登录多个来源的最简单方法是使用zapper包。创建config.yml

outputPaths:
  - stdout
  - /var/log/abc.log
  - /var/log/n2n.log

errorOutputPaths:
  - stderr
  - /var/log/abc.log
  - /var/log/n2n.log

然后初始化 Zap 记录器:

package main

import "github.com/nafigator/zapper"

func main() {
    path := "/path/to/config.yml"
    log  := zapper.Must(&path, nil)

    log.Info("Log into multiple sources: OK")
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接