@@ -33,12 +33,12 @@ use std::{
33
33
mem:: take,
34
34
sync:: {
35
35
atomic:: { AtomicI32 , Ordering } ,
36
- Arc , Mutex , Weak ,
36
+ Arc , Mutex , RwLock , Weak ,
37
37
} ,
38
38
} ;
39
39
40
40
struct Inner {
41
- trace_id : String ,
41
+ trace_id : RwLock < String > ,
42
42
trace_segment_id : String ,
43
43
service : String ,
44
44
service_instance : String ,
@@ -49,8 +49,7 @@ struct Inner {
49
49
primary_endpoint_name : Mutex < String > ,
50
50
}
51
51
52
- #[ derive( Clone ) ]
53
- #[ must_use = "You should call `create_entry_span` after `TracingContext` created." ]
52
+ #[ must_use = "call `create_entry_span` after `TracingContext` created." ]
54
53
pub struct TracingContext {
55
54
inner : Arc < Inner > ,
56
55
tracer : WeakTracer ,
@@ -79,7 +78,7 @@ impl TracingContext {
79
78
) -> Self {
80
79
TracingContext {
81
80
inner : Arc :: new ( Inner {
82
- trace_id : RandomGenerator :: generate ( ) ,
81
+ trace_id : RwLock :: new ( RandomGenerator :: generate ( ) ) ,
83
82
trace_segment_id : RandomGenerator :: generate ( ) ,
84
83
service : service_name. to_string ( ) ,
85
84
service_instance : instance_name. to_string ( ) ,
@@ -104,7 +103,7 @@ impl TracingContext {
104
103
) -> Self {
105
104
TracingContext {
106
105
inner : Arc :: new ( Inner {
107
- trace_id : context. parent_trace_id . clone ( ) ,
106
+ trace_id : RwLock :: new ( context. parent_trace_id . clone ( ) ) ,
108
107
trace_segment_id : RandomGenerator :: generate ( ) ,
109
108
service : service_name. to_string ( ) ,
110
109
service_instance : instance_name. to_string ( ) ,
@@ -119,8 +118,16 @@ impl TracingContext {
119
118
}
120
119
121
120
#[ inline]
122
- pub fn trace_id ( & self ) -> & str {
123
- & self . inner . trace_id
121
+ pub fn trace_id ( & self ) -> String {
122
+ self . with_trace_id ( ToString :: to_string)
123
+ }
124
+
125
+ fn with_trace_id < T > ( & self , f : impl FnOnce ( & String ) -> T ) -> T {
126
+ f ( & * self . inner . trace_id . try_read ( ) . expect ( LOCK_MSG ) )
127
+ }
128
+
129
+ fn with_trace_id_mut < T > ( & mut self , f : impl FnOnce ( & mut String ) -> T ) -> T {
130
+ f ( & mut * self . inner . trace_id . try_write ( ) . expect ( LOCK_MSG ) )
124
131
}
125
132
126
133
#[ inline]
@@ -182,8 +189,13 @@ impl TracingContext {
182
189
self . with_active_span_stack ( |stack| stack. last ( ) . map ( f) )
183
190
}
184
191
185
- // TODO Using for capture and continued.
186
- #[ allow( dead_code) ]
192
+ pub ( crate ) fn with_active_span_mut < T > (
193
+ & mut self ,
194
+ f : impl FnOnce ( & mut SpanObject ) -> T ,
195
+ ) -> Option < T > {
196
+ self . with_active_span_stack_mut ( |stack| stack. last_mut ( ) . map ( f) )
197
+ }
198
+
187
199
fn with_primary_endpoint_name < T > ( & self , f : impl FnOnce ( & String ) -> T ) -> T {
188
200
f ( & * self . inner . primary_endpoint_name . try_lock ( ) . expect ( LOCK_MSG ) )
189
201
}
@@ -209,7 +221,7 @@ impl TracingContext {
209
221
if let Some ( segment_link) = & self . inner . segment_link {
210
222
span. refs . push ( SegmentReference {
211
223
ref_type : RefType :: CrossProcess as i32 ,
212
- trace_id : self . inner . trace_id . clone ( ) ,
224
+ trace_id : self . trace_id ( ) ,
213
225
parent_trace_segment_id : segment_link. parent_trace_segment_id . clone ( ) ,
214
226
parent_span_id : segment_link. parent_span_id ,
215
227
parent_service : segment_link. parent_service . clone ( ) ,
@@ -273,6 +285,40 @@ impl TracingContext {
273
285
Span :: new ( index, self . downgrade ( ) )
274
286
}
275
287
288
+ /// Capture a snapshot for cross-thread propagation.
289
+ pub fn capture ( & self ) -> ContextSnapshot {
290
+ ContextSnapshot {
291
+ trace_id : self . trace_id ( ) ,
292
+ trace_segment_id : self . trace_segment_id ( ) . to_owned ( ) ,
293
+ span_id : self . peek_active_span_id ( ) . unwrap_or ( -1 ) ,
294
+ parent_endpoint : self . with_primary_endpoint_name ( Clone :: clone) ,
295
+ }
296
+ }
297
+
298
+ /// Build the reference between this segment and a cross-thread segment.
299
+ pub fn continued ( & mut self , snapshot : ContextSnapshot ) {
300
+ if snapshot. is_valid ( ) {
301
+ self . with_trace_id_mut ( |trace_id| * trace_id = snapshot. trace_id . clone ( ) ) ;
302
+
303
+ let tracer = self . upgrade_tracer ( ) ;
304
+
305
+ let segment_ref = SegmentReference {
306
+ ref_type : RefType :: CrossThread as i32 ,
307
+ trace_id : snapshot. trace_id ,
308
+ parent_trace_segment_id : snapshot. trace_segment_id ,
309
+ parent_span_id : snapshot. span_id ,
310
+ parent_service : tracer. service_name ( ) . to_owned ( ) ,
311
+ parent_service_instance : tracer. instance_name ( ) . to_owned ( ) ,
312
+ parent_endpoint : snapshot. parent_endpoint ,
313
+ network_address_used_at_peer : Default :: default ( ) ,
314
+ } ;
315
+
316
+ self . with_active_span_mut ( |span| {
317
+ span. refs . push ( segment_ref) ;
318
+ } ) ;
319
+ }
320
+ }
321
+
276
322
/// Close span. We can't use closed span after finalize called.
277
323
pub ( crate ) fn finalize_span ( & mut self , index : usize ) -> Result < ( ) , ( ) > {
278
324
let span = self . pop_active_span ( index) ;
@@ -290,7 +336,7 @@ impl TracingContext {
290
336
///
291
337
/// Notice: The spans will taked, so this method shouldn't be called twice.
292
338
pub ( crate ) fn convert_segment_object ( & mut self ) -> SegmentObject {
293
- let trace_id = self . trace_id ( ) . to_owned ( ) ;
339
+ let trace_id = self . trace_id ( ) ;
294
340
let trace_segment_id = self . trace_segment_id ( ) . to_owned ( ) ;
295
341
let service = self . service ( ) . to_owned ( ) ;
296
342
let service_instance = self . service_instance ( ) . to_owned ( ) ;
@@ -368,12 +414,11 @@ impl WeakTracingContext {
368
414
}
369
415
}
370
416
417
+ #[ derive( Debug ) ]
371
418
pub struct ContextSnapshot {
372
419
trace_id : String ,
373
420
trace_segment_id : String ,
374
421
span_id : i32 ,
375
- // TODO Using for capture and continued.
376
- #[ allow( dead_code) ]
377
422
parent_endpoint : String ,
378
423
}
379
424
0 commit comments