Change Span to refer to SpanStack, rather than TracingContext. (#39)

diff --git a/e2e/src/main.rs b/e2e/src/main.rs
index cccac22..8674ed2 100644
--- a/e2e/src/main.rs
+++ b/e2e/src/main.rs
@@ -112,8 +112,8 @@
             .unwrap(),
     )
     .unwrap();
-    let mut context = tracer::create_trace_context_from_propagation(ctx);
-    let _span = context.create_entry_span("/pong");
+    let mut context = tracer::create_trace_context();
+    let _span = context.create_entry_span_with_propagation("/pong", &ctx);
     Ok(Response::new(Body::from("hoge")))
 }
 
diff --git a/src/context/span.rs b/src/context/span.rs
index 692b653..8fced96 100644
--- a/src/context/span.rs
+++ b/src/context/span.rs
@@ -14,12 +14,17 @@
 // limitations under the License.
 //
 
-use crate::skywalking_proto::v3::{SpanLayer, SpanObject, SpanType};
-use std::fmt::Formatter;
-
 use super::{
     system_time::{fetch_time, TimePeriod},
-    trace_context::{TracingContext, WeakTracingContext},
+    trace_context::SpanStack,
+};
+use crate::{
+    error::LOCK_MSG,
+    skywalking_proto::v3::{SpanLayer, SpanObject, SpanType},
+};
+use std::{
+    fmt::Formatter,
+    sync::{Arc, Weak},
 };
 
 /// Span is a concept that represents trace information for a single RPC.
@@ -60,34 +65,38 @@
 #[must_use = "assign a variable name to guard the span not be dropped immediately."]
 pub struct Span {
     index: usize,
-    context: WeakTracingContext,
+    stack: Weak<SpanStack>,
 }
 
 impl std::fmt::Debug for Span {
     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
-        let mut d = f.debug_struct("Span");
-        match self.context.upgrade() {
-            Some(context) => {
-                let op = context.try_with_active_span_stack(|stack| {
-                    d.field("data", &stack.get(self.index));
-                });
-                if op.is_none() {
-                    d.field("data", &format_args!("<locked>"));
-                }
-            }
-            None => {
-                d.field("context", &format_args!("<dropped>"));
-            }
-        }
-        d.finish()
+        let span_object: SpanObject;
+        f.debug_struct("Span")
+            .field(
+                "data",
+                match self.stack.upgrade() {
+                    Some(stack) => match stack.active.try_read() {
+                        Ok(spans) => match spans.get(self.index) {
+                            Some(span) => {
+                                span_object = span.clone();
+                                &span_object
+                            }
+                            None => &"<hanged>",
+                        },
+                        Err(_) => &"<locked>",
+                    },
+                    None => &"<dropped>",
+                },
+            )
+            .finish()
     }
 }
 
 const SKYWALKING_RUST_COMPONENT_ID: i32 = 11000;
 
 impl Span {
-    pub(crate) fn new(index: usize, context: WeakTracingContext) -> Self {
-        Self { index, context }
+    pub(crate) fn new(index: usize, stack: Weak<SpanStack>) -> Self {
+        Self { index, stack }
     }
 
     #[allow(clippy::too_many_arguments)]
@@ -114,21 +123,17 @@
         }
     }
 
