From 36f885c301dfc9df097bf821588529e26ad3f13a Mon Sep 17 00:00:00 2001 From: David Herberth Date: Tue, 28 Jan 2025 16:49:05 +0100 Subject: [PATCH] fix(http): Finish transaction on drop --- sentry-tower/src/http.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/sentry-tower/src/http.rs b/sentry-tower/src/http.rs index 5ad96462..98caea80 100644 --- a/sentry-tower/src/http.rs +++ b/sentry-tower/src/http.rs @@ -4,7 +4,9 @@ use std::pin::Pin; use std::task::{Context, Poll}; use http::{header, uri, Request, Response, StatusCode}; +use pin_project::pinned_drop; use sentry_core::protocol; +use sentry_core::types::protocol; use tower_layer::Layer; use tower_service::Service; @@ -62,7 +64,7 @@ impl Layer for SentryHttpLayer { } /// The Future returned from [`SentryHttpService`]. -#[pin_project::pin_project] +#[pin_project::pin_project(PinnedDrop)] pub struct SentryHttpFuture { on_first_poll: Option<( sentry_core::protocol::Request, @@ -123,6 +125,23 @@ where } } +#[pinned_drop] +impl PinnedDrop for SentryHttpFuture { + fn drop(self: Pin<&mut Self>) { + let slf = self.project(); + + // If the future gets dropped without being polled to completion, + // still finish the transaction to make sure this is not lost. + if let Some((transaction, parent_span)) = slf.transaction.take() { + if transaction.get_status().is_none() { + transaction.set_status(protocol::SpanStatus::Aborted); + } + transaction.finish(); + sentry_core::configure_scope(|scope| scope.set_span(parent_span)); + } + } +} + impl Service> for SentryHttpService where S: Service, Response = Response>,