code: func Recovery() macaron.Handler {
  	return func(c *macaron.Context) {
  		defer func() {
  			if err := recover(); err != nil {
  				stack := stack(3)
  
  				panicLogger := log.Root
  				// try to get request logger
  				if ctx, ok := c.Data["ctx"]; ok {
  					ctxTyped := ctx.(*m.ReqContext)
  					panicLogger = ctxTyped.Logger
  				}
  
  				panicLogger.Error("Request error", "error", err, "stack", string(stack))
  
  				c.Data["Title"] = "Server Error"
  				c.Data["AppSubUrl"] = setting.AppSubUrl
  				c.Data["Theme"] = setting.DefaultTheme
  
  				if setting.Env == setting.DEV {
  					if theErr, ok := err.(error); ok {
  						c.Data["Title"] = theErr.Error()
  					}
  
  					c.Data["ErrorMsg"] = string(stack)
  				}
  
  				ctx, ok := c.Data["ctx"].(*m.ReqContext)
  
  				if ok && ctx.IsApiRequest() {
  					resp := make(map[string]interface{})
  					resp["message"] = "Internal Server Error - Check the Grafana server logs for the detailed error message."
  
  					if c.Data["ErrorMsg"] != nil {
  						resp["error"] = fmt.Sprintf("%v - %v", c.Data["Title"], c.Data["ErrorMsg"])
  					} else {
  						resp["error"] = c.Data["Title"]
  					}
  
  					c.JSON(500, resp)
  				} else {
  					c.HTML(500, setting.ERR_TEMPLATE_NAME)
  				}
  			}
  		}()
  
  		c.Next()
  	}
  }
docs: // Recovery returns a middleware that recovers from any panics and writes a 500 if there was one.
  // While Martini is in development mode, Recovery will also output the panic as HTML.