From d2de9f65d1c5590653955f275d806bb5e6d7eba5 Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Thu, 18 Jul 2024 11:47:30 +0200 Subject: [PATCH 1/4] ci: remove stray working-directory setting --- .github/workflows/CI.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 6a8a81a..edc0c5d 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -103,7 +103,6 @@ jobs: - name: install cargo-minimal-versions uses: taiki-e/install-action@cargo-minimal-versions - name: cargo minimal-versions check - working-directory: ${{ matrix.subcrate }} run: cargo minimal-versions check --feature-powerset --no-dev-deps ### test jobs ############################################################# From ceb5817c0ec7f6c34dcb9a5af9b3314a0ff753bc Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Thu, 18 Jul 2024 11:53:58 +0200 Subject: [PATCH 2/4] We now need a recent version of lazy_static --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.toml b/Cargo.toml index b369c3e..07fe466 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,7 @@ once_cell = "1.13.0" # Fix minimal-versions async-trait = { version = "0.1.56", optional = true } futures-util = { version = "0.3.17", optional = true } +lazy_static = { version = "1.0.2", optional = true } thiserror = { version = "1.0.31", optional = true } smallvec = { version = "1.0", optional = true } From 3da74a87adc3fc490c26a2267dbdafcc8e5083bc Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Thu, 18 Jul 2024 11:34:31 +0200 Subject: [PATCH 3/4] Remove deprecated APIs --- src/layer.rs | 78 ---------------------------------------------------- 1 file changed, 78 deletions(-) diff --git a/src/layer.rs b/src/layer.rs index f38b4bc..4b2269c 100644 --- a/src/layer.rs +++ b/src/layer.rs @@ -591,35 +591,6 @@ where } } - /// Sets whether or not span and event metadata should include OpenTelemetry - /// exception fields such as `exception.message` and `exception.backtrace` - /// when an `Error` value is recorded. If multiple error values are recorded - /// on the same span/event, only the most recently recorded error value will - /// show up under these fields. - /// - /// These attributes follow the [OpenTelemetry semantic conventions for - /// exceptions][conv]. - /// - /// By default, these attributes are recorded. - /// Note that this only works for `(dyn Error + 'static)`. - /// See [Implementations on Foreign Types of tracing::Value][impls] or [`OpenTelemetryLayer::with_error_events_to_exceptions`] - /// - /// [conv]: https://github.com/open-telemetry/semantic-conventions/tree/main/docs/exceptions/ - /// [impls]: https://docs.rs/tracing/0.1.37/tracing/trait.Value.html#foreign-impls - #[deprecated( - since = "0.21.0", - note = "renamed to `OpenTelemetryLayer::with_error_fields_to_exceptions`" - )] - pub fn with_exception_fields(self, exception_fields: bool) -> Self { - Self { - sem_conv_config: SemConvConfig { - error_fields_to_exceptions: exception_fields, - ..self.sem_conv_config - }, - ..self - } - } - /// Sets whether or not span and event metadata should include OpenTelemetry /// exception fields such as `exception.message` and `exception.backtrace` /// when an `Error` value is recorded. If multiple error values are recorded @@ -680,35 +651,6 @@ where } } - /// Sets whether or not reporting an `Error` value on an event will - /// propagate the OpenTelemetry exception fields such as `exception.message` - /// and `exception.backtrace` to the corresponding span. You do not need to - /// enable `with_exception_fields` in order to enable this. If multiple - /// error values are recorded on the same span/event, only the most recently - /// recorded error value will show up under these fields. - /// - /// These attributes follow the [OpenTelemetry semantic conventions for - /// exceptions][conv]. - /// - /// By default, these attributes are propagated to the span. Note that this only works for `(dyn Error + 'static)`. - /// See [Implementations on Foreign Types of tracing::Value][impls] or [`OpenTelemetryLayer::with_error_events_to_exceptions`] - /// - /// [conv]: https://github.com/open-telemetry/semantic-conventions/tree/main/docs/exceptions/ - /// [impls]: https://docs.rs/tracing/0.1.37/tracing/trait.Value.html#foreign-impls - #[deprecated( - since = "0.21.0", - note = "renamed to `OpenTelemetryLayer::with_error_records_to_exceptions`" - )] - pub fn with_exception_field_propagation(self, exception_field_propagation: bool) -> Self { - Self { - sem_conv_config: SemConvConfig { - error_records_to_exceptions: exception_field_propagation, - ..self.sem_conv_config - }, - ..self - } - } - /// Sets whether or not reporting an `Error` value on an event will /// propagate the OpenTelemetry exception fields such as `exception.message` /// and `exception.backtrace` to the corresponding span. You do not need to @@ -747,26 +689,6 @@ where Self { location, ..self } } - /// Sets whether or not span and event metadata should include OpenTelemetry - /// attributes with location information, such as the file, module and line number. - /// - /// These attributes follow the [OpenTelemetry semantic conventions for - /// source locations][conv]. - /// - /// By default, locations are enabled. - /// - /// [conv]: https://github.com/open-telemetry/semantic-conventions/blob/main/docs/general/attributes.md#source-code-attributes/ - #[deprecated( - since = "0.17.3", - note = "renamed to `OpenTelemetrySubscriber::with_location`" - )] - pub fn with_event_location(self, event_location: bool) -> Self { - Self { - location: event_location, - ..self - } - } - /// Sets whether or not spans metadata should include the _busy time_ /// (total time for which it was entered), and _idle time_ (total time /// the span existed but was not entered). From 6fb2ba4c8b5b5b00e2566256c3ce80d7ebbe59ec Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Mon, 15 Jul 2024 23:16:54 +0200 Subject: [PATCH 4/4] Upgrade to tracing-opentelemetry 0.24 --- Cargo.toml | 17 ++++++++--------- benches/trace.rs | 15 +++++---------- examples/opentelemetry-error.rs | 4 ++-- examples/opentelemetry-otlp.rs | 12 ++++++++---- src/layer.rs | 26 ++++++++++++++++++-------- src/tracer.rs | 27 ++++++++++----------------- tests/metrics_publishing.rs | 17 +++++++++++------ tests/parallel.rs | 16 ++++++++-------- 8 files changed, 70 insertions(+), 64 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 07fe466..eefcd49 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tracing-opentelemetry" -version = "0.24.0" +version = "0.25.0" description = "OpenTelemetry integration for tracing" homepage = "https://github.com/tokio-rs/tracing-opentelemetry" repository = "https://github.com/tokio-rs/tracing-opentelemetry" @@ -23,8 +23,8 @@ metrics = ["opentelemetry/metrics","opentelemetry_sdk/metrics", "smallvec"] metrics_gauge_unstable = ["opentelemetry/otel_unstable"] [dependencies] -opentelemetry = { version = "0.23.0", default-features = false, features = ["trace"] } -opentelemetry_sdk = { version = "0.23.0", default-features = false, features = ["trace"] } +opentelemetry = { version = "0.24", default-features = false, features = ["trace"] } +opentelemetry_sdk = { version = "0.24.1", default-features = false, features = ["trace"] } tracing = { version = "0.1.35", default-features = false, features = ["std"] } tracing-core = "0.1.28" tracing-subscriber = { version = "0.3.0", default-features = false, features = ["registry", "std"] } @@ -41,12 +41,11 @@ smallvec = { version = "1.0", optional = true } [dev-dependencies] async-trait = "0.1.56" criterion = { version = "0.5.1", default-features = false, features = ["html_reports"] } -opentelemetry = { version = "0.23.0", features = ["trace", "metrics"] } -opentelemetry_sdk = { version = "0.23.0", default-features = false, features = ["trace", "rt-tokio"] } -opentelemetry-jaeger = "0.22.0" -opentelemetry-stdout = { version = "0.4.0", features = ["trace", "metrics"] } -opentelemetry-otlp = { version = "0.16.0", features = ["metrics"] } -opentelemetry-semantic-conventions = "0.15.0" +opentelemetry = { version = "0.24", features = ["trace", "metrics"] } +opentelemetry_sdk = { version = "0.24", default-features = false, features = ["trace", "rt-tokio"] } +opentelemetry-stdout = { version = "0.5", features = ["trace", "metrics"] } +opentelemetry-otlp = { version = "0.17", features = ["metrics"] } +opentelemetry-semantic-conventions = "0.16" futures-util = { version = "0.3.17", default-features = false } tokio = { version = "1", features = ["full"] } tokio-stream = "0.1" diff --git a/benches/trace.rs b/benches/trace.rs index 827bcc5..b9c2aca 100644 --- a/benches/trace.rs +++ b/benches/trace.rs @@ -3,7 +3,7 @@ use opentelemetry::{ trace::{Span, SpanBuilder, Tracer as _, TracerProvider as _}, Context, }; -use opentelemetry_sdk::trace::{Config, SpanLimits, Tracer, TracerProvider}; +use opentelemetry_sdk::trace::{Config, Tracer, TracerProvider}; #[cfg(not(target_os = "windows"))] use pprof::criterion::{Output, PProfProfiler}; use std::time::SystemTime; @@ -160,15 +160,10 @@ fn many_events(c: &mut Criterion) { } { - let provider = TracerProvider::builder() - .with_config(Config { - span_limits: SpanLimits { - max_events_per_span: 1000, - ..SpanLimits::default() - }, - ..Config::default() - }) - .build(); + let mut config = Config::default(); + config.span_limits.max_events_per_span = 1000; + + let provider = TracerProvider::builder().with_config(config).build(); let tracer = provider.tracer("bench"); let otel_layer = tracing_opentelemetry::layer() .with_tracer(tracer) diff --git a/examples/opentelemetry-error.rs b/examples/opentelemetry-error.rs index 35276af..bcc3b5b 100644 --- a/examples/opentelemetry-error.rs +++ b/examples/opentelemetry-error.rs @@ -141,8 +141,8 @@ impl Display for SpanData { .as_secs() )?; writeln!(f, "- Resource:")?; - for (k, v) in self.0.resource.iter() { - writeln!(f, " - {}: {}", k, v)?; + for kv in self.0.attributes.iter() { + writeln!(f, " - {}: {}", kv.key, kv.value)?; } writeln!(f, "- Attributes:")?; for kv in self.0.attributes.iter() { diff --git a/examples/opentelemetry-otlp.rs b/examples/opentelemetry-otlp.rs index 1355570..35907ac 100644 --- a/examples/opentelemetry-otlp.rs +++ b/examples/opentelemetry-otlp.rs @@ -1,4 +1,4 @@ -use opentelemetry::{global, Key, KeyValue}; +use opentelemetry::{global, trace::TracerProvider, Key, KeyValue}; use opentelemetry_sdk::{ metrics::{ reader::{DefaultAggregationSelector, DefaultTemporalitySelector}, @@ -93,7 +93,7 @@ fn init_meter_provider() -> SdkMeterProvider { // Construct Tracer for OpenTelemetryLayer fn init_tracer() -> Tracer { - opentelemetry_otlp::new_pipeline() + let provider = opentelemetry_otlp::new_pipeline() .tracing() .with_trace_config( opentelemetry_sdk::trace::Config::default() @@ -108,12 +108,16 @@ fn init_tracer() -> Tracer { .with_batch_config(BatchConfig::default()) .with_exporter(opentelemetry_otlp::new_exporter().tonic()) .install_batch(runtime::Tokio) - .unwrap() + .unwrap(); + + global::set_tracer_provider(provider.clone()); + provider.tracer("tracing-otel-subscriber") } // Initialize tracing-subscriber and return OtelGuard for opentelemetry-related termination processing fn init_tracing_subscriber() -> OtelGuard { let meter_provider = init_meter_provider(); + let tracer = init_tracer(); tracing_subscriber::registry() .with(tracing_subscriber::filter::LevelFilter::from_level( @@ -121,7 +125,7 @@ fn init_tracing_subscriber() -> OtelGuard { )) .with(tracing_subscriber::fmt::layer()) .with(MetricsLayer::new(meter_provider.clone())) - .with(OpenTelemetryLayer::new(init_tracer())) + .with(OpenTelemetryLayer::new(tracer)) .init(); OtelGuard { meter_provider } diff --git a/src/layer.rs b/src/layer.rs index 4b2269c..fde9be5 100644 --- a/src/layer.rs +++ b/src/layer.rs @@ -516,13 +516,18 @@ where /// ```no_run /// use tracing_opentelemetry::OpenTelemetryLayer; /// use tracing_subscriber::layer::SubscriberExt; + /// use opentelemetry::trace::TracerProvider; /// use tracing_subscriber::Registry; /// - /// // Create a jaeger exporter pipeline for a `trace_demo` service. - /// let tracer = opentelemetry_jaeger::new_agent_pipeline() - /// .with_service_name("trace_demo") + /// // Create an OTLP pipeline exporter for a `trace_demo` service. + /// + /// let otlp_exporter = opentelemetry_otlp::new_exporter().tonic(); + /// let tracer = opentelemetry_otlp::new_pipeline() + /// .tracing() + /// .with_exporter(otlp_exporter) /// .install_simple() - /// .expect("Error initializing Jaeger exporter"); + /// .unwrap() + /// .tracer("trace_demo"); /// /// // Create a layer with the configured tracer /// let otel_layer = OpenTelemetryLayer::new(tracer); @@ -561,12 +566,17 @@ where /// ```no_run /// use tracing_subscriber::layer::SubscriberExt; /// use tracing_subscriber::Registry; + /// use opentelemetry::trace::TracerProvider; + /// + /// // Create an OTLP pipeline exporter for a `trace_demo` service. /// - /// // Create a jaeger exporter pipeline for a `trace_demo` service. - /// let tracer = opentelemetry_jaeger::new_agent_pipeline() - /// .with_service_name("trace_demo") + /// let otlp_exporter = opentelemetry_otlp::new_exporter().tonic(); + /// let tracer = opentelemetry_otlp::new_pipeline() + /// .tracing() + /// .with_exporter(otlp_exporter) /// .install_simple() - /// .expect("Error initializing Jaeger exporter"); + /// .unwrap() + /// .tracer("trace_demo"); /// /// // Create a layer with the configured tracer /// let otel_layer = tracing_opentelemetry::layer().with_tracer(tracer); diff --git a/src/tracer.rs b/src/tracer.rs index 5b1651d..7ea6074 100644 --- a/src/tracer.rs +++ b/src/tracer.rs @@ -6,7 +6,7 @@ use opentelemetry::{ }, Context as OtelContext, }; -use opentelemetry_sdk::trace::{Tracer as SdkTracer, TracerProvider as SdkTracerProvider}; +use opentelemetry_sdk::trace::{IdGenerator, Tracer as SdkTracer}; /// An interface for authors of OpenTelemetry SDKs to build pre-sampled tracers. /// @@ -65,21 +65,18 @@ impl PreSampledTracer for noop::NoopTracer { impl PreSampledTracer for SdkTracer { fn sampled_context(&self, data: &mut crate::OtelData) -> OtelContext { - // Ensure tracing pipeline is still installed. - let Some(provider) = self.provider() else { - return OtelContext::new(); - }; let parent_cx = &data.parent_cx; let builder = &mut data.builder; // Gather trace state - let (trace_id, parent_trace_flags) = current_trace_state(builder, parent_cx, &provider); + let (trace_id, parent_trace_flags) = + current_trace_state(builder, parent_cx, self.id_generator()); // Sample or defer to existing sampling decisions let (flags, trace_state) = if let Some(result) = &builder.sampling_result { process_sampling_result(result, parent_trace_flags) } else { - builder.sampling_result = Some(provider.config().sampler.should_sample( + builder.sampling_result = Some(self.should_sample().should_sample( Some(parent_cx), trace_id, &builder.name, @@ -101,22 +98,18 @@ impl PreSampledTracer for SdkTracer { } fn new_trace_id(&self) -> otel::TraceId { - self.provider() - .map(|provider| provider.config().id_generator.new_trace_id()) - .unwrap_or(otel::TraceId::INVALID) + self.id_generator().new_trace_id() } fn new_span_id(&self) -> otel::SpanId { - self.provider() - .map(|provider| provider.config().id_generator.new_span_id()) - .unwrap_or(otel::SpanId::INVALID) + self.id_generator().new_span_id() } } fn current_trace_state( builder: &SpanBuilder, parent_cx: &OtelContext, - provider: &SdkTracerProvider, + id_generator: &dyn IdGenerator, ) -> (TraceId, TraceFlags) { if parent_cx.has_active_span() { let span = parent_cx.span(); @@ -126,7 +119,7 @@ fn current_trace_state( ( builder .trace_id - .unwrap_or_else(|| provider.config().id_generator.new_trace_id()), + .unwrap_or_else(|| id_generator.new_trace_id()), Default::default(), ) } @@ -159,7 +152,7 @@ mod tests { use super::*; use crate::OtelData; use opentelemetry::trace::TracerProvider as _; - use opentelemetry_sdk::trace::{config, Sampler, TracerProvider}; + use opentelemetry_sdk::trace::{Config, Sampler, TracerProvider}; #[test] fn assigns_default_trace_id_if_missing() { @@ -203,7 +196,7 @@ mod tests { fn sampled_context() { for (name, sampler, parent_cx, previous_sampling_result, is_sampled) in sampler_data() { let provider = TracerProvider::builder() - .with_config(config().with_sampler(sampler)) + .with_config(Config::default().with_sampler(sampler)) .build(); let tracer = provider.tracer("test"); let mut builder = SpanBuilder::from_name("parent".to_string()); diff --git a/tests/metrics_publishing.rs b/tests/metrics_publishing.rs index 5968c6c..597d10a 100644 --- a/tests/metrics_publishing.rs +++ b/tests/metrics_publishing.rs @@ -6,9 +6,9 @@ use opentelemetry_sdk::{ AggregationSelector, DefaultAggregationSelector, DefaultTemporalitySelector, MetricReader, TemporalitySelector, }, - InstrumentKind, ManualReader, MeterProviderBuilder, SdkMeterProvider, + AttributeSet, InstrumentKind, ManualReader, MeterProviderBuilder, SdkMeterProvider, }, - AttributeSet, Resource, + Resource, }; use std::{fmt::Debug, sync::Arc}; @@ -563,7 +563,12 @@ fn init_subscriber( expected_metric_name, expected_instrument_kind, expected_value, - expected_attributes, + expected_attributes: expected_attributes.map(|attrs| { + attrs + .iter() + .map(|(k, v)| KeyValue::new(k.clone(), v.clone())) + .collect() + }), reader, _meter_provider: provider.clone(), }; @@ -613,7 +618,7 @@ struct TestExporter { expected_metric_name: String, expected_instrument_kind: InstrumentKind, expected_value: T, - expected_attributes: Option, + expected_attributes: Option>, reader: TestReader, _meter_provider: SdkMeterProvider, } @@ -654,7 +659,7 @@ where if let Some(expected_attributes) = self.expected_attributes.as_ref() { sum.data_points.iter().for_each(|data_point| { - assert_eq!(expected_attributes, &data_point.attributes,) + assert_eq!(expected_attributes, &data_point.attributes) }); } } @@ -672,7 +677,7 @@ where if let Some(expected_attributes) = self.expected_attributes.as_ref() { gauge.data_points.iter().for_each(|data_point| { - assert_eq!(expected_attributes, &data_point.attributes,) + assert_eq!(expected_attributes, &data_point.attributes) }); } } diff --git a/tests/parallel.rs b/tests/parallel.rs index 6c9294b..60d84c5 100644 --- a/tests/parallel.rs +++ b/tests/parallel.rs @@ -32,18 +32,18 @@ fn test_tracer() -> ( impl Subscriber + Clone, ) { let exporter = TestExporter::default(); + let mut config = Config::default(); + config.span_limits = SpanLimits { + max_events_per_span: u32::MAX, + ..SpanLimits::default() + }; + let provider = TracerProvider::builder() .with_simple_exporter(exporter.clone()) - .with_config(Config { - span_limits: SpanLimits { - max_events_per_span: u32::MAX, - ..SpanLimits::default() - }, - ..Config::default() - }) + .with_config(config) .build(); - let tracer = provider.tracer("test"); + let tracer = provider.tracer("test"); let subscriber = tracing_subscriber::registry() .with( layer()