Search code examples
gologginggo-zap

How to simply read from stdout with zap.logger (and without creating files)


For test purposes now I have this configuration of zapLogger with writing to "errors.log". In test I read the file, compare some needed texts and delete it when test is finished.

l := logger.New(zap.Config{Level: level, Encoding: "json", OutputPaths: []string{"errors.log"}}).
    With(zap.String("app-env", cfg.APP.Environment), zap.String("app-version", cfg.APP.Version))

//reading logs in different file...
data, _ := os.ReadFile("errors.log")
actual := string(data)

Is it possible to do that without creating file and reading from the os.Stdout or saving logs to buffer? I tried several times but with no luck.

What should I change here to be able to read logs in my test without creating a file?


Solution

  • Seems like there's a construction method func New(core zapcore.Core, options ...Option) (https://github.com/uber-go/zap/blob/master/logger.go#L67) For the Core there's a construction method func NewCore(enc Encoder, ws WriteSyncer, enab LevelEnabler) (https://github.com/uber-go/zap/blob/master/zapcore/core.go#L58), with ws specifying where to write the data to. You can just setup a bytes.Buffer as such a WriteSyncer and pass it.

    Note that for errors occuring on logging there seems to be another WriteSyncer to be set up. You can pass an ErrorOutput option (https://github.com/uber-go/zap/blob/master/options.go#L55) for then when you create a new logger.

    Here's a sketch:

    import (
        "go.uber.org/zap"
        "go.uber.org/zap/zapcore"
    )
    
    var buff bytes.Buffer
    var errorBuff bytes.Buffer
    logger := zap.New(
        zapcore.NewCore(zapcore.NewJSONEncoder(
            zapcore.EncoderConfig{}), zapcore.AddSync(&buff),
            zapcore.DPanicLevel
        ),
        zap.ErrorOutput(zapcore.AddSync(&errorBuff)),
    )