Search code examples
goiotimestamplogrus

Is there a way to append io.multiwriter with timestamp in go?


I am dealing with logs generated in go. Things are printed to stdout and a log file using io.multiwriterlog := io.MultiWriter(os.Stdout, logfile). I would like to add timestamps to both os.Stdout and logfile.

My approach is to write a write function

type writer struct {
    io.Writer
    timeFormat string
}

func (w writer) Write(b []byte) (n int, err error) {
    return w.Writer.Write(append([]byte(time.Now().Format(w.timeFormat)), b...))
}
log := io.MultiWriter(&writer{os.Stdout, "2006/01/02 15:04:05"}, logFile)

However, it does not produce the timestamp both in Stdout and logfile. Does anyone know if there is another way to do this?


Solution

  • The reason why the timestamp doesn't show up in the log file is because only your writer adds the timestamp, not io.MultiWriter().

    Change your use to set the multi-writer to writer.Writer, so the timestamp will be sent to both writers: os.Stdout and logFile.

    logFile := &bytes.Buffer{}
    log := &writer{io.MultiWriter(os.Stdout, logFile), "2006/01/02 15:04:05"}
    log.Write([]byte(" hi"))
    
    fmt.Println("\nlogFile:", logFile)
    

    This will output (try it on the Go Playground):

    2009/11/10 23:00:00 hi
    logFile: 2009/11/10 23:00:00 hi
    

    Also note that the log package (combined with io.MultiWriter) gives you this functionality out of the box, you can set the output writer using log.SetOutput():

    logFile := &bytes.Buffer{}
    log.SetOutput(io.MultiWriter(os.Stdout, logFile))
    log.Print("hi")
    
    fmt.Println("logFile:", logFile)
    

    Output (try it on the Go Playground):

    2009/11/10 23:00:00 hi
    logFile: 2009/11/10 23:00:00 hi
    

    Moreover, the log package also provides formatting capabilities and configurable output.