1package logging
2
3import (
4 "fmt"
5 "log/slog"
6 "os"
7 "runtime/debug"
8 "time"
9)
10
11func Info(msg string, args ...any) {
12 slog.Info(msg, args...)
13}
14
15func Debug(msg string, args ...any) {
16 slog.Debug(msg, args...)
17}
18
19func Warn(msg string, args ...any) {
20 slog.Warn(msg, args...)
21}
22
23func Error(msg string, args ...any) {
24 slog.Error(msg, args...)
25}
26
27func InfoPersist(msg string, args ...any) {
28 args = append(args, persistKeyArg, true)
29 slog.Info(msg, args...)
30}
31
32func DebugPersist(msg string, args ...any) {
33 args = append(args, persistKeyArg, true)
34 slog.Debug(msg, args...)
35}
36
37func WarnPersist(msg string, args ...any) {
38 args = append(args, persistKeyArg, true)
39 slog.Warn(msg, args...)
40}
41
42func ErrorPersist(msg string, args ...any) {
43 args = append(args, persistKeyArg, true)
44 slog.Error(msg, args...)
45}
46
47// RecoverPanic is a common function to handle panics gracefully.
48// It logs the error, creates a panic log file with stack trace,
49// and executes an optional cleanup function before returning.
50func RecoverPanic(name string, cleanup func()) {
51 if r := recover(); r != nil {
52 // Log the panic
53 ErrorPersist(fmt.Sprintf("Panic in %s: %v", name, r))
54
55 // Create a timestamped panic log file
56 timestamp := time.Now().Format("20060102-150405")
57 filename := fmt.Sprintf("crush-panic-%s-%s.log", name, timestamp)
58
59 file, err := os.Create(filename)
60 if err != nil {
61 ErrorPersist(fmt.Sprintf("Failed to create panic log: %v", err))
62 } else {
63 defer file.Close()
64
65 // Write panic information and stack trace
66 fmt.Fprintf(file, "Panic in %s: %v\n\n", name, r)
67 fmt.Fprintf(file, "Time: %s\n\n", time.Now().Format(time.RFC3339))
68 fmt.Fprintf(file, "Stack Trace:\n%s\n", debug.Stack())
69
70 InfoPersist(fmt.Sprintf("Panic details written to %s", filename))
71 }
72
73 // Execute cleanup function if provided
74 if cleanup != nil {
75 cleanup()
76 }
77 }
78}