@@ -4,6 +4,7 @@ use std::pin::Pin;
4
4
use std:: task:: { Context , Poll } ;
5
5
6
6
use http:: { header, uri, Request , Response , StatusCode } ;
7
+ use pin_project:: pinned_drop;
7
8
use sentry_core:: protocol;
8
9
use tower_layer:: Layer ;
9
10
use tower_service:: Service ;
@@ -62,7 +63,7 @@ impl<S> Layer<S> for SentryHttpLayer {
62
63
}
63
64
64
65
/// The Future returned from [`SentryHttpService`].
65
- #[ pin_project:: pin_project]
66
+ #[ pin_project:: pin_project( PinnedDrop ) ]
66
67
pub struct SentryHttpFuture < F > {
67
68
on_first_poll : Option < (
68
69
sentry_core:: protocol:: Request ,
@@ -123,6 +124,23 @@ where
123
124
}
124
125
}
125
126
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
+
126
144
impl < S , ReqBody , ResBody > Service < Request < ReqBody > > for SentryHttpService < S >
127
145
where
128
146
S : Service < Request < ReqBody > , Response = Response < ResBody > > ,
0 commit comments