Files
cylogger/safe.go

85 lines
2.6 KiB
Go

// Package cylogger provides panic recovery and safe goroutine execution utilities.
// These functions help prevent panics from crashing your application by catching
// them and logging them appropriately.
package cylogger
import (
"fmt"
"runtime/debug"
)
// PanicHandler handles a panic and logs it with goroutine ID and stack trace.
// This function should be used with defer to catch panics in goroutines or functions.
// When a panic occurs, it logs the panic value, goroutine ID, and full stack trace.
// Example:
//
// defer cylogger.PanicHandler()
// // Your code that might panic
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.
// If the goroutine panics, the panic will be caught and logged instead of crashing the program.
// This is useful for running potentially unstable code in goroutines.
// Usage: cylogger.SafeGo(func() { ... your code ... })
// Example:
//
// cylogger.SafeGo(func() {
// // Code that might panic
// riskyOperation()
// })
func SafeGo(f func()) {
go func() {
defer PanicHandler()
f()
}()
}
// SafeGoWithArgs launches a goroutine with panic recovery and passes arguments.
// If the goroutine panics, the panic will be caught and logged instead of crashing the program.
// This is useful for running potentially unstable code in goroutines with specific arguments.
// Usage: cylogger.SafeGoWithArgs(func(arg1, arg2 interface{}) { ... }, "value1", 42)
// Example:
//
// cylogger.SafeGoWithArgs(func(args ...interface{}) {
// // Code that might panic with arguments
// processData(args[0], args[1])
// }, "data1", 42)
func SafeGoWithArgs(f func(...interface{}), args ...interface{}) {
go func() {
defer PanicHandler()
f(args...)
}()
}
// SafeExec executes a function with panic recovery and returns an error if a panic occurs.
// This is useful for code that should not panic but might, allowing you to handle panics gracefully.
// If the function panics, it returns an error describing the panic instead of crashing the program.
// Example:
//
// err := cylogger.SafeExec(func() {
// // Code that might panic
// riskyOperation()
// })
// if err != nil {
// // Handle the panic as an error
// }
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
}