-    fn upgrade_context(&self) -> TracingContext {
-        self.context.upgrade().expect("Context has dropped")
+    fn upgrade_stack(&self) -> Arc<SpanStack> {
+        self.stack.upgrade().expect("Context has dropped")
     }
 
-    // Notice: Perhaps in the future, `RwLock` can be used instead of `Mutex`, so
-    // `with_*` can be nested. (Although I can't find the meaning of such use at
-    // present.)
     pub fn with_span_object<T>(&self, f: impl FnOnce(&SpanObject) -> T) -> T {
-        self.upgrade_context()
-            .with_active_span_stack(|stack| f(&stack[self.index]))
+        self.upgrade_stack()
+            .with_active(|stack| f(&stack[self.index]))
     }
 
     pub fn with_span_object_mut<T>(&mut self, f: impl FnOnce(&mut SpanObject) -> T) -> T {
-        self.upgrade_context()
-            .with_active_span_stack_mut(|stack| f(&mut stack[self.index]))
+        f(&mut (self.upgrade_stack().active.try_write().expect(LOCK_MSG))[self.index])
     }
 
     pub fn span_id(&self) -> i32 {
@@ -159,9 +164,7 @@
     ///
     /// Panic if context is dropped or this span isn't the active span.
     fn drop(&mut self) {
-        if self.upgrade_context().finalize_span(self.index).is_err() {
-            panic!("Dropped span isn't the active span");
-        }
+        self.upgrade_stack().finalize_span(self.index);
     }
 }
 
diff --git a/src/context/trace_context.rs b/src/context/trace_context.rs
index 107daea..be0a7a1 100644
--- a/src/context/trace_context.rs
+++ b/src/context/trace_context.rs
@@ -30,159 +30,157 @@
 use std::{
     fmt::Formatter,
     mem::take,
-    sync::{
-        atomic::{AtomicI32, Ordering},
-        Arc, Mutex, RwLock, Weak,
-    },
+    sync::{Arc, RwLock},
 };
 
-struct Inner {
-    trace_id: RwLock<String>,
-    trace_segment_id: String,
-    service: String,
-    service_instance: String,
-    next_span_id: AtomicI32,
-    spans: Mutex<Vec<SpanObject>>,
-    active_span_stack: Mutex<Vec<SpanObject>>,
-    segment_link: Option<PropagationContext>,
-    primary_endpoint_name: Mutex<String>,
+#[derive(Default)]
+pub(crate) struct SpanStack {
+    pub(crate) finialized: RwLock<Vec<SpanObject>>,
+    pub(crate) active: RwLock<Vec<SpanObject>>,
+}
+
+impl SpanStack {
+    pub(crate) fn with_finialized<T>(&self, f: impl FnOnce(&Vec<SpanObject>) -> T) -> T {
+        f(&self.finialized.try_read().expect(LOCK_MSG))
+    }
+
+    pub(crate) fn with_finialized_mut<T>(&self, f: impl FnOnce(&mut Vec<SpanObject>) -> T) -> T {
+        f(&mut *self.finialized.try_write().expect(LOCK_MSG))
+    }
+
+    pub(crate) fn with_active<T>(&self, f: impl FnOnce(&Vec<SpanObject>) -> T) -> T {
+        f(&*self.active.try_read().expect(LOCK_MSG))
+    }
+
+    pub(crate) fn with_active_mut<T>(&self, f: impl FnOnce(&mut Vec<SpanObject>) -> T) -> T {
+        f(&mut *self.active.try_write().expect(LOCK_MSG))
+    }
+
+    fn pop_active(&self, index: usize) -> Option<SpanObject> {
+        self.with_active_mut(|stack| {
+            if stack.len() > index + 1 {
+                None
+            } else {
+                stack.pop()
+            }
+        })
+    }
+
+    /// Close span. We can't use closed span after finalize called.
+    pub(crate) fn finalize_span(&self, index: usize) {
+        let span = self.pop_active(index);
+        if let Some(mut span) = span {
+            span.end_time = fetch_time(TimePeriod::End);
+            self.with_finialized_mut(|spans| spans.push(span));
+        } else {
+            panic!("Finalize span isn't the active span");
+        }
+    }
 }
 
 #[must_use = "call `create_entry_span` after `TracingContext` created."]
 pub struct TracingContext {
-    inner: Arc<Inner>,
+    trace_id: String,
+    trace_segment_id: String,
+    service: String,
+    service_instance: String,
+    next_span_id: i32,
+    span_stack: Arc<SpanStack>,
+    primary_endpoint_name: String,
     tracer: WeakTracer,
 }
 
 impl std::fmt::Debug for TracingContext {
     fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+        let span_objects: Vec<SpanObject>;
         f.debug_struct("TracingContext")
-            .field("trace_id", &self.inner.trace_id)
-            .field("trace_segment_id", &self.inner.trace_segment_id)
-            .field("service", &self.inner.service)
-            .field("service_instance", &self.inner.service_instance)
-            .field("next_span_id", &self.inner.next_span_id)
-            .field("spans", &self.inner.spans)
+            .field("trace_id", &self.trace_id)
+            .field("trace_segment_id", &self.trace_segment_id)
+            .field("service", &self.service)
+            .field("service_instance", &self.service_instance)
+            .field("next_span_id", &self.next_span_id)
+            .field(
+                "finialized_spans",
+                match self.span_stack.finialized.try_read() {
+                    Ok(spans) => {
+                        span_objects = spans.clone();
+                        &span_objects
+                    }
+                    Err(_) => &"<locked>",
+                },
+            )
             .finish()
     }
 }
 
 impl TracingContext {
-    /// Generate a new trace context. Typically called when no context has
-    /// been propagated and a new trace is to be started.
+    /// Generate a new trace context.
     pub(crate) fn new(
         service_name: impl ToString,
         instance_name: impl ToString,
         tracer: WeakTracer,
     ) -> Self {
         TracingContext {
-            inner: Arc::new(Inner {
-                trace_id: RwLock::new(RandomGenerator::generate()),
-                trace_segment_id: RandomGenerator::generate(),
-                service: service_name.to_string(),
-                service_instance: instance_name.to_string(),
-                next_span_id: Default::default(),
-                spans: Default::default(),
-                segment_link: None,
-                active_span_stack: Default::default(),
-                primary_endpoint_name: Default::default(),
-            }),
-            tracer,
-        }
-    }
-
-    /// Generate a new trace context using the propagated context.
-    /// They should be propagated on `sw8` header in HTTP request with encoded
-    /// form. You can retrieve decoded context with
-    /// `skywalking::context::propagation::encoder::encode_propagation`
-    pub(crate) fn from_propagation_context(
-        service_name: impl ToString,
-        instance_name: impl ToString,
-        context: PropagationContext,
-        tracer: WeakTracer,
-    ) -> Self {
-        TracingContext {
-            inner: Arc::new(Inner {
-                trace_id: RwLock::new(context.parent_trace_id.clone()),
-                trace_segment_id: RandomGenerator::generate(),
-                service: service_name.to_string(),
-                service_instance: instance_name.to_string(),
-                next_span_id: Default::default(),
-                spans: Default::default(),
-                segment_link: Some(context),
-                active_span_stack: Default::default(),
-                primary_endpoint_name: Default::default(),
-            }),
+            trace_id: RandomGenerator::generate(),
+            trace_segment_id: RandomGenerator::generate(),
+            service: service_name.to_string(),
+            service_instance: instance_name.to_string(),
+            next_span_id: Default::default(),
+            span_stack: Default::default(),
+            primary_endpoint_name: Default::default(),
             tracer,
         }
     }
 
     #[inline]
-    pub fn trace_id(&self) -> String {
-        self.with_trace_id(ToString::to_string)
-    }
-
-    fn with_trace_id<T>(&self, f: impl FnOnce(&String) -> T) -> T {
-        f(&*self.inner.trace_id.try_read().expect(LOCK_MSG))
-    }
-
-    fn with_trace_id_mut<T>(&mut self, f: impl FnOnce(&mut String) -> T) -> T {
-        f(&mut *self.inner.trace_id.try_write().expect(LOCK_MSG))
+    pub fn trace_id(&self) -> &str {
+        &self.trace_id
     }
 
     #[inline]
     pub fn trace_segment_id(&self) -> &str {
-        &self.inner.trace_segment_id
+        &self.trace_segment_id
     }
 
     #[inline]
     pub fn service(&self) -> &str {
-        &self.inner.service
+        &self.service
     }
 
     #[inline]
     pub fn service_instance(&self) -> &str {
-        &self.inner.service_instance
+        &self.service_instance
     }
 
     fn next_span_id(&self) -> i32 {
-        self.inner.next_span_id.load(Ordering::Relaxed)
+        self.next_span_id
     }
 
     #[inline]
-    fn inc_next_span_id(&self) -> i32 {
-        self.inner.next_span_id.fetch_add(1, Ordering::Relaxed)
+    fn inc_next_span_id(&mut self) -> i32 {
+        let span_id = self.next_span_id;
+        self.next_span_id += 1;
+        span_id
     }
 
-    #[cfg(feature = "mock")]
-    pub fn with_spans<T>(&self, f: impl FnOnce(&Vec<SpanObject>) -> T) -> T {
-        f(&*self.inner.spans.try_lock().expect(LOCK_MSG))
+    pub fn last_span(&self) -> Option<SpanObject> {
+        self.span_stack
+            .with_finialized(|spans| spans.last().cloned())
     }
 
     fn with_spans_mut<T>(&mut self, f: impl FnOnce(&mut Vec<SpanObject>) -> T) -> T {
-        f(&mut *self.inner.spans.try_lock().expect(LOCK_MSG))
+        f(&mut *self.span_stack.finialized.try_write().expect(LOCK_MSG))
     }
 
     pub(crate) fn with_active_span_stack<T>(&self, f: impl FnOnce(&Vec<SpanObject>) -> T) -> T {
-        f(&*self.inner.active_span_stack.try_lock().expect(LOCK_MSG))
+        self.span_stack.with_active(f)
     }
 
     pub(crate) fn with_active_span_stack_mut<T>(
         &mut self,
         f: impl FnOnce(&mut Vec<SpanObject>) -> T,
     ) -> T {
-        f(&mut *self.inner.active_span_stack.try_lock().expect(LOCK_MSG))
-    }
-
-    pub(crate) fn try_with_active_span_stack<T>(
-        &self,
-        f: impl FnOnce(&Vec<SpanObject>) -> T,
-    ) -> Option<T> {
-        self.inner
-            .active_span_stack
-            .try_lock()
-            .ok()
-            .map(|stack| f(&*stack))
+        self.span_stack.with_active_mut(f)
     }
 
     pub(crate) fn with_active_span<T>(&self, f: impl FnOnce(&SpanObject) -> T) -> Option<T> {
@@ -196,19 +194,14 @@
         self.with_active_span_stack_mut(|stack| stack.last_mut().map(f))
     }
 
-    fn with_primary_endpoint_name<T>(&self, f: impl FnOnce(&String) -> T) -> T {
-        f(&*self.inner.primary_endpoint_name.try_lock().expect(LOCK_MSG))
-    }
-
-    fn with_primary_endpoint_name_mut<T>(&mut self, f: impl FnOnce(&mut String) -> T) -> T {
-        f(&mut *self.inner.primary_endpoint_name.try_lock().expect(LOCK_MSG))
-    }
-
     /// Create a new entry span, which is an initiator of collection of spans.
     /// This should be called by invocation of the function which is triggered
     /// by external service.
+    ///
+    /// Typically called when no context has
+    /// been propagated and a new trace is to be started.
     pub fn create_entry_span(&mut self, operation_name: &str) -> Span {
-        let mut span = Span::new_obj(
+        let span = Span::new_obj(
             self.inc_next_span_id(),
             self.peek_active_span_id().unwrap_or(-1),
             operation_name.to_string(),
@@ -218,21 +211,36 @@
             false,
         );
 
-        if let Some(segment_link) = &self.inner.segment_link {
+        let index = self.push_active_span(span);
+        Span::new(index, Arc::downgrade(&self.span_stack))
+    }
+
+    /// Create a new entry span, which is an initiator of collection of spans.
+    /// This should be called by invocation of the function which is triggered
+    /// by external service.
+    ///
+    /// They should be propagated on `sw8` header in HTTP request with encoded
+    /// form. You can retrieve decoded context with
+    /// `skywalking::context::propagation::encoder::encode_propagation`
+    pub fn create_entry_span_with_propagation(
+        &mut self,
+        operation_name: &str,
+        propagation: &PropagationContext,
+    ) -> Span {
+        let mut span = self.create_entry_span(operation_name);
+        span.with_span_object_mut(|span| {
             span.refs.push(SegmentReference {
                 ref_type: RefType::CrossProcess as i32,
-                trace_id: self.trace_id(),
-                parent_trace_segment_id: segment_link.parent_trace_segment_id.clone(),
-                parent_span_id: segment_link.parent_span_id,
-                parent_service: segment_link.parent_service.clone(),
-                parent_service_instance: segment_link.parent_service_instance.clone(),
-                parent_endpoint: segment_link.destination_endpoint.clone(),
-                network_address_used_at_peer: segment_link.destination_address.clone(),
+                trace_id: self.trace_id().to_owned(),
+                parent_trace_segment_id: propagation.parent_trace_segment_id.clone(),
+                parent_span_id: propagation.parent_span_id,
+                parent_service: propagation.parent_service.clone(),
+                parent_service_instance: propagation.parent_service_instance.clone(),
+                parent_endpoint: propagation.destination_endpoint.clone(),
+                network_address_used_at_peer: propagation.destination_address.clone(),
             });
-        }
-
-        let index = self.push_active_span(span);
-        Span::new(index, self.downgrade())
+        });
+        span
     }
 
     /// Create a new exit span, which will be created when tracing context will
@@ -258,7 +266,7 @@
         );
 
         let index = self.push_active_span(span);
-        Span::new(index, self.downgrade())
+        Span::new(index, Arc::downgrade(&self.span_stack))
     }
 
     /// Create a new local span.
@@ -282,23 +290,23 @@
         );
 
         let index = self.push_active_span(span);
-        Span::new(index, self.downgrade())
+        Span::new(index, Arc::downgrade(&self.span_stack))
     }
 
     /// Capture a snapshot for cross-thread propagation.
     pub fn capture(&self) -> ContextSnapshot {
         ContextSnapshot {
-            trace_id: self.trace_id(),
+            trace_id: self.trace_id().to_owned(),
             trace_segment_id: self.trace_segment_id().to_owned(),
             span_id: self.peek_active_span_id().unwrap_or(-1),
-            parent_endpoint: self.with_primary_endpoint_name(Clone::clone),
+            parent_endpoint: self.primary_endpoint_name.clone(),
         }
     }
 
     /// Build the reference between this segment and a cross-thread segment.
     pub fn continued(&mut self, snapshot: ContextSnapshot) {
         if snapshot.is_valid() {
-            self.with_trace_id_mut(|trace_id| *trace_id = snapshot.trace_id.clone());
+            self.trace_id = snapshot.trace_id.clone();
 
             let tracer = self.upgrade_tracer();
 
@@ -319,24 +327,12 @@
         }
     }
 
-    /// Close span. We can't use closed span after finalize called.
-    pub(crate) fn finalize_span(&mut self, index: usize) -> Result<(), ()> {
-        let span = self.pop_active_span(index);
-        if let Some(mut span) = span {
-            span.end_time = fetch_time(TimePeriod::End);
-            self.with_spans_mut(|spans| spans.push(span));
-            Ok(())
-        } else {
-            Err(())
-        }
-    }
-
     /// It converts tracing context into segment object.
     /// This conversion should be done before sending segments into OAP.
     ///
     /// Notice: The spans will taked, so this method shouldn't be called twice.
     pub(crate) fn convert_segment_object(&mut self) -> SegmentObject {
-        let trace_id = self.trace_id();
+        let trace_id = self.trace_id().to_owned();
         let trace_segment_id = self.trace_segment_id().to_owned();
         let service = self.service().to_owned();
         let service_instance = self.service_instance().to_owned();
@@ -357,30 +353,13 @@
     }
 
     fn push_active_span(&mut self, span: SpanObject) -> usize {
-        self.with_primary_endpoint_name_mut(|endpoint| *endpoint = span.operation_name.clone());
+        self.primary_endpoint_name = span.operation_name.clone();
         self.with_active_span_stack_mut(|stack| {
             stack.push(span);
             stack.len() - 1
         })
     }
 
-    fn pop_active_span(&mut self, index: usize) -> Option<SpanObject> {
-        self.with_active_span_stack_mut(|stack| {
-            if stack.len() > index + 1 {
-                None
-            } else {
-                stack.pop()
-            }
-        })
-    }
-
-    fn downgrade(&self) -> WeakTracingContext {
-        WeakTracingContext {
-            inner: Arc::downgrade(&self.inner),
-            tracer: self.tracer.clone(),
-        }
-    }
-
     fn upgrade_tracer(&self) -> Tracer {
         self.tracer.upgrade().expect("Tracer has dropped")
     }
@@ -393,24 +372,7 @@
     ///
     /// Panic if tracer is dropped.
     fn drop(&mut self) {
-        if Arc::strong_count(&self.inner) <= 1 {
-            self.upgrade_tracer().finalize_context(self)
-        }
-    }
-}
-
-#[derive(Clone)]
-pub(crate) struct WeakTracingContext {
-    inner: Weak<Inner>,
-    tracer: WeakTracer,
-}
-
-impl WeakTracingContext {
-    pub(crate) fn upgrade(&self) -> Option<TracingContext> {
-        self.inner.upgrade().map(|inner| TracingContext {
-            inner,
-            tracer: self.tracer.clone(),
-        })
+        self.upgrade_tracer().finalize_context(self)
     }
 }
 
diff --git a/src/context/tracer.rs b/src/context/tracer.rs
index f528b1f..bb161b8 100644
--- a/src/context/tracer.rs
+++ b/src/context/tracer.rs
@@ -14,7 +14,6 @@
 // limitations under the License.
 //
 
-use super::propagation::context::PropagationContext;
 use crate::{
     context::trace_context::TracingContext,
     reporter::{DynReporter, Reporter},
@@ -59,11 +58,6 @@
     global_tracer().create_trace_context()
 }
 
-/// Create trace conetxt from propagation by global tracer.
-pub fn create_trace_context_from_propagation(context: PropagationContext) -> TracingContext {
-    global_tracer().create_trace_context_from_propagation(context)
-}
-
 /// Start to reporting by global tracer, quit when shutdown_signal received.
 ///
 /// Accept a `shutdown_signal` argument as a graceful shutdown signal.
@@ -129,7 +123,7 @@
     instance_name: String,
     segment_sender: Box<dyn SegmentSender>,
     segment_receiver: Box<dyn SegmentReceiver>,
-    reporter: Box<Mutex<DynReporter>>,
+    reporter: Mutex<Box<DynReporter>>,
     is_reporting: AtomicBool,
     is_closed: AtomicBool,
 }
