Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions opentelemetry-sdk/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- **Breaking** The SDK `testing` feature is now runtime agnostic. [#3407][3407]
- `TokioSpanExporter` and `new_tokio_test_exporter` have been renamed to `TestSpanExporter` and `new_test_exporter`.
- The following transitive dependencies and features have been removed: `tokio/rt`, `tokio/time`, `tokio/macros`, `tokio/rt-multi-thread`, `tokio-stream`, `experimental_async_runtime`
- Store `InstrumentationScope` in `Arc` internally in `SdkTracer`, making tracer clones cheaper (Arc refcount increment instead of deep copy).
- Add 32-bit platform support by using `portable-atomic` for `AtomicI64` and `AtomicU64` in the metrics module. This enables compilation on 32-bit ARM targets (e.g., `armv5te-unknown-linux-gnueabi`, `armv7-unknown-linux-gnueabihf`).
- `Aggregation` enum and `StreamBuilder::with_aggregation()` are now stable and no longer require the `spec_unstable_metrics_views` feature flag.
- Fix `service.name` Resource attribute fallback to follow OpenTelemetry
Expand Down
36 changes: 36 additions & 0 deletions opentelemetry-sdk/src/trace/span.rs
Original file line number Diff line number Diff line change
Expand Up @@ -709,6 +709,42 @@ mod tests {
assert_eq!(event_vec.len(), DEFAULT_MAX_EVENT_PER_SPAN as usize);
}

#[test]
fn multiple_processors_receive_span_data() {
use crate::trace::InMemorySpanExporterBuilder;

let exporter1 = InMemorySpanExporterBuilder::new().build();
let exporter2 = InMemorySpanExporterBuilder::new().build();

let provider = crate::trace::SdkTracerProvider::builder()
.with_simple_exporter(exporter1.clone())
.with_simple_exporter(exporter2.clone())
.build();

let tracer = provider.tracer("test");
let mut span = tracer.start("multi_processor_span");
span.set_attribute(KeyValue::new("key", "value"));
span.end();

let spans1 = exporter1.get_finished_spans().unwrap();
let spans2 = exporter2.get_finished_spans().unwrap();

assert_eq!(spans1.len(), 1);
assert_eq!(spans2.len(), 1);
assert_eq!(spans1[0].name, "multi_processor_span");
assert_eq!(spans2[0].name, "multi_processor_span");
assert_eq!(spans1[0].attributes, spans2[0].attributes);
// Verify instrumentation scope is correctly propagated to both processors
assert_eq!(spans1[0].instrumentation_scope.name(), "test");
assert_eq!(spans2[0].instrumentation_scope.name(), "test");
assert_eq!(
spans1[0].instrumentation_scope,
spans2[0].instrumentation_scope
);

let _ = provider.shutdown();
}

#[test]
fn test_span_exported_data() {
let provider = crate::trace::SdkTracerProvider::builder()
Expand Down
8 changes: 6 additions & 2 deletions opentelemetry-sdk/src/trace/tracer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@ use opentelemetry::{
Context, InstrumentationScope, KeyValue,
};
use std::fmt;
use std::sync::Arc;

/// `Tracer` implementation to create and manage spans
#[derive(Clone)]
pub struct SdkTracer {
scope: InstrumentationScope,
scope: Arc<InstrumentationScope>,
provider: SdkTracerProvider,
}

Expand All @@ -39,7 +40,10 @@ impl fmt::Debug for SdkTracer {
impl SdkTracer {
/// Create a new tracer (used internally by `TracerProvider`s).
pub(crate) fn new(scope: InstrumentationScope, provider: SdkTracerProvider) -> Self {
SdkTracer { scope, provider }
SdkTracer {
scope: Arc::new(scope),
provider,
}
}

/// TracerProvider associated with this tracer.
Expand Down
Loading