logger.go 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. package logging
  2. import (
  3. "fmt"
  4. "log/slog"
  5. "os"
  6. "runtime/debug"
  7. "time"
  8. "github.com/opencode-ai/opencode/internal/status"
  9. )
  10. func Info(msg string, args ...any) {
  11. slog.Info(msg, args...)
  12. }
  13. func Debug(msg string, args ...any) {
  14. slog.Debug(msg, args...)
  15. }
  16. func Warn(msg string, args ...any) {
  17. slog.Warn(msg, args...)
  18. }
  19. func Error(msg string, args ...any) {
  20. slog.Error(msg, args...)
  21. }
  22. // RecoverPanic is a common function to handle panics gracefully.
  23. // It logs the error, creates a panic log file with stack trace,
  24. // and executes an optional cleanup function before returning.
  25. func RecoverPanic(name string, cleanup func()) {
  26. if r := recover(); r != nil {
  27. // Log the panic
  28. errorMsg := fmt.Sprintf("Panic in %s: %v", name, r)
  29. Error(errorMsg)
  30. status.Error(errorMsg)
  31. // Create a timestamped panic log file
  32. timestamp := time.Now().Format("20060102-150405")
  33. filename := fmt.Sprintf("opencode-panic-%s-%s.log", name, timestamp)
  34. file, err := os.Create(filename)
  35. if err != nil {
  36. errMsg := fmt.Sprintf("Failed to create panic log: %v", err)
  37. Error(errMsg)
  38. status.Error(errMsg)
  39. } else {
  40. defer file.Close()
  41. // Write panic information and stack trace
  42. fmt.Fprintf(file, "Panic in %s: %v\n\n", name, r)
  43. fmt.Fprintf(file, "Time: %s\n\n", time.Now().Format(time.RFC3339))
  44. fmt.Fprintf(file, "Stack Trace:\n%s\n", debug.Stack())
  45. infoMsg := fmt.Sprintf("Panic details written to %s", filename)
  46. Info(infoMsg)
  47. status.Info(infoMsg)
  48. }
  49. // Execute cleanup function if provided
  50. if cleanup != nil {
  51. cleanup()
  52. }
  53. }
  54. }