Home > Software design >  go - Multiple logger.New to same output file?
go - Multiple logger.New to same output file?

Time:03-21

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

CodePudding user response:

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)
}

CodePudding user response:

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...)
}
  • Related