@@ -169,7 +163,7 @@
                 instance_name: instance_name.to_string(),
                 segment_sender: Box::new(channel.0),
                 segment_receiver: Box::new(channel.1),
-                reporter: Box::new(Mutex::new(reporter)),
+                reporter: Mutex::new(Box::new(reporter)),
                 is_reporting: Default::default(),
                 is_closed: Default::default(),
             }),
@@ -184,6 +178,15 @@
         &self.inner.instance_name
     }
 
+    /// Set the reporter, only valid if [`Tracer::reporting`] not started.
+    pub fn set_reporter(&self, reporter: impl Reporter + Send + Sync + 'static) {
+        if !self.inner.is_reporting.load(Ordering::Relaxed) {
+            if let Ok(mut lock) = self.inner.reporter.try_lock() {
+                *lock = Box::new(reporter);
+            }
+        }
+    }
+
     /// Create trace conetxt.
     pub fn create_trace_context(&self) -> TracingContext {
         TracingContext::new(
@@ -193,19 +196,6 @@
         )
     }
 
-    /// Create trace conetxt from propagation.
-    pub fn create_trace_context_from_propagation(
-        &self,
-        context: PropagationContext,
-    ) -> TracingContext {
-        TracingContext::from_propagation_context(
-            &self.inner.service_name,
-            &self.inner.instance_name,
-            context,
-            self.downgrade(),
-        )
-    }
-
     /// Finalize the trace context.
     pub(crate) fn finalize_context(&self, context: &mut TracingContext) {
         if self.inner.is_closed.load(Ordering::Relaxed) {
@@ -294,7 +284,7 @@
     }
 
     async fn report_segment_object(
-        reporter: &Mutex<DynReporter>,
+        reporter: &Mutex<Box<DynReporter>>,
         segments: LinkedList<SegmentObject>,
     ) {
         if let Err(err) = reporter.lock().await.collect(segments).await {
diff --git a/tests/trace_context.rs b/tests/trace_context.rs
index d3c9238..3a15d30 100644
--- a/tests/trace_context.rs
+++ b/tests/trace_context.rs
@@ -115,9 +115,7 @@
                         logs: Vec::<Log>::new(),
                         skip_analysis: false,
                     };
-                    context.with_spans(|spans| {
-                        assert_eq!(spans.last(), Some(&span3_expected));
-                    });
+                    assert_eq!(context.last_span(), Some(span3_expected));
                 }
 
                 {
@@ -143,9 +141,7 @@
                             logs: Vec::<Log>::new(),
                             skip_analysis: false,
                         };
-                        context.with_spans(|spans| {
-                            assert_eq!(spans.last(), Some(&span5_expected));
-                        });
+                        assert_eq!(context.last_span(), Some(span5_expected));
                     }
                 }
 
