recovery.go 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. package middleware
  2. import (
  3. "fmt"
  4. "net/http"
  5. "runtime/debug"
  6. "git.linuxforward.com/byom/byom-gateway/logger"
  7. "github.com/gin-gonic/gin"
  8. "github.com/sirupsen/logrus"
  9. )
  10. // Recovery returns a middleware that recovers from panics and logs the stack trace
  11. func Recovery(log *logrus.Logger) gin.HandlerFunc {
  12. recoveryLogger := logger.NewLogger("recovery")
  13. return func(c *gin.Context) {
  14. defer func() {
  15. if err := recover(); err != nil {
  16. // Get request ID if available
  17. requestID := c.GetString(RequestIDKey)
  18. if requestID == "" {
  19. requestID = "no-request-id"
  20. }
  21. // Get stack trace
  22. stack := string(debug.Stack())
  23. // Add request ID to logger
  24. reqLogger := logger.WithRequestID(recoveryLogger, requestID)
  25. // Log the panic with context
  26. reqLogger.WithFields(logrus.Fields{
  27. "error": fmt.Sprintf("%v", err),
  28. "stack": stack,
  29. "method": c.Request.Method,
  30. "path": c.Request.URL.Path,
  31. "client_ip": c.ClientIP(),
  32. }).Error("Panic recovered")
  33. // Return a 500 error to the client
  34. c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
  35. "error": "Internal server error",
  36. "code": "INTERNAL_SERVER_ERROR",
  37. })
  38. }
  39. }()
  40. c.Next()
  41. }
  42. }