From d28db037ae71f9da02441b187cc2e94d95f2dc97 Mon Sep 17 00:00:00 2001 From: Ash Keel Date: Thu, 9 Mar 2023 12:41:50 +0100 Subject: [PATCH] feat: add stderr logging to its own file --- main.go | 19 ++++++++++++++++++- utils/stderr_unix.go | 17 +++++++++++++++++ utils/stderr_windows.go | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 utils/stderr_unix.go create mode 100644 utils/stderr_windows.go diff --git a/main.go b/main.go index 88fddfb..bf0ffd4 100644 --- a/main.go +++ b/main.go @@ -34,6 +34,8 @@ func main() { log.Fatal(err) } + var panicLog *os.File + app := &cli.App{ Name: "strimertul", Usage: "the small broadcasting suite for Twitch", @@ -83,12 +85,27 @@ func main() { level = zapcore.InfoLevel } initLogger(level) + + // Create file for panics + panicLog, err = os.OpenFile("strimertul-panic.log", os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0o666) + if err != nil { + logger.Warn("could not create panic log", zap.Error(err)) + } else { + utils.RedirectStderr(panicLog) + } + + zap.RedirectStdLog(logger)() + ctx.Context = context.WithValue(ctx.Context, utils.ContextLogger, logger) return nil }, After: func(ctx *cli.Context) error { + if panicLog != nil { + utils.Close(panicLog, logger) + } + _ = logger.Sync() - zap.RedirectStdLog(logger)() + return nil }, } diff --git a/utils/stderr_unix.go b/utils/stderr_unix.go new file mode 100644 index 0000000..ae931c6 --- /dev/null +++ b/utils/stderr_unix.go @@ -0,0 +1,17 @@ +//go:build unix + +package utils + +import "os" + +import ( + "log" + "syscall" +) + +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) + } +} diff --git a/utils/stderr_windows.go b/utils/stderr_windows.go new file mode 100644 index 0000000..f994473 --- /dev/null +++ b/utils/stderr_windows.go @@ -0,0 +1,34 @@ +//go:build windows + +package utils + +import ( + "log" + "os" + "syscall" +) + +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 +} + +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) + } + // SetStdHandle does not affect prior references to stderr + os.Stderr = f +}