1818//! Span from Google Dapper Paper.
1919
2020use crate :: {
21- common:: system_time:: { fetch_time, TimePeriod } ,
21+ common:: {
22+ system_time:: { fetch_time, TimePeriod } ,
23+ wait_group:: WaitGroup ,
24+ } ,
2225 proto:: v3:: { SpanLayer , SpanObject , SpanType } ,
23- trace:: trace_context:: SpanStack ,
26+ trace:: trace_context:: { SpanStack , SpanUid } ,
2427} ;
25- use std:: { fmt:: Formatter , mem:: take, sync:: Arc } ;
28+ use std:: {
29+ fmt:: { self , Formatter } ,
30+ mem:: take,
31+ sync:: { Arc , Weak } ,
32+ } ;
33+
34+ /// [AbstractSpan] contains methods handle [SpanObject].
35+ pub trait AbstractSpan {
36+ /// Get immutable span object reference.
37+ fn span_object ( & self ) -> & SpanObject ;
38+
39+ /// Mutable with inner span object.
40+ fn span_object_mut ( & mut self ) -> & mut SpanObject ;
41+
42+ /// Get span id.
43+ fn span_id ( & self ) -> i32 {
44+ self . span_object ( ) . span_id
45+ }
46+
47+ /// Add logs to the span.
48+ fn add_log < K , V , I > ( & mut self , message : I )
49+ where
50+ K : Into < String > ,
51+ V : Into < String > ,
52+ I : IntoIterator < Item = ( K , V ) > ,
53+ {
54+ self . span_object_mut ( ) . add_log ( message)
55+ }
56+
57+ /// Add tag to the span.
58+ fn add_tag ( & mut self , key : impl Into < String > , value : impl Into < String > ) {
59+ self . span_object_mut ( ) . add_tag ( key, value)
60+ }
61+ }
2662
2763/// Span is a concept that represents trace information for a single RPC.
2864/// The Rust SDK supports Entry Span to represent inbound to a service
@@ -61,13 +97,14 @@ use std::{fmt::Formatter, mem::take, sync::Arc};
6197/// ```
6298#[ must_use = "assign a variable name to guard the span not be dropped immediately." ]
6399pub struct Span {
64- index : usize ,
100+ uid : SpanUid ,
65101 obj : Option < SpanObject > ,
102+ wg : WaitGroup ,
66103 stack : Arc < SpanStack > ,
67104}
68105
69- impl std :: fmt:: Debug for Span {
70- fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std :: fmt:: Result {
106+ impl fmt:: Debug for Span {
107+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
71108 f. debug_struct ( "Span" )
72109 . field (
73110 "data" ,
@@ -83,10 +120,11 @@ impl std::fmt::Debug for Span {
83120const SKYWALKING_RUST_COMPONENT_ID : i32 = 11000 ;
84121
85122impl Span {
86- pub ( crate ) fn new ( index : usize , obj : SpanObject , stack : Arc < SpanStack > ) -> Self {
123+ pub ( crate ) fn new ( uid : SpanUid , obj : SpanObject , wg : WaitGroup , stack : Arc < SpanStack > ) -> Self {
87124 Self {
88- index ,
125+ uid ,
89126 obj : Some ( obj) ,
127+ wg,
90128 stack,
91129 }
92130 }
@@ -115,53 +153,121 @@ impl Span {
115153 }
116154 }
117155
118- /// Get immutable span object reference.
156+ fn is_active_span ( & self ) -> bool {
157+ let active_spans = & * self . stack . active ( ) ;
158+ active_spans
159+ . last ( )
160+ . map ( |span| span. uid ( ) == self . uid )
161+ . unwrap_or_default ( )
162+ }
163+
164+ /// The [Span] finish at current tracing context, but the current span is
165+ /// still alive, until [AsyncSpan] dropped.
166+ ///
167+ /// This method must be called:
168+ ///
169+ /// 1. In original thread (tracing context).
170+ /// 2. Current span is active span.
171+ ///
172+ /// During alive, tags, logs and attributes of the span could be changed, in
173+ /// any thread.
174+ ///
175+ /// # Panics
176+ ///
177+ /// Current span could by active span.
178+ pub fn prepare_for_async ( mut self ) -> AsyncSpan {
179+ if !self . is_active_span ( ) {
180+ panic ! ( "current span isn't active span" ) ;
181+ }
182+
183+ self . wg . add ( 1 ) ;
184+
185+ AsyncSpan {
186+ uid : self . uid ,
187+ wg : self . wg . clone ( ) ,
188+ obj : take ( & mut self . obj ) ,
189+ stack : Arc :: downgrade ( & self . stack ) ,
190+ }
191+ }
192+ }
193+
194+ impl Drop for Span {
195+ /// Set the end time as current time, pop from context active span stack,
196+ /// and push to context spans.
197+ fn drop ( & mut self ) {
198+ self . stack . finalize_span ( self . uid , take ( & mut self . obj ) ) ;
199+ }
200+ }
201+
202+ impl AbstractSpan for Span {
119203 #[ inline]
120- pub fn span_object ( & self ) -> & SpanObject {
204+ fn span_object ( & self ) -> & SpanObject {
121205 self . obj . as_ref ( ) . unwrap ( )
122206 }
123207
124- /// Mutable with inner span object.
125208 #[ inline]
126- pub fn span_object_mut ( & mut self ) -> & mut SpanObject {
209+ fn span_object_mut ( & mut self ) -> & mut SpanObject {
127210 self . obj . as_mut ( ) . unwrap ( )
128211 }
212+ }
129213
130- /// Get span id.
131- pub fn span_id ( & self ) -> i32 {
132- self . span_object ( ) . span_id
133- }
134-
135- /// Add logs to the span.
136- pub fn add_log < K , V , I > ( & mut self , message : I )
137- where
138- K : Into < String > ,
139- V : Into < String > ,
140- I : IntoIterator < Item = ( K , V ) > ,
141- {
142- self . span_object_mut ( ) . add_log ( message)
143- }
214+ /// Generated by [Span::prepare_for_async], tags, logs and attributes of the
215+ /// span could be changed, in any thread.
216+ ///
217+ /// It could be finished when dropped.
218+ #[ must_use = "assign a variable name to guard the active span not be dropped immediately." ]
219+ pub struct AsyncSpan {
220+ uid : SpanUid ,
221+ obj : Option < SpanObject > ,
222+ wg : WaitGroup ,
223+ stack : Weak < SpanStack > ,
224+ }
144225
145- /// Add tag to the span.
146- pub fn add_tag ( & mut self , key : impl Into < String > , value : impl Into < String > ) {
147- self . span_object_mut ( ) . add_tag ( key, value)
226+ impl fmt:: Debug for AsyncSpan {
227+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
228+ f. debug_struct ( "AsyncSpan" )
229+ . field (
230+ "data" ,
231+ match self . obj {
232+ Some ( ref obj) => obj,
233+ None => & "<none>" ,
234+ } ,
235+ )
236+ . finish ( )
148237 }
149238}
150239
151- impl Drop for Span {
152- /// Set the end time as current time, pop from context active span stack,
153- /// and push to context spans.
240+ impl Drop for AsyncSpan {
241+ /// Set the end time as current time.
154242 fn drop ( & mut self ) {
155243 self . stack
156- . finalize_span ( self . index , take ( & mut self . obj ) . unwrap ( ) ) ;
244+ . upgrade ( )
245+ . expect ( "TracingContext has dropped" )
246+ . finalize_async_span ( self . uid , take ( & mut self . obj ) . unwrap ( ) ) ;
247+
248+ self . wg . done ( ) ;
249+ }
250+ }
251+
252+ impl AbstractSpan for AsyncSpan {
253+ #[ inline]
254+ fn span_object ( & self ) -> & SpanObject {
255+ self . obj . as_ref ( ) . unwrap ( )
256+ }
257+
258+ #[ inline]
259+ fn span_object_mut ( & mut self ) -> & mut SpanObject {
260+ self . obj . as_mut ( ) . unwrap ( )
157261 }
158262}
159263
160264#[ cfg( test) ]
161265mod tests {
162266 use super :: * ;
163267
164- trait AssertSend : Send { }
268+ trait AssertSend : Send + ' static { }
165269
166270 impl AssertSend for Span { }
271+
272+ impl AssertSend for AsyncSpan { }
167273}
0 commit comments