@@ -33,12 +33,12 @@ use std::{
3333 mem:: take,
3434 sync:: {
3535 atomic:: { AtomicI32 , Ordering } ,
36- Arc , Mutex , Weak ,
36+ Arc , Mutex , RwLock , Weak ,
3737 } ,
3838} ;
3939
4040struct Inner {
41- trace_id : String ,
41+ trace_id : RwLock < String > ,
4242 trace_segment_id : String ,
4343 service : String ,
4444 service_instance : String ,
@@ -49,8 +49,7 @@ struct Inner {
4949 primary_endpoint_name : Mutex < String > ,
5050}
5151
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." ]
5453pub struct TracingContext {
5554 inner : Arc < Inner > ,
5655 tracer : WeakTracer ,
@@ -79,7 +78,7 @@ impl TracingContext {
7978 ) -> Self {
8079 TracingContext {
8180 inner : Arc :: new ( Inner {
82- trace_id : RandomGenerator :: generate ( ) ,
81+ trace_id : RwLock :: new ( RandomGenerator :: generate ( ) ) ,
8382 trace_segment_id : RandomGenerator :: generate ( ) ,
8483 service : service_name. to_string ( ) ,
8584 service_instance : instance_name. to_string ( ) ,
@@ -104,7 +103,7 @@ impl TracingContext {
104103 ) -> Self {
105104 TracingContext {
106105 inner : Arc :: new ( Inner {
107- trace_id : context. parent_trace_id . clone ( ) ,
106+ trace_id : RwLock :: new ( context. parent_trace_id . clone ( ) ) ,
108107 trace_segment_id : RandomGenerator :: generate ( ) ,
109108 service : service_name. to_string ( ) ,
110109 service_instance : instance_name. to_string ( ) ,
@@ -119,8 +118,16 @@ impl TracingContext {
119118 }
120119
121120 #[ 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 ) )
124131 }
125132
126133 #[ inline]
@@ -182,8 +189,13 @@ impl TracingContext {
182189 self . with_active_span_stack ( |stack| stack. last ( ) . map ( f) )
183190 }
184191
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+
187199 fn with_primary_endpoint_name < T > ( & self , f : impl FnOnce ( & String ) -> T ) -> T {
188200 f ( & * self . inner . primary_endpoint_name . try_lock ( ) . expect ( LOCK_MSG ) )
189201 }
@@ -209,7 +221,7 @@ impl TracingContext {
209221 if let Some ( segment_link) = & self . inner . segment_link {
210222 span. refs . push ( SegmentReference {
211223 ref_type : RefType :: CrossProcess as i32 ,
212- trace_id : self . inner . trace_id . clone ( ) ,
224+ trace_id : self . trace_id ( ) ,
213225 parent_trace_segment_id : segment_link. parent_trace_segment_id . clone ( ) ,
214226 parent_span_id : segment_link. parent_span_id ,
215227 parent_service : segment_link. parent_service . clone ( ) ,
@@ -273,6 +285,40 @@ impl TracingContext {
273285 Span :: new ( index, self . downgrade ( ) )
274286 }
275287
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+
276322 /// Close span. We can't use closed span after finalize called.
277323 pub ( crate ) fn finalize_span ( & mut self , index : usize ) -> Result < ( ) , ( ) > {
278324 let span = self . pop_active_span ( index) ;
@@ -290,7 +336,7 @@ impl TracingContext {
290336 ///
291337 /// Notice: The spans will taked, so this method shouldn't be called twice.
292338 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 ( ) ;
294340 let trace_segment_id = self . trace_segment_id ( ) . to_owned ( ) ;
295341 let service = self . service ( ) . to_owned ( ) ;
296342 let service_instance = self . service_instance ( ) . to_owned ( ) ;
@@ -368,12 +414,11 @@ impl WeakTracingContext {
368414 }
369415}
370416
417+ #[ derive( Debug ) ]
371418pub struct ContextSnapshot {
372419 trace_id : String ,
373420 trace_segment_id : String ,
374421 span_id : i32 ,
375- // TODO Using for capture and continued.
376- #[ allow( dead_code) ]
377422 parent_endpoint : String ,
378423}
379424
0 commit comments