@@ -4,6 +4,7 @@ use std::pin::Pin;
44use std:: task:: { Context , Poll } ;
55
66use http:: { header, uri, Request , Response , StatusCode } ;
7+ use pin_project:: pinned_drop;
78use sentry_core:: protocol;
89use tower_layer:: Layer ;
910use tower_service:: Service ;
@@ -62,7 +63,7 @@ impl<S> Layer<S> for SentryHttpLayer {
6263}
6364
6465/// The Future returned from [`SentryHttpService`].
65- #[ pin_project:: pin_project]
66+ #[ pin_project:: pin_project( PinnedDrop ) ]
6667pub struct SentryHttpFuture < F > {
6768 on_first_poll : Option < (
6869 sentry_core:: protocol:: Request ,
@@ -123,6 +124,23 @@ where
123124 }
124125}
125126
127+ #[ pinned_drop]
128+ impl < F > PinnedDrop for SentryHttpFuture < F > {
129+ fn drop ( self : Pin < & mut Self > ) {
130+ let slf = self . project ( ) ;
131+
132+ // If the future gets dropped without being polled to completion,
133+ // still finish the transaction to make sure this is not lost.
134+ if let Some ( ( transaction, parent_span) ) = slf. transaction . take ( ) {
135+ if transaction. get_status ( ) . is_none ( ) {
136+ transaction. set_status ( protocol:: SpanStatus :: Aborted ) ;
137+ }
138+ transaction. finish ( ) ;
139+ sentry_core:: configure_scope ( |scope| scope. set_span ( parent_span) ) ;
140+ }
141+ }
142+ }
143+
126144impl < S , ReqBody , ResBody > Service < Request < ReqBody > > for SentryHttpService < S >
127145where
128146 S : Service < Request < ReqBody > , Response = Response < ResBody > > ,
0 commit comments