From 2156c236db4c488eb6fce08bdd710dde290f5f52 Mon Sep 17 00:00:00 2001 From: Julian Tescher Date: Tue, 7 Nov 2023 13:13:26 -0500 Subject: [PATCH] Update otel to version 0.21 (#68) Support the latest version of otel. See https://github.com/open-telemetry/opentelemetry-rust/blob/v0.21.0/opentelemetry/CHANGELOG.md for changes. --- .github/workflows/CI.yml | 2 +- CHANGELOG.md | 9 ++++++ Cargo.toml | 18 +++++------ README.md | 2 +- benches/trace.rs | 2 +- examples/opentelemetry-error.rs | 23 ++++++-------- examples/opentelemetry-otlp.rs | 19 ++++++----- src/layer.rs | 56 ++++++++++++++++----------------- src/lib.rs | 2 +- src/span_ext.rs | 2 +- src/tracer.rs | 3 +- tests/errors.rs | 10 +++--- tests/metrics_publishing.rs | 14 +++------ 13 files changed, 80 insertions(+), 82 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 075db17..8005346 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -88,7 +88,7 @@ jobs: strategy: matrix: toolchain: - - 1.60.0 + - 1.65.0 - stable steps: - uses: actions/checkout@v3 diff --git a/CHANGELOG.md b/CHANGELOG.md index 942ad38..dcf8412 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +# Unreleased + +### Breaking Changes + +- Upgrade to `v0.21.0` of `opentelemetry` + For list of breaking changes in OpenTelemetry, see the + [v0.21.0 changelog](https://github.com/open-telemetry/opentelemetry-rust/blob/v0.21.0/opentelemetry/CHANGELOG.md). +- Update MSRV to require Rust 1.65+, as `opentelemetry` requires it now. + # 0.21.0 (August 28, 2023) ### Added diff --git a/Cargo.toml b/Cargo.toml index ff831ab..06419a4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ categories = [ keywords = ["tracing", "opentelemetry", "jaeger", "zipkin", "async"] license = "MIT" edition = "2018" -rust-version = "1.60.0" +rust-version = "1.65.0" [features] default = ["tracing-log", "metrics"] @@ -25,8 +25,8 @@ default = ["tracing-log", "metrics"] metrics = ["opentelemetry/metrics","opentelemetry_sdk/metrics", "smallvec"] [dependencies] -opentelemetry = { version = "0.20.0", default-features = false, features = ["trace"] } -opentelemetry_sdk = { version = "0.20.0", default-features = false, features = ["trace"] } +opentelemetry = { version = "0.21.0", default-features = false, features = ["trace"] } +opentelemetry_sdk = { version = "0.21.0", 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,12 @@ 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.20.0", features = ["trace", "metrics", "rt-tokio"] } -opentelemetry_sdk = { version = "0.20.0", default-features = false, features = ["trace"] } -opentelemetry-jaeger = "0.19.0" -opentelemetry-stdout = { version = "0.1.0", features = ["trace", "metrics"] } -opentelemetry-otlp = { version = "0.13.0", features = ["metrics"] } -opentelemetry-semantic-conventions = "0.12.0" +opentelemetry = { version = "0.21.0", features = ["trace", "metrics"] } +opentelemetry_sdk = { version = "0.21.0", default-features = false, features = ["trace", "rt-tokio"] } +opentelemetry-jaeger = "0.20.0" +opentelemetry-stdout = { version = "0.2.0", features = ["trace", "metrics"] } +opentelemetry-otlp = { version = "0.14.0", features = ["metrics"] } +opentelemetry-semantic-conventions = "0.13.0" futures-util = { version = "0.3", default-features = false } tokio = { version = "1", features = ["full"] } tokio-stream = "0.1" diff --git a/README.md b/README.md index 20a0415..6733981 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ The crate provides the following types: [`tracing`]: https://crates.io/crates/tracing [OpenTelemetry]: https://opentelemetry.io/ -*Compiler support: [requires `rustc` 1.60+][msrv]* +*Compiler support: [requires `rustc` 1.65+][msrv]* [msrv]: #supported-rust-versions diff --git a/benches/trace.rs b/benches/trace.rs index c236b30..f4e6faf 100644 --- a/benches/trace.rs +++ b/benches/trace.rs @@ -1,9 +1,9 @@ use criterion::{criterion_group, criterion_main, Criterion}; use opentelemetry::{ - sdk::trace::{Tracer, TracerProvider}, trace::{SpanBuilder, Tracer as _, TracerProvider as _}, Context, }; +use opentelemetry_sdk::trace::{Tracer, TracerProvider}; #[cfg(not(target_os = "windows"))] use pprof::criterion::{Output, PProfProfiler}; use std::time::SystemTime; diff --git a/examples/opentelemetry-error.rs b/examples/opentelemetry-error.rs index fe93cf6..70e542e 100644 --- a/examples/opentelemetry-error.rs +++ b/examples/opentelemetry-error.rs @@ -7,13 +7,11 @@ use std::{ time::{Duration, SystemTime}, }; -use opentelemetry::{ - global, - sdk::{ - self, - export::trace::{ExportResult, SpanExporter}, - }, - trace::TracerProvider, +use opentelemetry::{global, trace::TracerProvider}; + +use opentelemetry_sdk::{ + self as sdk, + export::trace::{ExportResult, SpanExporter}, }; use tracing::{error, instrument, span, trace, warn}; use tracing_subscriber::prelude::*; @@ -104,9 +102,8 @@ struct WriterExporter; impl SpanExporter for WriterExporter { fn export( &mut self, - batch: Vec, - ) -> futures_util::future::BoxFuture<'static, opentelemetry::sdk::export::trace::ExportResult> - { + batch: Vec, + ) -> futures_util::future::BoxFuture<'static, sdk::export::trace::ExportResult> { let mut writer = std::io::stdout(); for span in batch { writeln!(writer, "{}", SpanData(span)).unwrap(); @@ -117,7 +114,7 @@ impl SpanExporter for WriterExporter { } } -struct SpanData(opentelemetry::sdk::export::trace::SpanData); +struct SpanData(sdk::export::trace::SpanData); impl Display for SpanData { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { writeln!(f, "Span: \"{}\"", self.0.name)?; @@ -152,8 +149,8 @@ impl Display for SpanData { writeln!(f, " - {}: {}", k, v)?; } writeln!(f, "- Attributes:")?; - for (k, v) in self.0.attributes.iter() { - writeln!(f, " - {}: {}", k, v)?; + for kv in self.0.attributes.iter() { + writeln!(f, " - {}: {}", kv.key, kv.value)?; } writeln!(f, "- Events:")?; diff --git a/examples/opentelemetry-otlp.rs b/examples/opentelemetry-otlp.rs index 1d520bd..77eb167 100644 --- a/examples/opentelemetry-otlp.rs +++ b/examples/opentelemetry-otlp.rs @@ -1,10 +1,10 @@ -use opentelemetry::{global, runtime, Key, KeyValue}; -use opentelemetry_otlp::TonicExporterBuilder; +use opentelemetry::{global, Key, KeyValue}; use opentelemetry_sdk::{ metrics::{ reader::{DefaultAggregationSelector, DefaultTemporalitySelector}, Aggregation, Instrument, MeterProvider, PeriodicReader, Stream, }, + runtime, trace::{BatchConfig, RandomIdGenerator, Sampler, Tracer}, Resource, }; @@ -30,14 +30,13 @@ fn resource() -> Resource { // Construct MeterProvider for MetricsLayer fn init_meter_provider() -> MeterProvider { - // Currently we could not access MeterProviderBuilder from opentelemetry_otlp - // However to customize View we need MeterBuilder, so manually construct. - let exporter = opentelemetry_otlp::MetricsExporter::new( - TonicExporterBuilder::default(), - Box::new(DefaultTemporalitySelector::new()), - Box::new(DefaultAggregationSelector::new()), - ) - .unwrap(); + let exporter = opentelemetry_otlp::new_exporter() + .tonic() + .build_metrics_exporter( + Box::new(DefaultAggregationSelector::new()), + Box::new(DefaultTemporalitySelector::new()), + ) + .unwrap(); let reader = PeriodicReader::builder(exporter, runtime::Tokio) .with_interval(std::time::Duration::from_secs(30)) diff --git a/src/layer.rs b/src/layer.rs index c61346e..783f6eb 100644 --- a/src/layer.rs +++ b/src/layer.rs @@ -1,7 +1,7 @@ use crate::{OtelData, PreSampledTracer}; use once_cell::unsync; use opentelemetry::{ - trace::{self as otel, noop, OrderMap, TraceContextExt}, + trace::{self as otel, noop, TraceContextExt}, Context as OtelContext, Key, KeyValue, StringValue, Value, }; use std::any::TypeId; @@ -290,10 +290,10 @@ impl<'a, 'b> field::Visit for SpanEventVisitor<'a, 'b> { if self.sem_conv_config.error_records_to_exceptions { if let Some(span) = &mut self.span_builder { if let Some(attrs) = span.attributes.as_mut() { - attrs.insert( - Key::new(FIELD_EXCEPTION_MESSAGE), + attrs.push(KeyValue::new( + FIELD_EXCEPTION_MESSAGE, Value::String(error_msg.clone().into()), - ); + )); // NOTE: This is actually not the stacktrace of the exception. This is // the "source chain". It represents the heirarchy of errors from the @@ -301,10 +301,10 @@ impl<'a, 'b> field::Visit for SpanEventVisitor<'a, 'b> { // of the callsites in the code that led to the error happening. // `std::error::Error::backtrace` is a nightly-only API and cannot be // used here until the feature is stabilized. - attrs.insert( - Key::new(FIELD_EXCEPTION_STACKTRACE), + attrs.push(KeyValue::new( + FIELD_EXCEPTION_STACKTRACE, Value::Array(chain.clone().into()), - ); + )); } } } @@ -362,7 +362,7 @@ impl<'a> SpanAttributeVisitor<'a> { fn record(&mut self, attribute: KeyValue) { debug_assert!(self.span_builder.attributes.is_some()); if let Some(v) = self.span_builder.attributes.as_mut() { - v.insert(attribute.key, attribute.value); + v.push(KeyValue::new(attribute.key, attribute.value)); } } } @@ -859,7 +859,7 @@ where builder.trace_id = Some(self.tracer.new_trace_id()); } - let builder_attrs = builder.attributes.get_or_insert(OrderMap::with_capacity( + let builder_attrs = builder.attributes.get_or_insert(Vec::with_capacity( attrs.fields().len() + self.extra_span_attrs(), )); @@ -867,26 +867,26 @@ where let meta = attrs.metadata(); if let Some(filename) = meta.file() { - builder_attrs.insert("code.filepath".into(), filename.into()); + builder_attrs.push(KeyValue::new("code.filepath", filename)); } if let Some(module) = meta.module_path() { - builder_attrs.insert("code.namespace".into(), module.into()); + builder_attrs.push(KeyValue::new("code.namespace", module)); } if let Some(line) = meta.line() { - builder_attrs.insert("code.lineno".into(), (line as i64).into()); + builder_attrs.push(KeyValue::new("code.lineno", line as i64)); } } if self.with_threads { - THREAD_ID.with(|id| builder_attrs.insert("thread.id".into(), (**id as i64).into())); + THREAD_ID.with(|id| builder_attrs.push(KeyValue::new("thread.id", **id as i64))); if let Some(name) = std::thread::current().name() { // TODO(eliza): it's a bummer that we have to allocate here, but // we can't easily get the string as a `static`. it would be // nice if `opentelemetry` could also take `Arc`s as // `String` values... - builder_attrs.insert("thread.name".into(), name.to_owned().into()); + builder_attrs.push(KeyValue::new("thread.name", name.to_string())); } } @@ -1090,9 +1090,9 @@ where let attributes = builder .attributes - .get_or_insert_with(|| OrderMap::with_capacity(2)); - attributes.insert(busy_ns, timings.busy.into()); - attributes.insert(idle_ns, timings.idle.into()); + .get_or_insert_with(|| Vec::with_capacity(2)); + attributes.push(KeyValue::new(busy_ns, timings.busy)); + attributes.push(KeyValue::new(idle_ns, timings.idle)); } } @@ -1168,7 +1168,7 @@ mod tests { where T: Into>, { - noop::NoopSpan::new() + noop::NoopSpan::DEFAULT } fn span_builder(&self, name: T) -> otel::SpanBuilder where @@ -1185,7 +1185,7 @@ mod tests { builder, parent_cx: parent_cx.clone(), }); - noop::NoopSpan::new() + noop::NoopSpan::DEFAULT } } @@ -1369,7 +1369,7 @@ mod tests { let attributes = tracer.with_data(|data| data.builder.attributes.as_ref().unwrap().clone()); let keys = attributes .iter() - .map(|(key, _)| key.as_str()) + .map(|kv| kv.key.as_str()) .collect::>(); assert!(keys.contains(&"idle_ns")); assert!(keys.contains(&"busy_ns")); @@ -1405,7 +1405,7 @@ mod tests { let key_values = attributes .into_iter() - .map(|(key, value)| (key.as_str().to_owned(), value)) + .map(|kv| (kv.key.as_str().to_owned(), kv.value)) .collect::>(); assert_eq!(key_values["error"].as_str(), "user error"); @@ -1467,7 +1467,7 @@ mod tests { let key_values = attributes .into_iter() - .map(|(key, value)| (key.as_str().to_owned(), value)) + .map(|kv| (kv.key.as_str().to_owned(), kv.value)) .collect::>(); assert_eq!(key_values["error"].as_str(), "user error"); @@ -1508,7 +1508,7 @@ mod tests { let attributes = tracer.with_data(|data| data.builder.attributes.as_ref().unwrap().clone()); let keys = attributes .iter() - .map(|(key, _)| key.as_str()) + .map(|kv| kv.key.as_str()) .collect::>(); assert!(keys.contains(&"code.filepath")); assert!(keys.contains(&"code.namespace")); @@ -1528,7 +1528,7 @@ mod tests { let attributes = tracer.with_data(|data| data.builder.attributes.as_ref().unwrap().clone()); let keys = attributes .iter() - .map(|(key, _)| key.as_str()) + .map(|kv| kv.key.as_str()) .collect::>(); assert!(!keys.contains(&"code.filepath")); assert!(!keys.contains(&"code.namespace")); @@ -1554,7 +1554,7 @@ mod tests { let attributes = tracer .with_data(|data| data.builder.attributes.as_ref().unwrap().clone()) .drain(..) - .map(|(key, value)| (key.as_str().to_string(), value)) + .map(|kv| (kv.key.as_str().to_string(), kv.value)) .collect::>(); assert_eq!(attributes.get("thread.name"), expected_name.as_ref()); assert_eq!(attributes.get("thread.id"), Some(&expected_id)); @@ -1573,7 +1573,7 @@ mod tests { let attributes = tracer.with_data(|data| data.builder.attributes.as_ref().unwrap().clone()); let keys = attributes .iter() - .map(|(key, _)| key.as_str()) + .map(|kv| kv.key.as_str()) .collect::>(); assert!(!keys.contains(&"thread.name")); assert!(!keys.contains(&"thread.id")); @@ -1611,7 +1611,7 @@ mod tests { let key_values = attributes .into_iter() - .map(|(key, value)| (key.as_str().to_owned(), value)) + .map(|kv| (kv.key.as_str().to_owned(), kv.value)) .collect::>(); assert_eq!(key_values[FIELD_EXCEPTION_MESSAGE].as_str(), "user error"); @@ -1663,7 +1663,7 @@ mod tests { let key_values = attributes .into_iter() - .map(|(key, value)| (key.as_str().to_owned(), value)) + .map(|kv| (kv.key.as_str().to_owned(), kv.value)) .collect::>(); assert_eq!(key_values[FIELD_EXCEPTION_MESSAGE].as_str(), "user error"); diff --git a/src/lib.rs b/src/lib.rs index 1c7b839..843f086 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,7 @@ //! [OpenTelemetry]: https://opentelemetry.io //! [`tracing`]: https://github.com/tokio-rs/tracing //! -//! *Compiler support: [requires `rustc` 1.60+][msrv]* +//! *Compiler support: [requires `rustc` 1.65+][msrv]* //! //! [msrv]: #supported-rust-versions //! diff --git a/src/span_ext.rs b/src/span_ext.rs index 94d96a9..d7f8f3a 100644 --- a/src/span_ext.rs +++ b/src/span_ext.rs @@ -201,7 +201,7 @@ impl OpenTelemetrySpanExt for tracing::Span { .attributes .as_mut() .unwrap() - .insert(key.take().unwrap(), value.take().unwrap()); + .push(KeyValue::new(key.take().unwrap(), value.take().unwrap())); }) } }); diff --git a/src/tracer.rs b/src/tracer.rs index 81e892d..a4072d7 100644 --- a/src/tracer.rs +++ b/src/tracer.rs @@ -1,4 +1,3 @@ -use opentelemetry::trace::OrderMap; use opentelemetry::{ trace as otel, trace::{ @@ -86,7 +85,7 @@ impl PreSampledTracer for SdkTracer { trace_id, &builder.name, builder.span_kind.as_ref().unwrap_or(&SpanKind::Internal), - builder.attributes.as_ref().unwrap_or(&OrderMap::default()), + builder.attributes.as_deref().unwrap_or(&[]), builder.links.as_deref().unwrap_or(&[]), )); diff --git a/tests/errors.rs b/tests/errors.rs index d1e92e1..93162fa 100644 --- a/tests/errors.rs +++ b/tests/errors.rs @@ -1,10 +1,8 @@ use futures_util::future::BoxFuture; -use opentelemetry::{ - sdk::{ - export::trace::{ExportResult, SpanData, SpanExporter}, - trace::{Tracer, TracerProvider}, - }, - trace::TracerProvider as _, +use opentelemetry::trace::TracerProvider as _; +use opentelemetry_sdk::{ + export::trace::{ExportResult, SpanData, SpanExporter}, + trace::{Tracer, TracerProvider}, }; use std::sync::{Arc, Mutex}; use tracing::{instrument, Subscriber}; diff --git a/tests/metrics_publishing.rs b/tests/metrics_publishing.rs index 6e54deb..d1dbac9 100644 --- a/tests/metrics_publishing.rs +++ b/tests/metrics_publishing.rs @@ -1,11 +1,11 @@ -use opentelemetry::{metrics::MetricsError, Context, KeyValue}; +use opentelemetry::{metrics::MetricsError, KeyValue}; use opentelemetry_sdk::{ metrics::{ data, data::{Histogram, Sum}, reader::{ AggregationSelector, DefaultAggregationSelector, DefaultTemporalitySelector, - MetricProducer, MetricReader, TemporalitySelector, + MetricReader, TemporalitySelector, }, InstrumentKind, ManualReader, MeterProvider, }, @@ -395,7 +395,7 @@ fn init_subscriber( expected_attributes: Option, ) -> (impl Subscriber + 'static, TestExporter) { let reader = ManualReader::builder() - .with_aggregation_selector(Box::new(DefaultAggregationSelector::new())) + .with_aggregation_selector(DefaultAggregationSelector::new()) .with_temporality_selector(DefaultTemporalitySelector::new()) .build(); let reader = TestReader { @@ -440,16 +440,12 @@ impl MetricReader for TestReader { self.inner.register_pipeline(pipeline); } - fn register_producer(&self, producer: Box) { - self.inner.register_producer(producer); - } - fn collect(&self, rm: &mut data::ResourceMetrics) -> opentelemetry::metrics::Result<()> { self.inner.collect(rm) } - fn force_flush(&self, cx: &Context) -> opentelemetry::metrics::Result<()> { - self.inner.force_flush(cx) + fn force_flush(&self) -> opentelemetry::metrics::Result<()> { + self.inner.force_flush() } fn shutdown(&self) -> opentelemetry::metrics::Result<()> {