diff --git a/Cargo.toml b/Cargo.toml index 2d3467c..5fccb0f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,8 +23,8 @@ metrics = ["opentelemetry/metrics","opentelemetry_sdk/metrics", "smallvec"] metrics_gauge_unstable = ["opentelemetry/otel_unstable"] [dependencies] -opentelemetry = { version = "0.26", default-features = false, features = ["trace"] } -opentelemetry_sdk = { version = "0.26", default-features = false, features = ["trace"] } +opentelemetry = { version = "0.27.0", default-features = false, features = ["trace"] } +opentelemetry_sdk = { version = "0.27.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,11 +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.26", features = ["trace", "metrics"] } -opentelemetry_sdk = { version = "0.26", default-features = false, features = ["trace", "rt-tokio"] } -opentelemetry-stdout = { version = "0.26", features = ["trace", "metrics"] } -opentelemetry-otlp = { version = "0.26", features = ["metrics"] } -opentelemetry-semantic-conventions = { version = "0.26", features = ["semconv_experimental"] } +opentelemetry = { version = "0.27.0", features = ["trace", "metrics", "spec_unstable_metrics_views"] } +opentelemetry_sdk = { version = "0.27.0", default-features = false, features = ["trace", "rt-tokio"] } +opentelemetry-stdout = { version = "0.27.0", features = ["trace", "metrics"] } +opentelemetry-otlp = { version = "0.27.0", features = ["metrics"] } +opentelemetry-semantic-conventions = { version = "0.27.0", features = ["semconv_experimental"] } futures-util = { version = "0.3.17", default-features = false } tokio = { version = "1", features = ["full"] } tokio-stream = "0.1" diff --git a/benches/metrics.rs b/benches/metrics.rs index a58b738..0648ceb 100644 --- a/benches/metrics.rs +++ b/benches/metrics.rs @@ -1,10 +1,35 @@ use criterion::{criterion_group, criterion_main, Criterion}; -use opentelemetry::metrics::noop::NoopMeterProvider; #[cfg(not(target_os = "windows"))] use pprof::criterion::{Output, PProfProfiler}; use tracing_opentelemetry::MetricsLayer; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; +// OpenTelemetry crate no longer publishes their NoopMeterProvider, +// so we just implement our own here. +mod noop { + use opentelemetry::metrics::{InstrumentProvider, Meter, MeterProvider}; + + #[derive(Default)] + pub struct NoopMeterProvider { + _private: (), + } + + impl MeterProvider for NoopMeterProvider { + fn meter_with_scope(&self, _: opentelemetry::InstrumentationScope) -> Meter { + Meter::new(std::sync::Arc::new(NoopMeter::default())) + } + } + + #[derive(Default)] + pub struct NoopMeter { + _private: (), + } + + impl InstrumentProvider for NoopMeter {} +} + +use noop::*; + fn metrics_events(c: &mut Criterion) { let mut group = c.benchmark_group("otel_metrics_events"); { @@ -18,7 +43,7 @@ fn metrics_events(c: &mut Criterion) { { let _subscriber = tracing_subscriber::registry() - .with(MetricsLayer::new(NoopMeterProvider::new())) + .with(MetricsLayer::new(NoopMeterProvider::default())) .set_default(); group.bench_function("metrics_events_0_attr_0", |b| { b.iter(|| { @@ -29,7 +54,7 @@ fn metrics_events(c: &mut Criterion) { { let _subscriber = tracing_subscriber::registry() - .with(MetricsLayer::new(NoopMeterProvider::new())) + .with(MetricsLayer::new(NoopMeterProvider::default())) .set_default(); group.bench_function("metrics_events_1_attr_0", |b| { b.iter(|| { @@ -40,7 +65,7 @@ fn metrics_events(c: &mut Criterion) { { let _subscriber = tracing_subscriber::registry() - .with(MetricsLayer::new(NoopMeterProvider::new())) + .with(MetricsLayer::new(NoopMeterProvider::default())) .set_default(); group.bench_function("metrics_events_2_attr_0", |b| { b.iter(|| { @@ -51,7 +76,7 @@ fn metrics_events(c: &mut Criterion) { { let _subscriber = tracing_subscriber::registry() - .with(MetricsLayer::new(NoopMeterProvider::new())) + .with(MetricsLayer::new(NoopMeterProvider::default())) .set_default(); group.bench_function("metrics_events_4_attr_0", |b| { b.iter(|| { @@ -68,7 +93,7 @@ fn metrics_events(c: &mut Criterion) { { let _subscriber = tracing_subscriber::registry() - .with(MetricsLayer::new(NoopMeterProvider::new())) + .with(MetricsLayer::new(NoopMeterProvider::default())) .set_default(); group.bench_function("metrics_events_8_attr_0", |b| { b.iter(|| { @@ -89,7 +114,7 @@ fn metrics_events(c: &mut Criterion) { { let _subscriber = tracing_subscriber::registry() - .with(MetricsLayer::new(NoopMeterProvider::new())) + .with(MetricsLayer::new(NoopMeterProvider::default())) .set_default(); group.bench_function("metrics_events_1_attr_1", |b| { b.iter(|| { @@ -100,7 +125,7 @@ fn metrics_events(c: &mut Criterion) { { let _subscriber = tracing_subscriber::registry() - .with(MetricsLayer::new(NoopMeterProvider::new())) + .with(MetricsLayer::new(NoopMeterProvider::default())) .set_default(); group.bench_function("metrics_events_1_attr_2", |b| { b.iter(|| { @@ -116,7 +141,7 @@ fn metrics_events(c: &mut Criterion) { { let _subscriber = tracing_subscriber::registry() - .with(MetricsLayer::new(NoopMeterProvider::new())) + .with(MetricsLayer::new(NoopMeterProvider::default())) .set_default(); group.bench_function("metrics_events_1_attr_4", |b| { b.iter(|| { @@ -134,7 +159,7 @@ fn metrics_events(c: &mut Criterion) { { let _subscriber = tracing_subscriber::registry() - .with(MetricsLayer::new(NoopMeterProvider::new())) + .with(MetricsLayer::new(NoopMeterProvider::default())) .set_default(); group.bench_function("metrics_events_1_attr_8", |b| { b.iter(|| { diff --git a/examples/opentelemetry-error.rs b/examples/opentelemetry-error.rs index bcc3b5b..37c3d3b 100644 --- a/examples/opentelemetry-error.rs +++ b/examples/opentelemetry-error.rs @@ -6,8 +6,8 @@ use std::{ time::{Duration, SystemTime}, }; -use opentelemetry::{global, trace::TracerProvider}; - +use opentelemetry::global; +use opentelemetry::trace::TracerProvider as _; use opentelemetry_sdk::{ self as sdk, export::trace::{ExportResult, SpanExporter}, @@ -59,9 +59,8 @@ fn double_failable_work(fail: bool) -> Result<&'static str, Error> { fn main() -> Result<(), Box> { let builder = sdk::trace::TracerProvider::builder().with_simple_exporter(WriterExporter); let provider = builder.build(); - let tracer = provider - .tracer_builder("opentelemetry-write-exporter") - .build(); + let tracer = provider.tracer("opentelemetry-write-exporter"); + global::set_tracer_provider(provider); let opentelemetry = tracing_opentelemetry::layer().with_tracer(tracer); diff --git a/examples/opentelemetry-otlp.rs b/examples/opentelemetry-otlp.rs index 62d67ee..f5efc26 100644 --- a/examples/opentelemetry-otlp.rs +++ b/examples/opentelemetry-otlp.rs @@ -1,11 +1,8 @@ -use opentelemetry::{global, trace::TracerProvider, Key, KeyValue}; +use opentelemetry::{global, trace::TracerProvider as _, KeyValue}; use opentelemetry_sdk::{ - metrics::{ - reader::DefaultTemporalitySelector, Aggregation, Instrument, MeterProviderBuilder, - PeriodicReader, SdkMeterProvider, Stream, - }, + metrics::{MeterProviderBuilder, PeriodicReader, SdkMeterProvider}, runtime, - trace::{BatchConfig, RandomIdGenerator, Sampler, Tracer}, + trace::{RandomIdGenerator, Sampler, Tracer, TracerProvider}, Resource, }; use opentelemetry_semantic_conventions::{ @@ -30,9 +27,10 @@ fn resource() -> Resource { // Construct MeterProvider for MetricsLayer fn init_meter_provider() -> SdkMeterProvider { - let exporter = opentelemetry_otlp::new_exporter() - .tonic() - .build_metrics_exporter(Box::new(DefaultTemporalitySelector::new())) + let exporter = opentelemetry_otlp::MetricExporter::builder() + .with_tonic() + .with_temporality(opentelemetry_sdk::metrics::Temporality::default()) + .build() .unwrap(); let reader = PeriodicReader::builder(exporter, runtime::Tokio) @@ -41,11 +39,13 @@ fn init_meter_provider() -> SdkMeterProvider { // For debugging in development let stdout_reader = PeriodicReader::builder( - opentelemetry_stdout::MetricsExporter::default(), + opentelemetry_stdout::MetricExporter::default(), runtime::Tokio, ) .build(); + // NOTE: Views are gated behind opentelemetry's `spec_unstable_metrics_views` feature. + // If you need to use views in your crate, remember to enable the feature! // Rename foo metrics to foo_named and drop key_2 attribute let view_foo = |instrument: &Instrument| -> Option { if instrument.name == "foo" { @@ -90,9 +90,13 @@ fn init_meter_provider() -> SdkMeterProvider { // Construct Tracer for OpenTelemetryLayer fn init_tracer() -> Tracer { - let provider = opentelemetry_otlp::new_pipeline() - .tracing() - .with_trace_config( + let exporter = opentelemetry_otlp::SpanExporter::builder() + .with_tonic() + .build() + .unwrap(); + + let provider = TracerProvider::builder() + .with_config( opentelemetry_sdk::trace::Config::default() // Customize sampling strategy .with_sampler(Sampler::ParentBased(Box::new(Sampler::TraceIdRatioBased( @@ -102,10 +106,8 @@ fn init_tracer() -> Tracer { .with_id_generator(RandomIdGenerator::default()) .with_resource(resource()), ) - .with_batch_config(BatchConfig::default()) - .with_exporter(opentelemetry_otlp::new_exporter().tonic()) - .install_batch(runtime::Tokio) - .unwrap(); + .with_batch_exporter(exporter, runtime::Tokio) + .build(); global::set_tracer_provider(provider.clone()); provider.tracer("tracing-otel-subscriber") diff --git a/src/layer.rs b/src/layer.rs index 45c6b36..f8de13a 100644 --- a/src/layer.rs +++ b/src/layer.rs @@ -536,17 +536,19 @@ where /// ```no_run /// use tracing_opentelemetry::OpenTelemetryLayer; /// use tracing_subscriber::layer::SubscriberExt; - /// use opentelemetry::trace::TracerProvider; + /// use opentelemetry::trace::TracerProvider as _; /// use tracing_subscriber::Registry; /// /// // 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() - /// .unwrap() + /// let otlp_exporter = opentelemetry_otlp::SpanExporter::builder() + /// .with_tonic() + /// .build() + /// .unwrap(); + /// + /// let tracer = opentelemetry_sdk::trace::TracerProvider::builder() + /// .with_simple_exporter(otlp_exporter) + /// .build() /// .tracer("trace_demo"); /// /// // Create a layer with the configured tracer @@ -591,12 +593,14 @@ where /// /// // 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() - /// .unwrap() + /// let otlp_exporter = opentelemetry_otlp::SpanExporter::builder() + /// .with_tonic() + /// .build() + /// .unwrap(); + /// + /// let tracer = opentelemetry_sdk::trace::TracerProvider::builder() + /// .with_simple_exporter(otlp_exporter) + /// .build() /// .tracer("trace_demo"); /// /// // Create a layer with the configured tracer diff --git a/src/metrics.rs b/src/metrics.rs index 33e1863..ca558eb 100644 --- a/src/metrics.rs +++ b/src/metrics.rs @@ -6,7 +6,7 @@ use tracing_core::{Field, Interest, Metadata}; use opentelemetry::metrics::Gauge; use opentelemetry::{ metrics::{Counter, Histogram, Meter, MeterProvider, UpDownCounter}, - KeyValue, Value, + InstrumentationScope, KeyValue, Value, }; use tracing_subscriber::{ filter::Filtered, @@ -98,7 +98,7 @@ impl Instruments { update_or_insert( &self.u64_counter, metric_name, - || meter.u64_counter(metric_name).init(), + || meter.u64_counter(metric_name).build(), |ctr| ctr.add(value, attributes), ); } @@ -106,7 +106,7 @@ impl Instruments { update_or_insert( &self.f64_counter, metric_name, - || meter.f64_counter(metric_name).init(), + || meter.f64_counter(metric_name).build(), |ctr| ctr.add(value, attributes), ); } @@ -114,7 +114,7 @@ impl Instruments { update_or_insert( &self.i64_up_down_counter, metric_name, - || meter.i64_up_down_counter(metric_name).init(), + || meter.i64_up_down_counter(metric_name).build(), |ctr| ctr.add(value, attributes), ); } @@ -122,7 +122,7 @@ impl Instruments { update_or_insert( &self.f64_up_down_counter, metric_name, - || meter.f64_up_down_counter(metric_name).init(), + || meter.f64_up_down_counter(metric_name).build(), |ctr| ctr.add(value, attributes), ); } @@ -130,7 +130,7 @@ impl Instruments { update_or_insert( &self.u64_histogram, metric_name, - || meter.u64_histogram(metric_name).init(), + || meter.u64_histogram(metric_name).build(), |rec| rec.record(value, attributes), ); } @@ -138,7 +138,7 @@ impl Instruments { update_or_insert( &self.f64_histogram, metric_name, - || meter.f64_histogram(metric_name).init(), + || meter.f64_histogram(metric_name).build(), |rec| rec.record(value, attributes), ); } @@ -395,11 +395,10 @@ where where M: MeterProvider, { - let meter = meter_provider.versioned_meter( - INSTRUMENTATION_LIBRARY_NAME, - Some(CARGO_PKG_VERSION), - None::<&'static str>, - None, + let meter = meter_provider.meter_with_scope( + InstrumentationScope::builder(INSTRUMENTATION_LIBRARY_NAME) + .with_version(CARGO_PKG_VERSION) + .build(), ); let layer = InstrumentLayer { diff --git a/tests/metrics_publishing.rs b/tests/metrics_publishing.rs index 35a51ab..7868b5b 100644 --- a/tests/metrics_publishing.rs +++ b/tests/metrics_publishing.rs @@ -1,9 +1,9 @@ -use opentelemetry::{metrics::MetricsError, KeyValue}; +use opentelemetry::KeyValue; use opentelemetry_sdk::{ metrics::{ data::{self, Gauge, Histogram, Sum}, - reader::{MetricReader, TemporalitySelector}, - InstrumentKind, ManualReader, MeterProviderBuilder, SdkMeterProvider, + reader::MetricReader, + InstrumentKind, ManualReader, MeterProviderBuilder, MetricError, SdkMeterProvider, }, Resource, }; @@ -542,28 +542,29 @@ struct TestReader { inner: Arc, } -impl TemporalitySelector for TestReader { - fn temporality(&self, kind: InstrumentKind) -> opentelemetry_sdk::metrics::data::Temporality { - self.inner.temporality(kind) - } -} - impl MetricReader for TestReader { fn register_pipeline(&self, pipeline: std::sync::Weak) { self.inner.register_pipeline(pipeline); } - fn collect(&self, rm: &mut data::ResourceMetrics) -> opentelemetry::metrics::Result<()> { + fn collect( + &self, + rm: &mut data::ResourceMetrics, + ) -> opentelemetry_sdk::metrics::MetricResult<()> { self.inner.collect(rm) } - fn force_flush(&self) -> opentelemetry::metrics::Result<()> { + fn force_flush(&self) -> opentelemetry_sdk::metrics::MetricResult<()> { self.inner.force_flush() } - fn shutdown(&self) -> opentelemetry::metrics::Result<()> { + fn shutdown(&self) -> opentelemetry_sdk::metrics::MetricResult<()> { self.inner.shutdown() } + + fn temporality(&self, kind: InstrumentKind) -> opentelemetry_sdk::metrics::Temporality { + self.inner.temporality(kind) + } } struct TestExporter { @@ -579,7 +580,7 @@ impl TestExporter where T: Debug + PartialEq + Copy + std::iter::Sum + 'static, { - fn export(&self) -> Result<(), MetricsError> { + fn export(&self) -> Result<(), MetricError> { let mut rm = data::ResourceMetrics { resource: Resource::default(), scope_metrics: Vec::new(), @@ -589,11 +590,8 @@ where assert!(!rm.scope_metrics.is_empty()); rm.scope_metrics.into_iter().for_each(|scope_metrics| { - assert_eq!(scope_metrics.scope.name, INSTRUMENTATION_LIBRARY_NAME); - assert_eq!( - scope_metrics.scope.version.unwrap().as_ref(), - CARGO_PKG_VERSION - ); + assert_eq!(scope_metrics.scope.name(), INSTRUMENTATION_LIBRARY_NAME); + assert_eq!(scope_metrics.scope.version().unwrap(), CARGO_PKG_VERSION); scope_metrics.metrics.into_iter().for_each(|metric| { assert_eq!(metric.name, self.expected_metric_name); @@ -671,8 +669,8 @@ fn compare_attributes(expected: &Vec, actual: &Vec) -> bool let mut expected = expected.clone(); let mut actual = actual.clone(); - expected.sort(); - actual.sort(); + expected.sort_unstable_by(|a, b| a.key.cmp(&b.key)); + actual.sort_unstable_by(|a, b| a.key.cmp(&b.key)); expected == actual }