Golang中Zerolog将错误写入stderr其他内容写入stdout的实现方法
Golang中Zerolog将错误写入stderr其他内容写入stdout的实现方法 你好,
说实话,我有点困惑。我的一个Git仓库收到了一个问题反馈,他们问我是否可以将项目的错误信息输出到stderr,而其他所有内容输出到stdout。我正在使用zerolog和lumberjack来在命令行和文件之间分割输出。有人能帮助我或为我指明正确的方向吗?
package logger
import (
"io"
"os"
"path"
"gickup/types"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"gopkg.in/natefinch/lumberjack.v2"
)
func NewRollingFile(config types.FileLogging) io.Writer {
if config.Dir != "" {
if err := os.MkdirAll(config.Dir, 0744); err != nil {
log.Error().Err(err).Str("path", config.Dir).Msg("can't create log directory")
return nil
}
更多关于Golang中Zerolog将错误写入stderr其他内容写入stdout的实现方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于Golang中Zerolog将错误写入stderr其他内容写入stdout的实现方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
使用Zerolog实现错误日志到stderr、其他日志到stdout,可以通过MultiLevelWriter配合LevelWriter实现。以下是具体实现方法:
package logger
import (
"io"
"os"
"path"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"gopkg.in/natefinch/lumberjack.v2"
)
// 创建分级输出writer
func createLevelWriters(config types.FileLogging) zerolog.LevelWriter {
// 创建文件writer
fileWriter := &lumberjack.Logger{
Filename: path.Join(config.Dir, "app.log"),
MaxSize: config.MaxSize,
MaxBackups: config.MaxBackups,
MaxAge: config.MaxAge,
Compress: config.Compress,
}
// 创建MultiLevelWriter,将不同级别日志路由到不同输出
multiWriter := zerolog.MultiLevelWriter(
// 错误及以上级别写入stderr
zerolog.LevelWriterAdapter{
Writer: zerolog.SyncWriter(os.Stderr),
Level: zerolog.ErrorLevel,
},
// 所有级别都写入文件
zerolog.LevelWriterAdapter{
Writer: fileWriter,
Level: zerolog.TraceLevel,
},
// 除错误外的其他级别写入stdout
zerolog.LevelWriterAdapter{
Writer: zerolog.SyncWriter(os.Stdout),
Level: zerolog.NoLevel, // 匹配所有级别
ExcludeLevels: []zerolog.Level{
zerolog.ErrorLevel,
zerolog.FatalLevel,
zerolog.PanicLevel,
},
},
)
return multiWriter
}
func NewRollingFile(config types.FileLogging) io.Writer {
if config.Dir != "" {
if err := os.MkdirAll(config.Dir, 0744); err != nil {
log.Error().Err(err).Str("path", config.Dir).Msg("can't create log directory")
return nil
}
}
return createLevelWriters(config)
}
// 初始化logger使用示例
func setupLogger(config types.FileLogging) {
writer := NewRollingFile(config)
if writer == nil {
return
}
logger := zerolog.New(writer).With().Timestamp().Logger()
zerolog.DefaultContextLogger = &logger
// 测试日志输出
logger.Info().Msg("普通信息到stdout和文件")
logger.Warn().Msg("警告信息到stdout和文件")
logger.Error().Msg("错误信息到stderr和文件")
logger.Debug().Msg("调试信息到stdout和文件")
}
如果需要更细粒度的控制,可以使用自定义Writer实现:
type splitWriter struct {
stdout io.Writer
stderr io.Writer
file io.Writer
}
func (w *splitWriter) WriteLevel(level zerolog.Level, p []byte) (n int, err error) {
// 错误级别写入stderr
if level >= zerolog.ErrorLevel {
n, err = w.stderr.Write(p)
if err != nil {
return n, err
}
} else {
// 其他级别写入stdout
n, err = w.stdout.Write(p)
if err != nil {
return n, err
}
}
// 所有级别都写入文件
_, err = w.file.Write(p)
return n, err
}
func (w *splitWriter) Write(p []byte) (n int, err error) {
// 默认写入stdout(用于无级别日志)
return w.stdout.Write(p)
}
func createSplitWriter(config types.FileLogging) zerolog.LevelWriter {
fileWriter := &lumberjack.Logger{
Filename: path.Join(config.Dir, "app.log"),
MaxSize: config.MaxSize,
MaxBackups: config.MaxBackups,
MaxAge: config.MaxAge,
Compress: config.Compress,
}
return &splitWriter{
stdout: zerolog.SyncWriter(os.Stdout),
stderr: zerolog.SyncWriter(os.Stderr),
file: fileWriter,
}
}
这样配置后,错误级别(Error、Fatal、Panic)的日志会输出到stderr,其他级别的日志输出到stdout,所有日志都会写入文件。

