From 2261985ec8514c4c27118c934a9083069d80969a Mon Sep 17 00:00:00 2001 From: Julian Tescher Date: Thu, 23 Dec 2021 13:25:01 -0500 Subject: [PATCH] trace: split `tracer` and `versioned_tracer` methods The [trace spec] requires that `TracerProvider`s MUST accept optional `version` and `schema_url` parameters. This introduces ergonomic issues as rust does not have a variadic solution outside of macros, leading to many calls with only a single relevant argument (e.g. `tracer(name, None, None)`). This patch splits the current `TracerProvider::tracer` method into `TracerProvider::versioned_tracer` which implements the spec mandated optional fields, as well as a `TracerProvider::tracer` method that accepts only a `name` parameter as a convenience method for the above listed common case. [trace spec]: https://github.com/open-telemetry/opentelemetry-specification/blob/v1.4.0/specification/trace/api.md#get-a-tracer --- opentelemetry-datadog/src/exporter/mod.rs | 12 ++++- opentelemetry-jaeger/src/exporter/mod.rs | 14 +++-- opentelemetry-otlp/src/span.rs | 6 ++- opentelemetry-zipkin/src/exporter/mod.rs | 12 ++++- opentelemetry/benches/trace.rs | 4 +- opentelemetry/src/global/mod.rs | 12 +++-- opentelemetry/src/global/trace.rs | 44 ++++++++-------- opentelemetry/src/sdk/export/trace/stdout.rs | 4 +- .../src/sdk/propagation/composite.rs | 2 +- opentelemetry/src/sdk/trace/provider.rs | 13 +++-- opentelemetry/src/sdk/trace/span.rs | 8 +-- opentelemetry/src/sdk/trace/tracer.rs | 6 +-- opentelemetry/src/trace/context.rs | 2 +- opentelemetry/src/trace/mod.rs | 6 ++- opentelemetry/src/trace/noop.rs | 7 ++- opentelemetry/src/trace/tracer_provider.rs | 51 ++++++++++++++++--- 16 files changed, 142 insertions(+), 61 deletions(-) diff --git a/opentelemetry-datadog/src/exporter/mod.rs b/opentelemetry-datadog/src/exporter/mod.rs index 7dca141a22..6725b6369d 100644 --- a/opentelemetry-datadog/src/exporter/mod.rs +++ b/opentelemetry-datadog/src/exporter/mod.rs @@ -169,7 +169,11 @@ impl DatadogPipelineBuilder { sdk::trace::TracerProvider::builder().with_simple_exporter(exporter); provider_builder = provider_builder.with_config(config); let provider = provider_builder.build(); - let tracer = provider.tracer("opentelemetry-datadog", Some(env!("CARGO_PKG_VERSION"))); + let tracer = provider.versioned_tracer( + "opentelemetry-datadog", + Some(env!("CARGO_PKG_VERSION")), + None, + ); let _ = global::set_tracer_provider(provider); Ok(tracer) } @@ -186,7 +190,11 @@ impl DatadogPipelineBuilder { sdk::trace::TracerProvider::builder().with_batch_exporter(exporter, runtime); provider_builder = provider_builder.with_config(config); let provider = provider_builder.build(); - let tracer = provider.tracer("opentelemetry-datadog", Some(env!("CARGO_PKG_VERSION"))); + let tracer = provider.versioned_tracer( + "opentelemetry-datadog", + Some(env!("CARGO_PKG_VERSION")), + None, + ); let _ = global::set_tracer_provider(provider); Ok(tracer) } diff --git a/opentelemetry-jaeger/src/exporter/mod.rs b/opentelemetry-jaeger/src/exporter/mod.rs index bf752dc76f..2c95cb980e 100644 --- a/opentelemetry-jaeger/src/exporter/mod.rs +++ b/opentelemetry-jaeger/src/exporter/mod.rs @@ -322,8 +322,11 @@ impl PipelineBuilder { /// Install a Jaeger pipeline with a simple span processor. pub fn install_simple(self) -> Result { let tracer_provider = self.build_simple()?; - let tracer = - tracer_provider.tracer("opentelemetry-jaeger", Some(env!("CARGO_PKG_VERSION"))); + let tracer = tracer_provider.versioned_tracer( + "opentelemetry-jaeger", + Some(env!("CARGO_PKG_VERSION")), + None, + ); let _ = global::set_tracer_provider(tracer_provider); Ok(tracer) } @@ -334,8 +337,11 @@ impl PipelineBuilder { runtime: R, ) -> Result { let tracer_provider = self.build_batch(runtime)?; - let tracer = - tracer_provider.tracer("opentelemetry-jaeger", Some(env!("CARGO_PKG_VERSION"))); + let tracer = tracer_provider.versioned_tracer( + "opentelemetry-jaeger", + Some(env!("CARGO_PKG_VERSION")), + None, + ); let _ = global::set_tracer_provider(tracer_provider); Ok(tracer) } diff --git a/opentelemetry-otlp/src/span.rs b/opentelemetry-otlp/src/span.rs index 15d7642212..d4be2e07ed 100644 --- a/opentelemetry-otlp/src/span.rs +++ b/opentelemetry-otlp/src/span.rs @@ -164,7 +164,8 @@ fn build_simple_with_exporter( provider_builder = provider_builder.with_config(config); } let provider = provider_builder.build(); - let tracer = provider.tracer("opentelemetry-otlp", Some(env!("CARGO_PKG_VERSION"))); + let tracer = + provider.versioned_tracer("opentelemetry-otlp", Some(env!("CARGO_PKG_VERSION")), None); let _ = global::set_tracer_provider(provider); tracer } @@ -180,7 +181,8 @@ fn build_batch_with_exporter( provider_builder = provider_builder.with_config(config); } let provider = provider_builder.build(); - let tracer = provider.tracer("opentelemetry-otlp", Some(env!("CARGO_PKG_VERSION"))); + let tracer = + provider.versioned_tracer("opentelemetry-otlp", Some(env!("CARGO_PKG_VERSION")), None); let _ = global::set_tracer_provider(provider); tracer } diff --git a/opentelemetry-zipkin/src/exporter/mod.rs b/opentelemetry-zipkin/src/exporter/mod.rs index d5f9c5041e..b57e0c79c8 100644 --- a/opentelemetry-zipkin/src/exporter/mod.rs +++ b/opentelemetry-zipkin/src/exporter/mod.rs @@ -156,7 +156,11 @@ impl ZipkinPipelineBuilder { sdk::trace::TracerProvider::builder().with_simple_exporter(exporter); provider_builder = provider_builder.with_config(config); let provider = provider_builder.build(); - let tracer = provider.tracer("opentelemetry-zipkin", Some(env!("CARGO_PKG_VERSION"))); + let tracer = provider.versioned_tracer( + "opentelemetry-zipkin", + Some(env!("CARGO_PKG_VERSION")), + None, + ); let _ = global::set_tracer_provider(provider); Ok(tracer) } @@ -173,7 +177,11 @@ impl ZipkinPipelineBuilder { sdk::trace::TracerProvider::builder().with_batch_exporter(exporter, runtime); provider_builder = provider_builder.with_config(config); let provider = provider_builder.build(); - let tracer = provider.tracer("opentelemetry-zipkin", Some(env!("CARGO_PKG_VERSION"))); + let tracer = provider.versioned_tracer( + "opentelemetry-zipkin", + Some(env!("CARGO_PKG_VERSION")), + None, + ); let _ = global::set_tracer_provider(provider); Ok(tracer) } diff --git a/opentelemetry/benches/trace.rs b/opentelemetry/benches/trace.rs index 71b14d1773..e05920f779 100644 --- a/opentelemetry/benches/trace.rs +++ b/opentelemetry/benches/trace.rs @@ -115,7 +115,7 @@ fn trace_benchmark_group(c: &mut Criterion, name: &str .with_config(sdktrace::config().with_sampler(sdktrace::Sampler::AlwaysOn)) .with_simple_exporter(VoidExporter) .build(); - let always_sample = provider.tracer("always-sample", None); + let always_sample = provider.tracer("always-sample"); b.iter(|| f(&always_sample)); }); @@ -125,7 +125,7 @@ fn trace_benchmark_group(c: &mut Criterion, name: &str .with_config(sdktrace::config().with_sampler(sdktrace::Sampler::AlwaysOff)) .with_simple_exporter(VoidExporter) .build(); - let never_sample = provider.tracer("never-sample", None); + let never_sample = provider.tracer("never-sample"); b.iter(|| f(&never_sample)); }); diff --git a/opentelemetry/src/global/mod.rs b/opentelemetry/src/global/mod.rs index 05460c2fac..e224ac4141 100644 --- a/opentelemetry/src/global/mod.rs +++ b/opentelemetry/src/global/mod.rs @@ -49,13 +49,17 @@ //! ``` //! # #[cfg(feature="trace")] //! # { -//! use opentelemetry::trace::Tracer; +//! use opentelemetry::trace::{Tracer, TracerProvider}; //! use opentelemetry::global; //! //! pub fn my_traced_library_function() { //! // End users of your library will configure their global tracer provider //! // so you can use the global tracer without any setup -//! let tracer = global::tracer_with_version("my-library-name", env!("CARGO_PKG_VERSION")); +//! let tracer = global::tracer_provider().versioned_tracer( +//! "my-library-name", +//! Some(env!("CARGO_PKG_VERSION")), +//! None, +//! ); //! //! tracer.in_span("doing_library_work", |cx| { //! // Traced library logic here... @@ -156,6 +160,6 @@ pub use propagation::{get_text_map_propagator, set_text_map_propagator}; #[cfg_attr(docsrs, doc(cfg(feature = "trace")))] pub use trace::{ force_flush_tracer_provider, set_tracer_provider, shutdown_tracer_provider, tracer, - tracer_provider, tracer_with_version, BoxedSpan, BoxedTracer, GlobalTracerProvider, - ObjectSafeTracer, ObjectSafeTracerProvider, + tracer_provider, BoxedSpan, BoxedTracer, GlobalTracerProvider, ObjectSafeTracer, + ObjectSafeTracerProvider, }; diff --git a/opentelemetry/src/global/trace.rs b/opentelemetry/src/global/trace.rs index 854da11024..de00d4cb51 100644 --- a/opentelemetry/src/global/trace.rs +++ b/opentelemetry/src/global/trace.rs @@ -327,11 +327,13 @@ where /// [`TracerProvider`]: crate::trace::TracerProvider /// [`GlobalTracerProvider`]: crate::global::GlobalTracerProvider pub trait ObjectSafeTracerProvider { - /// Creates a named tracer instance that is a trait object through the underlying `TracerProvider`. - fn tracer_boxed( + /// Creates a versioned named tracer instance that is a trait object through the underlying + /// `TracerProvider`. + fn versioned_tracer_boxed( &self, name: Cow<'static, str>, - version: Option>, + version: Option<&'static str>, + schema_url: Option<&'static str>, ) -> Box; /// Force flush all remaining spans in span processors and return results. @@ -344,13 +346,14 @@ where T: trace::Tracer + Send + Sync + 'static, P: trace::TracerProvider, { - /// Return a boxed tracer - fn tracer_boxed( + /// Return a versioned boxed tracer + fn versioned_tracer_boxed( &self, name: Cow<'static, str>, - version: Option>, + version: Option<&'static str>, + schema_url: Option<&'static str>, ) -> Box { - Box::new(self.tracer(name, version)) + Box::new(self.versioned_tracer(name, version, schema_url)) } fn force_flush(&self) -> Vec> { @@ -391,11 +394,16 @@ impl GlobalTracerProvider { impl trace::TracerProvider for GlobalTracerProvider { type Tracer = BoxedTracer; - /// Find or create a named tracer using the global provider. - fn tracer>>(&self, name: T, version: Option) -> Self::Tracer { + /// Create a versioned tracer using the global provider. + fn versioned_tracer( + &self, + name: impl Into>, + version: Option<&'static str>, + schema_url: Option<&'static str>, + ) -> Self::Tracer { BoxedTracer( self.provider - .tracer_boxed(name.into(), version.map(Into::>::into)), + .versioned_tracer_boxed(name.into(), version, schema_url), ) } @@ -426,21 +434,11 @@ pub fn tracer_provider() -> GlobalTracerProvider { /// /// If the name is an empty string, the provider will use a default name. /// -/// This is a more convenient way of expressing `global::tracer_provider().tracer(name, None)`. -/// -/// [`Tracer`]: crate::trace::Tracer -pub fn tracer>>(name: T) -> BoxedTracer { - tracer_provider().tracer(name.into(), None) -} - -/// Creates a named instance of [`Tracer`] with version info via the configured [`GlobalTracerProvider`] -/// -/// If the name is an empty string, the provider will use a default name. -/// If the version is an empty string, it will be used as part of instrumentation library information. +/// This is a more convenient way of expressing `global::tracer_provider().tracer(name)`. /// /// [`Tracer`]: crate::trace::Tracer -pub fn tracer_with_version>>(name: T, version: T) -> BoxedTracer { - tracer_provider().tracer(name.into(), Some(version.into())) +pub fn tracer(name: impl Into>) -> BoxedTracer { + tracer_provider().tracer(name.into()) } /// Sets the given [`TracerProvider`] instance as the current global provider. diff --git a/opentelemetry/src/sdk/export/trace/stdout.rs b/opentelemetry/src/sdk/export/trace/stdout.rs index 78e0ac08d3..2600f6d15e 100644 --- a/opentelemetry/src/sdk/export/trace/stdout.rs +++ b/opentelemetry/src/sdk/export/trace/stdout.rs @@ -100,7 +100,9 @@ where provider_builder = provider_builder.with_config(config); } let provider = provider_builder.build(); - let tracer = provider.tracer("opentelemetry", Some(env!("CARGO_PKG_VERSION"))); + + let tracer = + provider.versioned_tracer("opentelemetry", Some(env!("CARGO_PKG_VERSION")), None); let _ = global::set_tracer_provider(provider); tracer diff --git a/opentelemetry/src/sdk/propagation/composite.rs b/opentelemetry/src/sdk/propagation/composite.rs index 44b3cbdcd0..234598633a 100644 --- a/opentelemetry/src/sdk/propagation/composite.rs +++ b/opentelemetry/src/sdk/propagation/composite.rs @@ -44,7 +44,7 @@ use std::collections::HashSet; /// /// // And a given span /// let example_span = sdktrace::TracerProvider::default() -/// .tracer("example-component", None) +/// .tracer("example-component") /// .start("span-name"); /// /// // with the current context, call inject to add the headers diff --git a/opentelemetry/src/sdk/trace/provider.rs b/opentelemetry/src/sdk/trace/provider.rs index 25a07eb33a..75bc7ef175 100644 --- a/opentelemetry/src/sdk/trace/provider.rs +++ b/opentelemetry/src/sdk/trace/provider.rs @@ -78,17 +78,22 @@ impl crate::trace::TracerProvider for TracerProvider { /// This implementation of `TracerProvider` produces `Tracer` instances. type Tracer = sdk::trace::Tracer; - /// Find or create `Tracer` instance by name. - fn tracer>>(&self, name: T, version: Option) -> Self::Tracer { + /// Create a new versioned `Tracer` instance. + fn versioned_tracer( + &self, + name: impl Into>, + version: Option<&'static str>, + _schema_url: Option<&'static str>, + ) -> Self::Tracer { let name = name.into(); - let version = version.map(Into::>::into); // Use default value if name is invalid empty string let component_name = if name.is_empty() { Cow::Borrowed(DEFAULT_COMPONENT_NAME) } else { name }; - let instrumentation_lib = sdk::InstrumentationLibrary::new(component_name, version); + let instrumentation_lib = + sdk::InstrumentationLibrary::new(component_name, version.map(Into::into)); sdk::trace::Tracer::new(instrumentation_lib, Arc::downgrade(&self.inner)) } diff --git a/opentelemetry/src/sdk/trace/span.rs b/opentelemetry/src/sdk/trace/span.rs index dcb7a69bf9..741fcace2d 100644 --- a/opentelemetry/src/sdk/trace/span.rs +++ b/opentelemetry/src/sdk/trace/span.rs @@ -251,7 +251,7 @@ mod tests { fn init() -> (sdk::trace::Tracer, SpanData) { let provider = sdk::trace::TracerProvider::default(); let config = provider.config(); - let tracer = provider.tracer("opentelemetry", Some(env!("CARGO_PKG_VERSION"))); + let tracer = provider.tracer("opentelemetry"); let data = SpanData { parent_span_id: SpanId::from_u64(0), span_kind: trace::SpanKind::Internal, @@ -529,7 +529,7 @@ mod tests { let exporter = NoopSpanExporter::new(); let provider_builder = sdk::trace::TracerProvider::builder().with_simple_exporter(exporter); let provider = provider_builder.build(); - let tracer = provider.tracer("opentelemetry-test", None); + let tracer = provider.tracer("opentelemetry-test"); let mut event1 = Event::with_name("test event"); for i in 0..(DEFAULT_MAX_ATTRIBUTES_PER_EVENT * 2) { @@ -563,7 +563,7 @@ mod tests { let exporter = NoopSpanExporter::new(); let provider_builder = sdk::trace::TracerProvider::builder().with_simple_exporter(exporter); let provider = provider_builder.build(); - let tracer = provider.tracer("opentelemetry-test", None); + let tracer = provider.tracer("opentelemetry-test"); let mut link = Link::new( SpanContext::new( @@ -597,7 +597,7 @@ mod tests { let provider = sdk::trace::TracerProvider::builder() .with_simple_exporter(NoopSpanExporter::new()) .build(); - let tracer = provider.tracer("test", None); + let tracer = provider.tracer("test"); let mut span = tracer.start("test_span"); span.add_event("test_event".to_string(), vec![]); diff --git a/opentelemetry/src/sdk/trace/tracer.rs b/opentelemetry/src/sdk/trace/tracer.rs index 3d58604e95..3c2f55373f 100644 --- a/opentelemetry/src/sdk/trace/tracer.rs +++ b/opentelemetry/src/sdk/trace/tracer.rs @@ -374,7 +374,7 @@ mod tests { let tracer_provider = sdk::trace::TracerProvider::builder() .with_config(config) .build(); - let tracer = tracer_provider.tracer("test", None); + let tracer = tracer_provider.tracer("test"); let trace_state = TraceState::from_key_value(vec![("foo", "bar")]).unwrap(); let span_builder = SpanBuilder { parent_context: Context::new().with_span(TestSpan(SpanContext::new( @@ -403,7 +403,7 @@ mod tests { .build(); let context = Context::current_with_span(TestSpan(SpanContext::empty_context())); - let tracer = tracer_provider.tracer("test", None); + let tracer = tracer_provider.tracer("test"); let span = tracer.start_with_context("must_not_be_sampled", context); assert!(!span.span_context().is_sampled()); @@ -416,7 +416,7 @@ mod tests { let tracer_provider = sdk::trace::TracerProvider::builder() .with_config(config) .build(); - let tracer = tracer_provider.tracer("test", None); + let tracer = tracer_provider.tracer("test"); let _attached = Context::current_with_span(TestSpan(SpanContext::empty_context())).attach(); let span = tracer.span_builder("must_not_be_sampled").start(&tracer); diff --git a/opentelemetry/src/trace/context.rs b/opentelemetry/src/trace/context.rs index 8ed6545d0d..7043d812b5 100644 --- a/opentelemetry/src/trace/context.rs +++ b/opentelemetry/src/trace/context.rs @@ -155,7 +155,7 @@ pub trait TraceContextExt { /// assert_eq!(Context::current().span().span_context(), &SpanContext::empty_context()); /// /// let provider = sdk::trace::TracerProvider::default(); - /// provider.tracer("my-component", None).in_span("my-span", |cx| { + /// provider.tracer("my-component").in_span("my-span", |cx| { /// // Returns a reference to the current span if set /// assert_ne!(cx.span().span_context(), &SpanContext::empty_context()); /// }); diff --git a/opentelemetry/src/trace/mod.rs b/opentelemetry/src/trace/mod.rs index 4cc1e60df8..ae1209156a 100644 --- a/opentelemetry/src/trace/mod.rs +++ b/opentelemetry/src/trace/mod.rs @@ -45,7 +45,11 @@ //! let tracer_provider = global::tracer_provider(); //! //! // Get a tracer for this library -//! let tracer = tracer_provider.tracer("my_name", Some(env!("CARGO_PKG_VERSION"))); +//! let tracer = tracer_provider.versioned_tracer( +//! "my_name", +//! Some(env!("CARGO_PKG_VERSION")), +//! None +//! ); //! //! // Create spans //! let mut span = tracer.start("doing_work"); diff --git a/opentelemetry/src/trace/noop.rs b/opentelemetry/src/trace/noop.rs index b80564f27f..4189196968 100644 --- a/opentelemetry/src/trace/noop.rs +++ b/opentelemetry/src/trace/noop.rs @@ -31,7 +31,12 @@ impl trace::TracerProvider for NoopTracerProvider { type Tracer = NoopTracer; /// Returns a new `NoopTracer` instance. - fn tracer>>(&self, _name: T, _version: Option) -> Self::Tracer { + fn versioned_tracer( + &self, + _name: impl Into>, + _version: Option<&'static str>, + _schema_url: Option<&'static str>, + ) -> Self::Tracer { NoopTracer::new() } diff --git a/opentelemetry/src/trace/tracer_provider.rs b/opentelemetry/src/trace/tracer_provider.rs index 1e26b49cf7..39d08d9d53 100644 --- a/opentelemetry/src/trace/tracer_provider.rs +++ b/opentelemetry/src/trace/tracer_provider.rs @@ -6,7 +6,7 @@ pub trait TracerProvider { /// The [`Tracer`] type that this provider will return. type Tracer: Tracer; - /// Returns a new tracer with the given name and version. + /// Returns a new tracer with the given name. /// /// The `name` should be the application name or the name of the library /// providing instrumentation. If the name is empty, then an @@ -19,13 +19,52 @@ pub trait TracerProvider { /// /// let provider = global::tracer_provider(); /// - /// // App tracer - /// let tracer = provider.tracer("my_app", None); + /// // tracer used in applications/binaries + /// let tracer = provider.tracer("my_app"); /// - /// // Library tracer - /// let tracer = provider.tracer("my_library", Some(env!("CARGO_PKG_VERSION"))); + /// // tracer used in libraries/crates that optionally includes version and schema url + /// let tracer = provider.versioned_tracer( + /// "my_library", + /// Some(env!("CARGO_PKG_VERSION")), + /// Some("https://opentelemetry.io/schema/1.0.0") + /// ); /// ``` - fn tracer>>(&self, name: T, version: Option) -> Self::Tracer; + fn tracer(&self, name: impl Into>) -> Self::Tracer { + self.versioned_tracer(name, None, None) + } + + /// Returns a new versioned tracer with a given name. + /// + /// The `name` should be the application name or the name of the library + /// providing instrumentation. If the name is empty, then an + /// implementation-defined default name may be used instead. + /// + /// + /// The `` + /// + /// # Examples + /// + /// ``` + /// use opentelemetry::{global, trace::TracerProvider}; + /// + /// let provider = global::tracer_provider(); + /// + /// // tracer used in applications/binaries + /// let tracer = provider.tracer("my_app"); + /// + /// // tracer used in libraries/crates that optionally includes version and schema url + /// let tracer = provider.versioned_tracer( + /// "my_library", + /// Some(env!("CARGO_PKG_VERSION")), + /// Some("https://opentelemetry.io/schema/1.0.0") + /// ); + /// ``` + fn versioned_tracer( + &self, + name: impl Into>, + version: Option<&'static str>, + schema_url: Option<&'static str>, + ) -> Self::Tracer; /// Force flush all remaining spans in span processors and return results. fn force_flush(&self) -> Vec>;