I'm using zerolog
for Go logging:
zerolog.SetGlobalLevel(zerolog.InfoLevel)
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: "15:04:05"})
This prints all the messages into the os.Stderr
, but I want to split the logs into multiple outputs, with the next condition:
DebugLevel
, InfoLevel
, and WarnLevel
will be printed to os.Stdout
,
and ErrorLevel
, FatalLevel
, and PanicLevel
will be printed to os.Stderr
.
How can I achieve that?
You need to use MultiLevelWriter
, to forward the logs into multiple LevelWriter
s outputs (although it is not in the function signature, you should give it LevelWriter
s, otherwise it will not do any special logic).
The LevelWriter
is an interface with io.Writer
and WriteLevel(level Level, p []byte) (n int, err error)
, so you can add any zerolog
writer you want (since it is an io.Writer
), and use it with a level condition on WriteLevel
.
Here is an example for a LevelWriter
:
type SpecificLevelWriter struct {
io.Writer
Levels []zerolog.Level
}
func (w SpecificLevelWriter) WriteLevel(level zerolog.Level, p []byte) (int, error) {
for _, l := range w.Levels {
if l == level {
return w.Write(p)
}
}
return len(p), nil
}
Now you need to use it twice with MultiLevelWriter
:
func CreateLogger() zerolog.Logger {
writer := zerolog.MultiLevelWriter(
SpecificLevelWriter{
Writer: zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: "15:04:05"},
Levels: []zerolog.Level{
zerolog.DebugLevel, zerolog.InfoLevel, zerolog.WarnLevel,
},
},
SpecificLevelWriter{
Writer: zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: "15:04:05"},
Levels: []zerolog.Level{
zerolog.ErrorLevel, zerolog.FatalLevel, zerolog.PanicLevel,
},
},
)
return zerolog.New(writer).Logger()
}
Note that as I said, zerologs
loggers are io.Writer
, you can replace the os.Stdout
with zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: "15:04:05"}