-
Notifications
You must be signed in to change notification settings - Fork 574
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Multiple writers, different levels on each? #150
Comments
Huh I'm working on that also now. So far I managed to do that by implementing custom writer: package main
import (
"os"
"github.com/rs/zerolog"
)
type FilteredWriter struct {
w zerolog.LevelWriter
level zerolog.Level
}
func (w *FilteredWriter) Write(p []byte) (n int, err error) {
return w.w.Write(p)
}
func (w *FilteredWriter) WriteLevel(level zerolog.Level, p []byte) (n int, err error) {
if level >= w.level {
return w.w.WriteLevel(level, p)
}
return len(p), nil
}
func main() {
fAll, _ := os.OpenFile("./test-all.log", os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644)
fWarn, _ := os.OpenFile("./test-warn.log", os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644)
errWriter := zerolog.MultiLevelWriter(fWarn)
filteredWriter := &FilteredWriter{errWriter, zerolog.WarnLevel}
w := zerolog.MultiLevelWriter(fAll, zerolog.ConsoleWriter{Out: os.Stdout}, filteredWriter)
mainLog := zerolog.New(w).With().Str("some_key", "some_val").Timestamp().Logger()
mainLog.Debug().Msg("🛠️ Some trace")
mainLog.Info().Msg("👌 Should work")
mainLog.Warn().Msg("⚠️ My first warning")
mainLog.Error().Msg("🛑 My last warning")
mainLog.Fatal().Msg("💣 Kaboom!")
} It works although solution is far from being perfect because there is no way to attach different fields to different outputs. I would expect something like that to work but unfortunately it doesn't and I have no idea how to make it to work. Expected but doesn't work: package main
import (
"os"
"github.com/rs/zerolog"
)
func main() {
fAll, _ := os.OpenFile("./test-all.log", os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644)
fWarn, _ := os.OpenFile("./test-warn.log", os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644)
rootLogger := zerolog.New(fAll).With().Str("some_key", "some_val").Timestamp().Logger()
warnLogger := zerolog.New(fWarn).With().Str("additional", "context").Logger().Level(zerolog.WarnLevel)
consoleLogger := zerolog.New(zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: "15:04:05"})
w := zerolog.MultiLevelWriter(rootLogger, warnLogger, consoleLogger)
mainLog := zerolog.New(w)
mainLog.Debug().Msg("🛠️ Some trace")
mainLog.Info().Msg("👌 Should work")
mainLog.Warn().Msg("⚠️ My first warning")
mainLog.Error().Msg("🛑 My last warning")
mainLog.Fatal().Msg("💣 Kaboom!")
} |
I guess chaining loggers this way would double encode your logs, you can't chain zerologgers this way. This type of complexe logging routing with custom per output fields is not supported by zerolog. |
this is so simple.
main.go:
check https://github.com/uniqss/gostudy/tree/master/log_test/log_test_zerolog for detail. |
in k8s we try to do this: i did not found elegant way to implement that with zerolog |
Implement a writer like this: type LevelWriter struct {
io.Writer
ErrorWriter io.Writer
}
func (lw *LevelWriter) WriteLevel(l zerolog.Level, p []byte) (n int, err error) {
w := lw
if l > zerolog.InfoLevel {
w = lw.ErrorWriter
}
return w.Write(p)
} |
thanks!! work like a charm |
I changed a bit more: type LevelWriter struct {
io.Writer
Level zerolog.Level
}
func (lw *LevelWriter) WriteLevel(l zerolog.Level, p []byte) (n int, err error) {
if l >= lw.Level { // Notice that it's ">=", not ">"
return lw.Writer.Write(p)
}
return len(p), nil
} Since I just want to skip logging when the log level is lower than the set level, so I return Lines 76 to 88 in d894f12
Use case: consoleWriter := zerolog.NewConsoleWriter(
func(w *zerolog.ConsoleWriter) {
w.Out = os.Stderr
},
)
// "Writer" is just the the anonymous field "io.Writer" in the struct
consoleWriterLeveled := &LevelWriter{Writer: consoleWriter, Level: zerolog.DebugLevel}
fileWriter := &lumberjack.Logger{
Filename: "log/server.log",
MaxSize: 1,
MaxAge: 30,
MaxBackups: 5,
LocalTime: false,
Compress: false,
}
fileWriterLeveled := &LevelWriter{Writer: fileWriter, Level: zerolog.WarnLevel}
log.Logger = log.Output(zerolog.MultiLevelWriter(consoleWriterLeveled, fileWriterLeveled)) |
I am having similar use case. I have multiple log categories ie access logs, application logs, transactional logs. I want them to store in separate files. I tried multiple way but no luck. Is there anything Zerolog provides? |
What about you tried and what exactly didn't work. This works well for me. |
@mitar its for LevelWriter. ZeroLog provides method |
I think you should open another issue about your use case. This issue is about multiple writers with different levels. |
#573 added |
Hi @mitar, can you please give me an example of how to print different levels to different outputs (the common usage- print errors to stderr and info to stdout)? I'm trying to do that but I even can't find the |
I do not think With that, you can do something like (untested code): writers := []io.Writer{
&zerolog.FilteredLevelWriter{
Writer: zerolog.LevelWriterAdapter{os.Stdout},
Level: zerolog.InfoLevel,
},
&zerolog.FilteredLevelWriter{
Writer: zerolog.LevelWriterAdapter{os.Stderr},
Level: zerolog.ErrorLevel,
},
}
writer := zerolog.MultiLevelWriter(writers...)
logger := zerolog.New(writer).Level(zerolog.InfoLevel).With().Timestamp().Logger() Do notice that this will write both info and error levels to stdout, and error levels to stderr. |
I don't like it prints errors to both stdout and stderr. I think I will use a hook to print errors with a second logger. |
You can check the code of |
Thanks, I did it! I moved the discussion to StackOverflow 🙂 |
Hi,
I'm trying to configure zerolog to output logs both to the console and a file, with different formats. I can easily do that with
ConsoleWriter
andio.MultiWriter
.But I'm also trying to have the different log destinations log different levels.
I couldn't find a way do it. I tried to see if a Hook would solve it, but apparently the hooks seem to apply before the logs are sent to the Writers.
Is there a way to do it?
Thanks
The text was updated successfully, but these errors were encountered: