1
1
use std:: borrow:: Cow ;
2
2
use std:: cell:: RefCell ;
3
3
use std:: collections:: BTreeMap ;
4
+ use std:: sync:: Arc ;
4
5
5
6
use sentry_core:: protocol:: Value ;
6
7
use sentry_core:: { Breadcrumb , TransactionOrSpan } ;
@@ -197,6 +198,8 @@ fn record_fields<'a, K: AsRef<str> + Into<Cow<'a, str>>>(
197
198
pub ( super ) struct SentrySpanData {
198
199
pub ( super ) sentry_span : TransactionOrSpan ,
199
200
parent_sentry_span : Option < TransactionOrSpan > ,
201
+ hub : Arc < sentry_core:: Hub > ,
202
+ hub_switch_guard : Option < sentry_core:: HubSwitchGuard > ,
200
203
}
201
204
202
205
impl < S > Layer < S > for SentryLayer < S >
@@ -256,7 +259,9 @@ where
256
259
}
257
260
} ) ;
258
261
259
- let parent_sentry_span = sentry_core:: configure_scope ( |s| s. get_span ( ) ) ;
262
+ let hub = sentry_core:: Hub :: current ( ) ;
263
+ let parent_sentry_span = hub. configure_scope ( |scope| scope. get_span ( ) ) ;
264
+
260
265
let sentry_span: sentry_core:: TransactionOrSpan = match & parent_sentry_span {
261
266
Some ( parent) => parent. start_child ( op, & description) . into ( ) ,
262
267
None => {
@@ -268,15 +273,48 @@ where
268
273
// This comes from typically the `fields` in `tracing::instrument`.
269
274
record_fields ( & sentry_span, data) ;
270
275
271
- sentry_core:: configure_scope ( |scope| scope. set_span ( Some ( sentry_span. clone ( ) ) ) ) ;
272
-
273
276
let mut extensions = span. extensions_mut ( ) ;
274
277
extensions. insert ( SentrySpanData {
275
278
sentry_span,
276
279
parent_sentry_span,
280
+ hub,
281
+ hub_switch_guard : None ,
277
282
} ) ;
278
283
}
279
284
285
+ /// Sets entered span as *current* sentry span. A tracing span can be
286
+ /// entered and existed multiple times, for example, when using a `tracing::Instrumented` future.
287
+ fn on_enter ( & self , id : & span:: Id , ctx : Context < ' _ , S > ) {
288
+ let span = match ctx. span ( id) {
289
+ Some ( span) => span,
290
+ None => return ,
291
+ } ;
292
+
293
+ let mut extensions = span. extensions_mut ( ) ;
294
+ if let Some ( data) = extensions. get_mut :: < SentrySpanData > ( ) {
295
+ data. hub_switch_guard = Some ( sentry_core:: HubSwitchGuard :: new ( data. hub . clone ( ) ) ) ;
296
+ data. hub . configure_scope ( |scope| {
297
+ scope. set_span ( Some ( data. sentry_span . clone ( ) ) ) ;
298
+ } )
299
+ }
300
+ }
301
+
302
+ /// Set exited span's parent as *current* sentry span.
303
+ fn on_exit ( & self , id : & span:: Id , ctx : Context < ' _ , S > ) {
304
+ let span = match ctx. span ( id) {
305
+ Some ( span) => span,
306
+ None => return ,
307
+ } ;
308
+
309
+ let mut extensions = span. extensions_mut ( ) ;
310
+ if let Some ( data) = extensions. get_mut :: < SentrySpanData > ( ) {
311
+ data. hub . configure_scope ( |scope| {
312
+ scope. set_span ( data. parent_sentry_span . clone ( ) ) ;
313
+ } ) ;
314
+ data. hub_switch_guard . take ( ) ;
315
+ }
316
+ }
317
+
280
318
/// When a span gets closed, finish the underlying sentry span, and set back
281
319
/// its parent as the *current* sentry span.
282
320
fn on_close ( & self , id : span:: Id , ctx : Context < ' _ , S > ) {
@@ -286,16 +324,12 @@ where
286
324
} ;
287
325
288
326
let mut extensions = span. extensions_mut ( ) ;
289
- let SentrySpanData {
290
- sentry_span,
291
- parent_sentry_span,
292
- } = match extensions. remove :: < SentrySpanData > ( ) {
327
+ let SentrySpanData { sentry_span, .. } = match extensions. remove :: < SentrySpanData > ( ) {
293
328
Some ( data) => data,
294
329
None => return ,
295
330
} ;
296
331
297
332
sentry_span. finish ( ) ;
298
- sentry_core:: configure_scope ( |scope| scope. set_span ( parent_sentry_span) ) ;
299
333
}
300
334
301
335
/// Implement the writing of extra data to span
0 commit comments