I have GoLang Application where I use log15 to write logs to a file. The package I use for log15 is gopkg.in/inconshreveable/log15.v2
I run into a situation where I want to write the information of STDERR and STDOUT to the same file where I write log15 logs. Is there any possible ways to achieve the same
For creating a log file to log data of stderr or stdout. Create a file using OpenFile
and then SetOutput
to the file as.
f, err := os.OpenFile("EDUC_LOG", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0664)
if err != nil {
panic(err)
}
defer f.Close()
log.SetOutput(f)
This will print the output to log file everytime you try to log some value like in case of an error as
if err != nil{
log.Println(err) // this will create a file if not created to output the log in a file.
}
Edited:
Fatal error will print the output on stdout rather than in a file, Since the program will exit before writing anything to the file.
package main
import (
"log"
)
func main() {
log.Println("error1")
log.Fatal("error1")
log.Println("error2") // this will not print since the program will exit the main with fatal error
}
You could capture os.Stdout
with a pipe and redirect the output to the actual stdout and your file using a io.MultiWriter
f, _ := os.OpenFile("my.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0664)
multiWriter := io.MultiWriter(os.Stdout, f)
rd, wr, err := os.Pipe()
if err != nil {
os.Exit(1)
}
// overwrite os.Stdout
os.Stdout = wr
go func() {
scanner := bufio.NewScanner(rd)
for scanner.Scan() {
stdoutLine := scanner.Text()
multiWriter.Write([]byte(stdoutLine + "
"))
}
}()
fmt.Println("foobar")
// hacky sleep to ensure the go routine can write before program exits
time.Sleep(time.Second)
You can apply the same with os.Stderr
of course
You'll have to find how to get a handle on the log15
file though, but that shouldn't be too hard
The issue you might have with this approach is that there is no guarantee that the goroutine will do its job when the program ends (see the sleep hack), not sure how to achieve that