diff --git a/module/apmechov4/middleware.go b/module/apmechov4/middleware.go index 731e54c22..84c2713bf 100644 --- a/module/apmechov4/middleware.go +++ b/module/apmechov4/middleware.go @@ -81,7 +81,10 @@ func (m *middleware) handle(c echo.Context) error { } name := m.requestName(c) tx, body, req := apmhttp.StartTransactionWithBody(m.tracer, name, req) - defer tx.End() + defer func() { + body.Discard() + tx.End() + }() c.SetRequest(req) resp := c.Response() @@ -106,11 +109,14 @@ func (m *middleware) handle(c echo.Context) error { e.Handled = true e.Send() } + + if txEnded := tx.TransactionData == nil; txEnded { + return + } tx.Result = apmhttp.StatusCodeResult(resp.Status) if tx.Sampled() { setContext(&tx.Context, req, resp, body) } - body.Discard() }() handlerErr = m.handler(c) diff --git a/module/apmechov4/middleware_test.go b/module/apmechov4/middleware_test.go index c4e0fa89c..a037e96bc 100644 --- a/module/apmechov4/middleware_test.go +++ b/module/apmechov4/middleware_test.go @@ -165,6 +165,21 @@ func TestEchoMiddlewarePanic(t *testing.T) { assertError(t, transport.Payloads(), "handlePanic", "boom", false) } +func TestEchoMiddlewareEndedTxn(t *testing.T) { + tracer, _ := transporttest.NewRecorderTracer() + defer tracer.Close() + + e := echo.New() + e.Use(apmecho.Middleware(apmecho.WithTracer(tracer))) + e.GET("/end-txn", handleEndTxn) + + assert.NotPanics(t, func() { + w := doRequest(e, "GET", "http://server.testing/end-txn") + assert.Equal(t, http.StatusOK, w.Code) + tracer.Flush(nil) + }) +} + func TestEchoMiddlewarePanicHeadersSent(t *testing.T) { tracer, transport := transporttest.NewRecorderTracer() defer tracer.Close() @@ -218,6 +233,12 @@ func handlePanicAfterHeaders(c echo.Context) error { panic("boom") } +func handleEndTxn(c echo.Context) error { + txn := apm.TransactionFromContext(c.Request().Context()) + txn.End() + return nil +} + func handleError(c echo.Context) error { return errors.New("wot") }