@@ -4,7 +4,9 @@ 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;
9+ use sentry_core:: types:: protocol;
810use tower_layer:: Layer ;
911use tower_service:: Service ;
1012
@@ -62,7 +64,7 @@ impl<S> Layer<S> for SentryHttpLayer {
6264}
6365
6466/// The Future returned from [`SentryHttpService`].
65- #[ pin_project:: pin_project]
67+ #[ pin_project:: pin_project( PinnedDrop ) ]
6668pub struct SentryHttpFuture < F > {
6769 on_first_poll : Option < (
6870 sentry_core:: protocol:: Request ,
@@ -123,6 +125,23 @@ where
123125 }
124126}
125127
128+ #[ pinned_drop]
129+ impl < F > PinnedDrop for SentryHttpFuture < F > {
130+ fn drop ( self : Pin < & mut Self > ) {
131+ let slf = self . project ( ) ;
132+
133+ // If the future gets dropped without being polled to completion,
134+ // still finish the transaction to make sure this is not lost.
135+ if let Some ( ( transaction, parent_span) ) = slf. transaction . take ( ) {
136+ if transaction. get_status ( ) . is_none ( ) {
137+ transaction. set_status ( protocol:: SpanStatus :: Aborted ) ;
138+ }
139+ transaction. finish ( ) ;
140+ sentry_core:: configure_scope ( |scope| scope. set_span ( parent_span) ) ;
141+ }
142+ }
143+ }
144+
126145impl < S , ReqBody , ResBody > Service < Request < ReqBody > > for SentryHttpService < S >
127146where
128147 S : Service < Request < ReqBody > , Response = Response < ResBody > > ,
0 commit comments