go – Multiple logger.New to same output file?

huangapple go评论77阅读模式
英文:

go - Multiple logger.New to same output file?

问题

我知道golang的log.New()可以使用自己的输出写入器创建一个新的Logger。

但是如果我给所有5个log.New() Logger相同的io写入器会发生什么呢?例如:5个Logger(INFO,WARN等)都记录到同一个文件中,该文件可以使用lumberjack模块或os.OpenFile创建。

这样会有问题吗?(例如:没有并发写入?)

或者有没有更好的方法来创建5个新的日志函数,自动添加前缀INFO/WARN等?

谢谢!
BR
Marcus

英文:

I know that golang's log.New() can create a new Logger with it's own output writer.

But what happens if I give all 5 log.New() Logger the same io writer? Example: 5x Logger (INFO,WARN,etc.) logs to the same file, created with the lumberjack module or with os.OpenFile.

Would that create issues? (e.g. No concurrent writes?)

Or what would be the preferred method to create 5 new log functions that automatically prefix INFO/WARN/etc.?

Thanks!
BR
Marcus

答案1

得分: 1

文档中提到:

Logger表示一个活动的日志对象,它将输出行生成到io.Writer。每个日志操作都会调用Writer的Write方法一次。Logger可以同时从多个goroutine中使用;它保证对Writer的访问进行序列化。

Logger对其写入器进行序列化访问,但日志记录器之间没有协调。

在日志记录器之间共享的写入器必须支持并发调用Write,并且不能交错处理这些并发调用的数据。

如果写入器没有这些属性,请使用一个添加了同步功能的类型来包装写入器。

type syncWriter struct {
    mu sync.Mutex
    w  io.Writer
}

func (sw *syncWriter) Write(p []byte) (int, error) {
    sw.mu.Lock()
    defer sw.mu.Unlock()
    return sw.w.Write(p)
}
英文:

The documentation says:

> A Logger represents an active logging object that generates lines of output to an io.Writer. Each logging operation makes a single call to the Writer's Write method. A Logger can be used simultaneously from multiple goroutines; it guarantees to serialize access to the Writer.

A logger serializes access to it's writer, but there's no coordination between loggers.

A writer shared between loggers must support concurrent calls to Write and must not interleave data from those concurrent calls.

If the writer does not have those properties, wrap the writer with a type that adds synchronization.

type syncWriter struct {
	mu sync.Mutex
	w  io.Writer
}

func (sw *syncWriter) Write(p []byte) (int, error) {
	sw.mu.Lock()
	defer sw.mu.Unlock()
	return sw.w.Write(p)
}

答案2

得分: 1

有很多支持日志级别的日志记录器实现,例如sirupsen/logrus

为了避免引入其他依赖,可以对log.Logger进行封装,并实现自定义的Info/Warn/Error方法。log.Logger是并发安全的,不需要多个日志记录器。

示例代码如下:

type Logger struct {
	l *log.Logger
}

// 可以使用一个字符串参数
// func (l *Logger) Info(msg string) { 
//     l.l.Println(fmt.Sprintf("[INFO]: %s", msg))
// }
func (l *Logger) Info(args ...interface{}) { 
	args = append(make([]interface{}, 1, len(args)+1), args...)
	args[0] = "[INFO]"
	l.l.Println(args...)
}

func (l *Logger) Error(args ...interface{}) {
	args = append(make([]interface{}, 1, len(args)+1), args...)
	args[0] = "[ERROR]"
	l.l.Println(args...)
}
英文:

There is plenty of logger implementations that supports log levels e. g. sirupsen/logrus.

To avoid another dependency wrap log.Logger and implement custom Info/Warn/Error methods. log.Logger is concurrent safe and there is no need to have multiple loggers.

Example:

type Logger struct {
	l *log.Logger
}

// You could use one string argument 
// func (l *Logger) Info(msg string) { 
//     l.l.Println(fmt.Sprintf("[INFO]: %s", msg))
// }
func (l *Logger) Info(args ...interface{}) { 
	args = append(make([]interface{}, 1, len(args)+1), args...)
	args[0] = "[INFO]"
	l.l.Println(args...)
}

func (l *Logger) Error(args ...interface{}) {
	args = append(make([]interface{}, 1, len(args)+1), args...)
	args[0] = "[ERROR]"
	l.l.Println(args...)
}

huangapple
  • 本文由 发表于 2022年3月20日 23:38:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/71548165.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定