You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
If the output destination for a logger is buffered, a call to one of the Fatal methods can lose logs, because os.Exit is called immediately after logging, likely before the buffer is flushed. To fix this, if the destination writer has a Flush method, then call it. Example implementation:
type flusher interface {
Flush() error
}
func (l *Logger) Fatal(v ...interface{}) {
l.Output(2, fmt.Sprint(v...))
if fl, ok := l.out.(flusher); ok {
fl.Flush()
}
os.Exit(1)
}
The Panic methods suffer from the same loss of logs, since panic is called immediately after logging, prior to the buffer being flushed. This can be solved in a similar way, calling Flush prior to calling panic.
The text was updated successfully, but these errors were encountered:
odeke-em
changed the title
log: Flush output for Fatal and Panic methods
proposal: log: flush output on Fatal and Panic methods if the destination writer has a Flush method
Sep 4, 2017
package main
import (
"bufio""flag""log""os""strings"
)
funcmain() {
varflushboolflag.BoolVar(&flush, "flush", false, "if set, will flush the buffered io before exiting")
flag.Parse()
br:=bufio.NewWriter(os.Stdout)
logger:=log.New(br, "", log.Ldate)
logger.Printf("%s\n", strings.Repeat("This is a test\n", 5))
ifflush {
br.Flush()
}
logger.Fatalf("exiting now!")
}
Without invoking flush -- the problem illustrated
$ echo -e "\033[32mCommon case, flush not invoked before Fatalf\033[00m"&& go run main.go
Common case, flush not invoked before Fatalf
exit status 1
With flush invoked -- the manual way, illustrating the solution
$ echo -e "\033[32mSupporting case, flush invoked before Fatalf\033[00m"&& go run main.go --flush
Supporting case, flush invoked before Fatalf
2017/09/03 This is a test
This is a test
This is a test
This is a test
This is a testexit status 1
Thanks. Note how the "exiting now!" message is not displayed in either test, which shows that the solution is needed inside the log package, since even if the application performs a Flush, the fatal message is still lost.
This can't work. If you have a bufio writing to a gzip writing to an os.File, flushing the bufio will not flush the gzip and so will not actually put any of the log message into the file. This is by design - Flush doesn't chain.
If the output destination for a logger is buffered, a call to one of the
Fatal
methods can lose logs, becauseos.Exit
is called immediately after logging, likely before the buffer is flushed. To fix this, if the destination writer has aFlush
method, then call it. Example implementation:type flusher interface {
Flush() error
}
func (l *Logger) Fatal(v ...interface{}) {
l.Output(2, fmt.Sprint(v...))
if fl, ok := l.out.(flusher); ok {
fl.Flush()
}
os.Exit(1)
}
The
Panic
methods suffer from the same loss of logs, sincepanic
is called immediately after logging, prior to the buffer being flushed. This can be solved in a similar way, callingFlush
prior to callingpanic
.The text was updated successfully, but these errors were encountered: