log.go 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. package log
  2. import (
  3. "fmt"
  4. "log/slog"
  5. "os"
  6. "runtime/debug"
  7. "sync"
  8. "sync/atomic"
  9. "time"
  10. "gopkg.in/natefinch/lumberjack.v2"
  11. )
  12. var (
  13. initOnce sync.Once
  14. initialized atomic.Bool
  15. )
  16. func Setup(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. level := slog.LevelInfo
  26. if debug {
  27. level = slog.LevelDebug
  28. }
  29. logger := slog.NewJSONHandler(logRotator, &slog.HandlerOptions{
  30. Level: level,
  31. AddSource: true,
  32. })
  33. slog.SetDefault(slog.New(logger))
  34. initialized.Store(true)
  35. })
  36. }
  37. func Initialized() bool {
  38. return initialized.Load()
  39. }
  40. func 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. file, err := os.Create(filename)
  46. if err == nil {
  47. defer file.Close()
  48. // Write panic information and stack trace
  49. fmt.Fprintf(file, "Panic in %s: %v\n\n", name, r)
  50. fmt.Fprintf(file, "Time: %s\n\n", time.Now().Format(time.RFC3339))
  51. fmt.Fprintf(file, "Stack Trace:\n%s\n", debug.Stack())
  52. // Execute cleanup function if provided
  53. if cleanup != nil {
  54. cleanup()
  55. }
  56. }
  57. }
  58. }