@@ -15,16 +15,16 @@ use crate::{GuestSpan, InstanceState};
1515
1616#[ async_trait]
1717impl tracer:: Host for InstanceState {
18- // TODO(Caleb): Make this implicit logic make more sense (the indexmap seems wrong)
19- // TODO(Caleb): Properly implement this
2018 async fn start (
2119 & mut self ,
2220 name : String ,
23- _options : Option < tracer:: StartOptions > ,
21+ options : Option < tracer:: StartOptions > ,
2422 ) -> Result < Resource < tracer:: Span > > {
2523 let mut state = self . state . write ( ) . unwrap ( ) ;
24+ let options = options. unwrap_or_default ( ) ;
2625
27- if state. active_spans . is_empty ( ) {
26+ // Before we ever create any new spans make sure we track the original host span ID
27+ if state. original_host_span_id . is_none ( ) {
2828 state. original_host_span_id = Some (
2929 tracing:: Span :: current ( )
3030 . context ( )
@@ -34,31 +34,47 @@ impl tracer::Host for InstanceState {
3434 ) ;
3535 }
3636
37- // TODO(Caleb): Make this cleaner
38- let parent_context = match state. active_spans . is_empty ( ) {
39- true => tracing :: Span :: current ( ) . context ( ) ,
40- false => Context :: new ( ) . with_remote_span_context (
41- state
37+ // Get span's parent based on whether it's a new root and whether there are any active spans
38+ let parent_context = match ( options . new_root , state. active_spans . is_empty ( ) ) {
39+ // Not a new root | Active spans -> Last active guest span is parent
40+ ( false , false ) => {
41+ let span_context = state
4242 . guest_spans
43- . get ( * state. active_spans . last ( ) . unwrap ( ) . 1 )
43+ . get ( * state. active_spans . last ( ) . unwrap ( ) )
4444 . unwrap ( )
4545 . inner
4646 . span_context ( )
47- . clone ( ) ,
48- ) ,
47+ . clone ( ) ;
48+ Context :: new ( ) . with_remote_span_context ( span_context)
49+ }
50+ // Not a new root | No active spans -> Current host span is parent
51+ ( false , true ) => tracing:: Span :: current ( ) . context ( ) ,
52+ // New root | n/a -> No parent
53+ ( true , _) => Context :: new ( ) ,
4954 } ;
5055
5156 // Create the underlying opentelemetry span
52- let otel_span = self . tracer . start_with_context ( name, & parent_context) ;
53-
54- let span_id = otel_span. span_context ( ) . span_id ( ) . to_string ( ) ;
57+ let mut builder = self . tracer . span_builder ( name) ;
58+ if let Some ( kind) = options. span_kind {
59+ builder = builder. with_kind ( kind. into ( ) ) ;
60+ }
61+ if let Some ( attributes) = options. attributes {
62+ builder = builder. with_attributes ( attributes. into_iter ( ) . map ( Into :: into) ) ;
63+ }
64+ if let Some ( links) = options. links {
65+ builder = builder. with_links ( links. into_iter ( ) . map ( Into :: into) . collect ( ) ) ;
66+ }
67+ if let Some ( timestamp) = options. timestamp {
68+ builder = builder. with_start_time ( timestamp) ;
69+ }
70+ let otel_span = builder. start_with_context ( & self . tracer , & parent_context) ;
5571
5672 // Wrap it in a GuestSpan for our own bookkeeping purposes
5773 let guest_span = GuestSpan { inner : otel_span } ;
5874
59- // Put the GuestSpan in our resource table and push it to our stack of active spans
75+ // Put the GuestSpan in our resource table and push it on to our stack of active spans
6076 let resource_id = state. guest_spans . push ( guest_span) . unwrap ( ) ;
61- state. active_spans . insert ( span_id , resource_id) ;
77+ state. active_spans . insert ( resource_id) ;
6278
6379 Ok ( Resource :: new_own ( resource_id) )
6480 }
@@ -203,30 +219,33 @@ impl tracer::HostSpan for InstanceState {
203219 resource : Resource < tracer:: Span > ,
204220 timestamp : Option < tracer:: Datetime > ,
205221 ) -> Result < ( ) > {
206- if let Some ( guest_span) = self
207- . state
208- . write ( )
209- . unwrap ( )
210- . guest_spans
211- . get_mut ( resource. rep ( ) )
212- {
222+ let mut state = self . state . write ( ) . unwrap ( ) ;
223+ if let Some ( guest_span) = state. guest_spans . get_mut ( resource. rep ( ) ) {
213224 if let Some ( timestamp) = timestamp {
214225 guest_span. inner . end_with_timestamp ( timestamp. into ( ) ) ;
215226 } else {
216227 guest_span. inner . end ( ) ;
217228 }
229+
230+ // Remove the span from active_spans
231+ state. active_spans . shift_remove ( & resource. rep ( ) ) ;
232+
218233 Ok ( ( ) )
219234 } else {
220235 Err ( anyhow ! ( "BUG: cannot find resource in table" ) )
221236 }
222237 }
223238
224- fn drop ( & mut self , _: Resource < tracer:: Span > ) -> Result < ( ) > {
225- // Dropping the resource automatically calls drop on the Span which ends itself with the current timestamp
239+ fn drop ( & mut self , resource : Resource < tracer:: Span > ) -> Result < ( ) > {
240+ // Dropping the resource automatically calls drop on the Span which ends itself with the
241+ // current timestamp if the Span is not already ended.
242+
243+ // Ensure that the span has been removed from active_spans
244+ let mut state = self . state . write ( ) . unwrap ( ) ;
245+ state. active_spans . shift_remove ( & resource. rep ( ) ) ;
246+
226247 Ok ( ( ) )
227248 }
228249}
229250
230- // TODO(Caleb): Move the tests from integration.rs to here
231251// TODO(Caleb): Write tests somewhere for all the finicky type conversion stuff
232- // TODO(Caleb): Maybe introduce macro to reduce boilerplate of finding resource
0 commit comments