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
2 changes: 1 addition & 1 deletion opentelemetry-otlp/src/exporter/http/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
};

impl SpanExporter for OtlpHttpClient {
async fn export(&mut self, batch: Vec<SpanData>) -> OTelSdkResult {
async fn export(&self, batch: Vec<SpanData>) -> OTelSdkResult {

Check warning on line 12 in opentelemetry-otlp/src/exporter/http/trace.rs

View check run for this annotation

Codecov / codecov/patch

opentelemetry-otlp/src/exporter/http/trace.rs#L12

Added line #L12 was not covered by tests
let client = match self
.client
.lock()
Expand Down
24 changes: 13 additions & 11 deletions opentelemetry-otlp/src/exporter/tonic/trace.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use core::fmt;
use tokio::sync::Mutex;

use opentelemetry::otel_debug;
use opentelemetry_proto::tonic::collector::trace::v1::{
Expand All @@ -23,7 +24,7 @@

struct ClientInner {
client: TraceServiceClient<Channel>,
interceptor: BoxInterceptor,
interceptor: Mutex<BoxInterceptor>,
}

impl fmt::Debug for TonicTracesClient {
Expand All @@ -50,26 +51,27 @@
TonicTracesClient {
inner: Some(ClientInner {
client,
interceptor,
interceptor: Mutex::new(interceptor),

Check warning on line 54 in opentelemetry-otlp/src/exporter/tonic/trace.rs

View check run for this annotation

Codecov / codecov/patch

opentelemetry-otlp/src/exporter/tonic/trace.rs#L54

Added line #L54 was not covered by tests
}),
resource: Default::default(),
}
}
}

impl SpanExporter for TonicTracesClient {
async fn export(&mut self, batch: Vec<SpanData>) -> OTelSdkResult {
let (mut client, metadata, extensions) = match &mut self.inner {
async fn export(&self, batch: Vec<SpanData>) -> OTelSdkResult {
let (mut client, metadata, extensions) = match &self.inner {

Check warning on line 63 in opentelemetry-otlp/src/exporter/tonic/trace.rs

View check run for this annotation

Codecov / codecov/patch

opentelemetry-otlp/src/exporter/tonic/trace.rs#L62-L63

Added lines #L62 - L63 were not covered by tests
Some(inner) => {
let (m, e, _) = match inner.interceptor.call(Request::new(())) {
Ok(res) => res.into_parts(),
Err(e) => return Err(OTelSdkError::InternalFailure(e.to_string())),
};
let (m, e, _) = inner
.interceptor
.lock()
.await // tokio::sync::Mutex doesn't return a poisoned error, so we can safely use the interceptor here
.call(Request::new(()))
.map_err(|e| OTelSdkError::InternalFailure(format!("error: {:?}", e)))?
.into_parts();

Check warning on line 71 in opentelemetry-otlp/src/exporter/tonic/trace.rs

View check run for this annotation

Codecov / codecov/patch

opentelemetry-otlp/src/exporter/tonic/trace.rs#L65-L71

Added lines #L65 - L71 were not covered by tests
(inner.client.clone(), m, e)
}
None => {
return Err(OTelSdkError::AlreadyShutdown);
}
None => return Err(OTelSdkError::AlreadyShutdown),

Check warning on line 74 in opentelemetry-otlp/src/exporter/tonic/trace.rs

View check run for this annotation

Codecov / codecov/patch

opentelemetry-otlp/src/exporter/tonic/trace.rs#L74

Added line #L74 was not covered by tests
};

let resource_spans = group_spans_by_resource_and_scope(batch, &self.resource);
Expand Down
4 changes: 2 additions & 2 deletions opentelemetry-otlp/src/span.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,8 @@
}

impl opentelemetry_sdk::trace::SpanExporter for SpanExporter {
async fn export(&mut self, batch: Vec<SpanData>) -> OTelSdkResult {
match &mut self.client {
async fn export(&self, batch: Vec<SpanData>) -> OTelSdkResult {
match &self.client {

Check warning on line 145 in opentelemetry-otlp/src/span.rs

View check run for this annotation

Codecov / codecov/patch

opentelemetry-otlp/src/span.rs#L144-L145

Added lines #L144 - L145 were not covered by tests
#[cfg(feature = "grpc-tonic")]
SupportedTransportClient::Tonic(client) => client.export(batch).await,
#[cfg(any(feature = "http-proto", feature = "http-json"))]
Expand Down
12 changes: 11 additions & 1 deletion opentelemetry-sdk/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,17 @@
}
}
```

- **Breaking** The SpanExporter::export() method no longer requires a mutable reference to self.
Before:
```rust
async fn export(&mut self, batch: Vec<SpanData>) -> OTelSdkResult
```
After:
```rust
async fn export(&self, batch: Vec<SpanData>) -> OTelSdkResult
```
Custom exporters will need to internally synchronize any mutable state, if applicable.

## 0.28.0

Released 2025-Feb-10
Expand Down
2 changes: 1 addition & 1 deletion opentelemetry-sdk/benches/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ fn parent_sampled_tracer(inner_sampler: Sampler) -> (SdkTracerProvider, BoxedTra
struct NoopExporter;

impl SpanExporter for NoopExporter {
async fn export(&mut self, _spans: Vec<SpanData>) -> OTelSdkResult {
async fn export(&self, _spans: Vec<SpanData>) -> OTelSdkResult {
Ok(())
}
}
Expand Down
2 changes: 1 addition & 1 deletion opentelemetry-sdk/benches/span_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ fn not_sampled_provider() -> (sdktrace::SdkTracerProvider, sdktrace::SdkTracer)
struct NoopExporter;

impl SpanExporter for NoopExporter {
async fn export(&mut self, _spans: Vec<SpanData>) -> OTelSdkResult {
async fn export(&self, _spans: Vec<SpanData>) -> OTelSdkResult {
Ok(())
}
}
Expand Down
2 changes: 1 addition & 1 deletion opentelemetry-sdk/benches/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ fn criterion_benchmark(c: &mut Criterion) {
struct VoidExporter;

impl SpanExporter for VoidExporter {
async fn export(&mut self, _spans: Vec<SpanData>) -> OTelSdkResult {
async fn export(&self, _spans: Vec<SpanData>) -> OTelSdkResult {
Ok(())
}
}
Expand Down
4 changes: 2 additions & 2 deletions opentelemetry-sdk/src/testing/trace/span_exporters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ pub struct TokioSpanExporter {
}

impl SpanExporter for TokioSpanExporter {
async fn export(&mut self, batch: Vec<SpanData>) -> OTelSdkResult {
async fn export(&self, batch: Vec<SpanData>) -> OTelSdkResult {
batch.into_iter().try_for_each(|span_data| {
self.tx_export
.send(span_data)
Expand Down Expand Up @@ -110,7 +110,7 @@ impl NoopSpanExporter {
}

impl SpanExporter for NoopSpanExporter {
async fn export(&mut self, _: Vec<SpanData>) -> OTelSdkResult {
async fn export(&self, _: Vec<SpanData>) -> OTelSdkResult {
Ok(())
}
}
2 changes: 1 addition & 1 deletion opentelemetry-sdk/src/trace/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub trait SpanExporter: Send + Sync + Debug {
/// Any retry logic that is required by the exporter is the responsibility
/// of the exporter.
fn export(
&mut self,
&self,
batch: Vec<SpanData>,
) -> impl std::future::Future<Output = OTelSdkResult> + Send;

Expand Down
2 changes: 1 addition & 1 deletion opentelemetry-sdk/src/trace/in_memory_exporter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ impl InMemorySpanExporter {
}

impl SpanExporter for InMemorySpanExporter {
async fn export(&mut self, batch: Vec<SpanData>) -> OTelSdkResult {
async fn export(&self, batch: Vec<SpanData>) -> OTelSdkResult {
let result = self
.spans
.lock()
Expand Down
2 changes: 1 addition & 1 deletion opentelemetry-sdk/src/trace/runtime_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

#[cfg(any(feature = "rt-tokio", feature = "rt-tokio-current-thread"))]
impl SpanExporter for SpanCountExporter {
async fn export(&mut self, batch: Vec<crate::trace::SpanData>) -> OTelSdkResult {
async fn export(&self, batch: Vec<crate::trace::SpanData>) -> OTelSdkResult {

Check warning on line 28 in opentelemetry-sdk/src/trace/runtime_tests.rs

View check run for this annotation

Codecov / codecov/patch

opentelemetry-sdk/src/trace/runtime_tests.rs#L28

Added line #L28 was not covered by tests
self.span_count.fetch_add(batch.len(), Ordering::SeqCst);
Ok(())
}
Expand Down
4 changes: 2 additions & 2 deletions opentelemetry-sdk/src/trace/span_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ impl<T: SpanExporter> SpanProcessor for SimpleSpanProcessor<T> {
.exporter
.lock()
.map_err(|_| OTelSdkError::InternalFailure("SimpleSpanProcessor mutex poison".into()))
.and_then(|mut exporter| futures_executor::block_on(exporter.export(vec![span])));
.and_then(|exporter| futures_executor::block_on(exporter.export(vec![span])));

if let Err(err) = result {
// TODO: check error type, and log `error` only if the error is user-actionable, else log `debug`
Expand Down Expand Up @@ -1022,7 +1022,7 @@ mod tests {
}

impl SpanExporter for MockSpanExporter {
async fn export(&mut self, batch: Vec<SpanData>) -> OTelSdkResult {
async fn export(&self, batch: Vec<SpanData>) -> OTelSdkResult {
let exported_spans = self.exported_spans.clone();
exported_spans.lock().unwrap().extend(batch);
Ok(())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ mod tests {
D: Fn(Duration) -> DS + 'static + Send + Sync,
DS: Future<Output = ()> + Send + Sync + 'static,
{
async fn export(&mut self, _batch: Vec<SpanData>) -> OTelSdkResult {
async fn export(&self, _batch: Vec<SpanData>) -> OTelSdkResult {
(self.delay_fn)(self.delay_for).await;
Ok(())
}
Expand Down
23 changes: 13 additions & 10 deletions opentelemetry-stdout/src/trace/exporter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
use core::fmt;
use opentelemetry_sdk::error::{OTelSdkError, OTelSdkResult};
use opentelemetry_sdk::trace::SpanData;
use std::sync::atomic;
use std::sync::atomic::{AtomicBool, Ordering};

use opentelemetry_sdk::resource::Resource;

/// An OpenTelemetry exporter that writes Spans to stdout on export.
pub struct SpanExporter {
resource: Resource,
is_shutdown: atomic::AtomicBool,
resource_emitted: bool,
is_shutdown: AtomicBool,
resource_emitted: AtomicBool,
}

impl fmt::Debug for SpanExporter {
Expand All @@ -23,23 +23,26 @@
fn default() -> Self {
SpanExporter {
resource: Resource::builder().build(),
is_shutdown: atomic::AtomicBool::new(false),
resource_emitted: false,
is_shutdown: AtomicBool::new(false),
resource_emitted: AtomicBool::new(false),

Check warning on line 27 in opentelemetry-stdout/src/trace/exporter.rs

View check run for this annotation

Codecov / codecov/patch

opentelemetry-stdout/src/trace/exporter.rs#L26-L27

Added lines #L26 - L27 were not covered by tests
}
}
}

impl opentelemetry_sdk::trace::SpanExporter for SpanExporter {
/// Write Spans to stdout
async fn export(&mut self, batch: Vec<SpanData>) -> OTelSdkResult {
if self.is_shutdown.load(atomic::Ordering::SeqCst) {
async fn export(&self, batch: Vec<SpanData>) -> OTelSdkResult {
if self.is_shutdown.load(Ordering::SeqCst) {

Check warning on line 35 in opentelemetry-stdout/src/trace/exporter.rs

View check run for this annotation

Codecov / codecov/patch

opentelemetry-stdout/src/trace/exporter.rs#L34-L35

Added lines #L34 - L35 were not covered by tests
Err(OTelSdkError::AlreadyShutdown)
} else {
println!("Spans");
if self.resource_emitted {
if self
.resource_emitted
.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst)
.is_err()
{

Check warning on line 43 in opentelemetry-stdout/src/trace/exporter.rs

View check run for this annotation

Codecov / codecov/patch

opentelemetry-stdout/src/trace/exporter.rs#L39-L43

Added lines #L39 - L43 were not covered by tests
print_spans(batch);
} else {
self.resource_emitted = true;
println!("Resource");
if let Some(schema_url) = self.resource.schema_url() {
println!("\tResource SchemaUrl: {:?}", schema_url);
Expand All @@ -57,7 +60,7 @@
}

fn shutdown(&mut self) -> OTelSdkResult {
self.is_shutdown.store(true, atomic::Ordering::SeqCst);
self.is_shutdown.store(true, Ordering::SeqCst);

Check warning on line 63 in opentelemetry-stdout/src/trace/exporter.rs

View check run for this annotation

Codecov / codecov/patch

opentelemetry-stdout/src/trace/exporter.rs#L63

Added line #L63 was not covered by tests
Ok(())
}

Expand Down
2 changes: 1 addition & 1 deletion opentelemetry-zipkin/src/exporter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@

impl trace::SpanExporter for ZipkinExporter {
/// Export spans to Zipkin collector.
async fn export(&mut self, batch: Vec<trace::SpanData>) -> OTelSdkResult {
async fn export(&self, batch: Vec<trace::SpanData>) -> OTelSdkResult {

Check warning on line 129 in opentelemetry-zipkin/src/exporter/mod.rs

View check run for this annotation

Codecov / codecov/patch

opentelemetry-zipkin/src/exporter/mod.rs#L129

Added line #L129 was not covered by tests
zipkin_export(batch, self.uploader.clone(), self.local_endpoint.clone()).await
}
}
Expand Down