recover.go 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. // Package recover provides recovery for specific routes or for the whole app via middleware. See _examples/miscellaneous/recover
  2. package recover
  3. import (
  4. "fmt"
  5. "runtime"
  6. "strconv"
  7. "github.com/kataras/iris/context"
  8. )
  9. func getRequestLogs(ctx context.Context) string {
  10. var status, ip, method, path string
  11. status = strconv.Itoa(ctx.GetStatusCode())
  12. path = ctx.Path()
  13. method = ctx.Method()
  14. ip = ctx.RemoteAddr()
  15. // the date should be logged by iris' Logger, so we skip them
  16. return fmt.Sprintf("%v %s %s %s", status, path, method, ip)
  17. }
  18. // New returns a new recover middleware,
  19. // it recovers from panics and logs
  20. // the panic message to the application's logger "Warn" level.
  21. func New() context.Handler {
  22. return func(ctx context.Context) {
  23. defer func() {
  24. if err := recover(); err != nil {
  25. if ctx.IsStopped() {
  26. return
  27. }
  28. var stacktrace string
  29. for i := 1; ; i++ {
  30. _, f, l, got := runtime.Caller(i)
  31. if !got {
  32. break
  33. }
  34. stacktrace += fmt.Sprintf("%s:%d\n", f, l)
  35. }
  36. // when stack finishes
  37. logMessage := fmt.Sprintf("Recovered from a route's Handler('%s')\n", ctx.HandlerName())
  38. logMessage += fmt.Sprintf("At Request: %s\n", getRequestLogs(ctx))
  39. logMessage += fmt.Sprintf("Trace: %s\n", err)
  40. logMessage += fmt.Sprintf("\n%s", stacktrace)
  41. ctx.Application().Logger().Warn(logMessage)
  42. ctx.StatusCode(500)
  43. ctx.StopExecution()
  44. }
  45. }()
  46. ctx.Next()
  47. }
  48. }