package cylogger import ( "fmt" "runtime/debug" ) // PanicHandler handles a panic and logs it func PanicHandler() { if r := recover(); r != nil { goroutineID := GetGoroutineID() stackTrace := debug.Stack() Error("PANIC in goroutine %s: %v\n%s", goroutineID, r, stackTrace) } } // SafeGo launches a goroutine with panic recovery // Usage: logger.SafeGo(func() { ... your code ... }) func SafeGo(f func()) { go func() { defer PanicHandler() f() }() } // SafeGoWithArgs launches a goroutine with panic recovery and passes arguments // Usage: logger.SafeGoWithArgs(func(arg1, arg2 interface{}) { ... }, "value1", 42) func SafeGoWithArgs(f func(...interface{}), args ...interface{}) { go func() { defer PanicHandler() f(args...) }() } // SafeExec executes a function with panic recovery // Useful for code that should not panic func SafeExec(f func()) (err error) { defer func() { if r := recover(); r != nil { goroutineID := GetGoroutineID() stackTrace := debug.Stack() Error("PANIC in goroutine %s: %v\n%s", goroutineID, r, stackTrace) err = fmt.Errorf("panic recovered: %v", r) } }() f() return nil }