when running web app locally with command
go run MainPackageFile.go
and we can map logger e.g with martini
m := martini.Classic()
m.Get("/m", func() string {
return "Hello world!"
})
m.Map(log.New(f, "[martini]", log.LstdFlags))
however what if there is something wrong outside the code, e.g Go not able to download package etc... is there a way to get those go runtime log? when running locally errors will print out onto console. is there a way when running in server, we can have all those log write into text file?
You can use this function to redirect standard error to a file. This will receive tracebacks.
// redirectStderr to the file passed in
func redirectStderr(f *os.File) {
err := syscall.Dup2(int(f.Fd()), int(os.Stderr.Fd()))
if err != nil {
log.Fatalf("Failed to redirect stderr to file: %v", err)
}
}
It only works on linux/mac/unix.
Here is how to do the same thing for windows
var (
kernel32 = syscall.MustLoadDLL("kernel32.dll")
procSetStdHandle = kernel32.MustFindProc("SetStdHandle")
)
func setStdHandle(stdhandle int32, handle syscall.Handle) error {
r0, _, e1 := syscall.Syscall(procSetStdHandle.Addr(), 2, uintptr(stdhandle), uintptr(handle), 0)
if r0 == 0 {
if e1 != 0 {
return error(e1)
}
return syscall.EINVAL
}
return nil
}
// redirectStderr to the file passed in
func redirectStderr(f *os.File) {
err := setStdHandle(syscall.STD_ERROR_HANDLE, syscall.Handle(f.Fd()))
if err != nil {
log.Fatalf("Failed to redirect stderr to file: %v", err)
}
}
Assuming your code uses the log library to report errors everywhere, you can change the file that the default logger writes to rather than defining your own log object and passing it around. This is done via the log library's SetOutput() function.
This way the following code would just write into your log file instead standard error:
// Call this when your program starts and pass it the file handle for your
// log file.
func SetupErrorLog(logFile io.Writer) {
log.SetOutput(logFile)
}
...
func DoSomething() {
...
if err != nil {
// prints to your log file and exits
log.Fatalln("A fatal error has occurred:", err)
}
}
If you are not using the log library uniformly and you want to capture all output (like panics), then the accepted answer works. However, I'd prefer a much simpler approach without complicating your code by using a tool like logger when you invoke your program:
go run MainPackageFile.go 2>&1 | logger
This will send all of your program's output to syslog without having to mess with your code. The logger command has many options to customize logging behavior, including the ability to choose your own log file. Read the logger man page for more information.
The logger command is available on Unix systems (including Mac). The Windows solution might be a little different.