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