in module/apmechov4/middleware.go [77:151]
func (m *middleware) handle(c echo.Context) error {
req := c.Request()
if !m.tracer.Recording() || m.requestIgnorer(req) {
return m.handler(c)
}
name := m.requestName(c)
tx, body, req := apmhttp.StartTransactionWithBody(m.tracer, name, req)
defer tx.End()
c.SetRequest(req)
resp := c.Response()
var handlerErr error
defer func() {
if v := recover(); v != nil {
err, ok := v.(error)
if !ok {
err = errors.New(fmt.Sprint(v))
}
c.Error(err)
e := m.tracer.Recovered(v)
e.SetTransaction(tx)
setContext(&e.Context, req, resp, body)
e.Send()
}
if handlerErr != nil {
e := m.tracer.NewError(handlerErr)
setContext(&e.Context, req, resp, body)
e.SetTransaction(tx)
e.Handled = true
e.Send()
}
tx.Result = apmhttp.StatusCodeResult(resp.Status)
if tx.Sampled() {
setContext(&tx.Context, req, resp, body)
}
body.Discard()
}()
handlerErr = m.handler(c)
if handlerErr != nil {
resp.Status = http.StatusInternalServerError
if handlerErr, ok := handlerErr.(*echo.HTTPError); ok {
resp.Status = handlerErr.Code
reqPath := req.URL.RawPath
if reqPath == "" {
reqPath = req.URL.Path
}
if c.Path() == reqPath {
// When c.Path() matches the request path exactly,
// that means either there's no matching route, or
// there's an exactly matching route.
//
// When ErrNotFound or ErrMethodNotAllowed are
// returned, it's probably because there's no
// matching route, as opposed to the handler
// returning them. We can confirm this by looking
// for exact-matching routes.
var unknownRoute bool
switch handlerErr {
case echo.ErrNotFound:
unknownRoute = isNotFoundHandler(c.Handler())
case echo.ErrMethodNotAllowed:
unknownRoute = isMethodNotAllowedHandler(c.Handler())
}
if unknownRoute {
tx.Name = apmhttp.UnknownRouteRequestName(req)
}
}
}
} else if !resp.Committed {
resp.WriteHeader(http.StatusOK)
}
return handlerErr
}