log.go

 1package log
 2
 3import (
 4	"fmt"
 5	"log/slog"
 6	"os"
 7	"runtime/debug"
 8	"sync"
 9	"time"
10
11	"gopkg.in/natefinch/lumberjack.v2"
12)
13
14var initOnce sync.Once
15
16func Init(logFile string, debug bool) {
17	initOnce.Do(func() {
18		logRotator := &lumberjack.Logger{
19			Filename:   logFile,
20			MaxSize:    10,    // Max size in MB
21			MaxBackups: 0,     // Number of backups
22			MaxAge:     30,    // Days
23			Compress:   false, // Enable compression
24		}
25
26		level := slog.LevelInfo
27		if debug {
28			level = slog.LevelDebug
29		}
30
31		logger := slog.NewJSONHandler(logRotator, &slog.HandlerOptions{
32			Level:     level,
33			AddSource: true,
34		})
35
36		slog.SetDefault(slog.New(logger))
37	})
38}
39
40func RecoverPanic(name string, cleanup func()) {
41	if r := recover(); r != nil {
42		// Create a timestamped panic log file
43		timestamp := time.Now().Format("20060102-150405")
44		filename := fmt.Sprintf("crush-panic-%s-%s.log", name, timestamp)
45
46		file, err := os.Create(filename)
47		if err == nil {
48			defer file.Close()
49
50			// Write panic information and stack trace
51			fmt.Fprintf(file, "Panic in %s: %v\n\n", name, r)
52			fmt.Fprintf(file, "Time: %s\n\n", time.Now().Format(time.RFC3339))
53			fmt.Fprintf(file, "Stack Trace:\n%s\n", debug.Stack())
54
55			// Execute cleanup function if provided
56			if cleanup != nil {
57				cleanup()
58			}
59		}
60	}
61}