@@ -167,9 +163,7 @@
                     logs: expected_log,
                     skip_analysis: false,
                 };
-                context.with_spans(|spans| {
-                    assert_eq!(spans.last(), Some(&span1_expected));
-                });
+                assert_eq!(context.last_span(), Some(span1_expected));
             }
 
             tracer
@@ -209,7 +203,8 @@
     MockReporter::with(
         |reporter| {
             let tracer = Tracer::new("service2", "instance2", reporter);
-            let _context = tracer.create_trace_context_from_propagation(prop);
+            let mut context = tracer.create_trace_context();
+            let _span = context.create_entry_span_with_propagation("operation_name", &prop);
             tracer
         },
         |segment| {
@@ -239,30 +234,29 @@
             let dec_prop = decode_propagation(&enc_prop).unwrap();
 
             let tracer = Tracer::new("service2", "instance2", LogReporter::new());
-            let mut context2 = tracer.create_trace_context_from_propagation(dec_prop);
+            let mut context2 = tracer.create_trace_context();
 
-            let span3 = context2.create_entry_span("op2");
+            let span3 = context2.create_entry_span_with_propagation("op2", &dec_prop);
             drop(span3);
 
-            context2.with_spans(|spans| {
-                let span3 = spans.last().unwrap();
-                assert_eq!(span3.span_id, 0);
-                assert_eq!(span3.parent_span_id, -1);
-                assert_eq!(span3.refs.len(), 1);
+            let span3 = context2.last_span().unwrap();
 
-                let expected_ref = SegmentReference {
-                    ref_type: RefType::CrossProcess as i32,
-                    trace_id: context2.trace_id().to_owned(),
-                    parent_trace_segment_id: context1.trace_segment_id().to_owned(),
-                    parent_span_id: 1,
-                    parent_service: context1.service().to_owned(),
-                    parent_service_instance: context1.service_instance().to_owned(),
-                    parent_endpoint: "endpoint".to_string(),
-                    network_address_used_at_peer: "address".to_string(),
-                };
+            assert_eq!(span3.span_id, 0);
+            assert_eq!(span3.parent_span_id, -1);
+            assert_eq!(span3.refs.len(), 1);
 
-                check_serialize_equivalent(&expected_ref, &span3.refs[0]);
-            });
+            let expected_ref = SegmentReference {
+                ref_type: RefType::CrossProcess as i32,
+                trace_id: context2.trace_id().to_owned(),
+                parent_trace_segment_id: context1.trace_segment_id().to_owned(),
+                parent_span_id: 1,
+                parent_service: context1.service().to_owned(),
+                parent_service_instance: context1.service_instance().to_owned(),
+                parent_endpoint: "endpoint".to_string(),
+                network_address_used_at_peer: "address".to_string(),
+            };
+
+            check_serialize_equivalent(&expected_ref, &span3.refs[0]);
         }
     }
 }