@@ -19,7 +19,7 @@ pub struct Span {
19
19
inner : Arc < SpanInner > ,
20
20
}
21
21
22
- /// Inner data, processed and exported on drop
22
+ /// Inner data, processed and exported on end
23
23
#[ derive( Debug ) ]
24
24
struct SpanInner {
25
25
span_context : SpanContext ,
@@ -107,8 +107,14 @@ impl crate::trace::Span for Span {
107
107
108
108
/// Returns true if this `Span` is recording information like events with the `add_event`
109
109
/// operation, attributes using `set_attributes`, status with `set_status`, etc.
110
+ /// Always returns false after span `end`.
110
111
fn is_recording ( & self ) -> bool {
111
- self . inner . data . is_some ( )
112
+ if let Some ( data) = & self . inner . data {
113
+ if let Ok ( span_data) = data. lock ( ) {
114
+ return span_data. is_some ( ) ;
115
+ }
116
+ }
117
+ false
112
118
}
113
119
114
120
/// Sets a single `Attribute` where the attribute properties are passed as arguments.
@@ -140,24 +146,25 @@ impl crate::trace::Span for Span {
140
146
141
147
/// Finishes the span with given timestamp.
142
148
fn end_with_timestamp ( & self , timestamp : SystemTime ) {
143
- self . with_data ( |data| {
144
- data. end_time = timestamp;
145
- } ) ;
149
+ self . inner . ensure_ended_and_exported ( Some ( timestamp) ) ;
146
150
}
147
151
}
148
152
149
- impl Drop for SpanInner {
150
- /// Report span on inner drop
151
- fn drop ( & mut self ) {
152
- if let Some ( data) = self . data . take ( ) {
153
+ impl SpanInner {
154
+ fn ensure_ended_and_exported ( & self , timestamp : Option < SystemTime > ) {
155
+ if let Some ( data) = & self . data {
153
156
if let Ok ( mut span_data) = data. lock ( ) . map ( |mut data| data. take ( ) ) {
154
- if let Some ( provider ) = self . tracer . provider ( ) {
155
- // Set end time if unset or invalid
156
- if let Some ( data ) = span_data . as_mut ( ) {
157
- if data . end_time <= data . start_time {
158
- data . end_time = SystemTime :: now ( ) ;
159
- }
157
+ // Ensure end time is set via explicit end or implicitly on drop
158
+ if let Some ( span_data ) = span_data . as_mut ( ) {
159
+ if let Some ( timestamp ) = timestamp {
160
+ span_data . end_time = timestamp ;
161
+ } else if span_data . end_time == span_data . start_time {
162
+ span_data . end_time = SystemTime :: now ( ) ;
160
163
}
164
+ }
165
+
166
+ // Notify each span processor that the span has ended
167
+ if let Some ( provider) = self . tracer . provider ( ) {
161
168
let mut processors = provider. span_processors ( ) . iter ( ) . peekable ( ) ;
162
169
while let Some ( processor) = processors. next ( ) {
163
170
let span_data = if processors. peek ( ) . is_none ( ) {
@@ -182,6 +189,13 @@ impl Drop for SpanInner {
182
189
}
183
190
}
184
191
192
+ impl Drop for SpanInner {
193
+ /// Report span on inner drop
194
+ fn drop ( & mut self ) {
195
+ self . ensure_ended_and_exported ( None ) ;
196
+ }
197
+ }
198
+
185
199
fn build_export_data (
186
200
data : SpanData ,
187
201
span_context : SpanContext ,
@@ -374,7 +388,20 @@ mod tests {
374
388
}
375
389
376
390
#[ test]
377
- #[ ignore = "not yet implemented" ]
391
+ fn allows_to_get_span_context_after_end ( ) {
392
+ let span = create_span ( ) ;
393
+ span. end ( ) ;
394
+ assert_eq ! ( span. span_context( ) , & SpanContext :: empty_context( ) ) ;
395
+ }
396
+
397
+ #[ test]
398
+ fn allows_to_get_span_context_after_clone_drop ( ) {
399
+ let span = create_span ( ) ;
400
+ drop ( span. clone ( ) ) ;
401
+ assert_eq ! ( span. span_context( ) , & SpanContext :: empty_context( ) ) ;
402
+ }
403
+
404
+ #[ test]
378
405
fn end_only_once ( ) {
379
406
let span = create_span ( ) ;
380
407
let timestamp = SystemTime :: now ( ) ;
@@ -384,7 +411,6 @@ mod tests {
384
411
}
385
412
386
413
#[ test]
387
- #[ ignore = "not yet implemented" ]
388
414
fn noop_after_end ( ) {
389
415
let span = create_span ( ) ;
390
416
let initial = span. with_data ( |data| data. clone ( ) ) . unwrap ( ) ;
@@ -417,7 +443,6 @@ mod tests {
417
443
}
418
444
419
445
#[ test]
420
- #[ ignore = "not yet implemented" ]
421
446
fn is_recording_false_after_end ( ) {
422
447
let span = create_span ( ) ;
423
448
span. end ( ) ;
0 commit comments