From 75ac1fad4a70889998010c2a7a2342ad7c2b8c89 Mon Sep 17 00:00:00 2001 From: Daniel Izquierdo Date: Wed, 14 Feb 2024 21:15:36 +0000 Subject: [PATCH 01/10] Use a builder pattern for loggers and tracers --- opentelemetry-appender-log/src/lib.rs | 10 +- opentelemetry-appender-tracing/src/layer.rs | 10 +- .../src/exporter/config/mod.rs | 10 +- opentelemetry-otlp/src/logs.rs | 20 ++-- opentelemetry-otlp/src/span.rs | 22 ++-- opentelemetry-sdk/src/logs/log_emitter.rs | 19 ++- opentelemetry-sdk/src/logs/mod.rs | 43 ++++++- .../src/metrics/meter_provider.rs | 14 ++- opentelemetry-sdk/src/trace/mod.rs | 36 ++++++ opentelemetry-sdk/src/trace/provider.rs | 19 ++- opentelemetry-zipkin/src/exporter/mod.rs | 24 ++-- opentelemetry/CHANGELOG.md | 4 + opentelemetry/src/common.rs | 101 +++++++++++++++- opentelemetry/src/global/mod.rs | 10 +- opentelemetry/src/lib.rs | 5 +- opentelemetry/src/logs/logger.rs | 92 +++++++++++++-- opentelemetry/src/trace/mod.rs | 10 +- opentelemetry/src/trace/tracer_provider.rs | 108 ++++++++++++++---- 18 files changed, 436 insertions(+), 121 deletions(-) diff --git a/opentelemetry-appender-log/src/lib.rs b/opentelemetry-appender-log/src/lib.rs index 66f58feb22..c6692dc29c 100644 --- a/opentelemetry-appender-log/src/lib.rs +++ b/opentelemetry-appender-log/src/lib.rs @@ -49,12 +49,10 @@ where { pub fn new(provider: &P) -> Self { OpenTelemetryLogBridge { - logger: provider.versioned_logger( - "opentelemetry-log-appender", - Some(Cow::Borrowed(env!("CARGO_PKG_VERSION"))), - None, - None, - ), + logger: provider + .logger_builder("opentelemetry-log-appender") + .with_version(Cow::Borrowed(env!("CARGO_PKG_VERSION"))) + .build(), _phantom: Default::default(), } } diff --git a/opentelemetry-appender-tracing/src/layer.rs b/opentelemetry-appender-tracing/src/layer.rs index 107a82a737..ef2a691dcc 100644 --- a/opentelemetry-appender-tracing/src/layer.rs +++ b/opentelemetry-appender-tracing/src/layer.rs @@ -138,12 +138,10 @@ where { pub fn new(provider: &P) -> Self { OpenTelemetryTracingBridge { - logger: provider.versioned_logger( - INSTRUMENTATION_LIBRARY_NAME, - Some(Cow::Borrowed(env!("CARGO_PKG_VERSION"))), - None, - None, - ), + logger: provider + .logger_builder(INSTRUMENTATION_LIBRARY_NAME) + .with_version(Cow::Borrowed(env!("CARGO_PKG_VERSION"))) + .build(), _phantom: Default::default(), } } diff --git a/opentelemetry-jaeger/src/exporter/config/mod.rs b/opentelemetry-jaeger/src/exporter/config/mod.rs index 3ee1a65f0c..93218867af 100644 --- a/opentelemetry-jaeger/src/exporter/config/mod.rs +++ b/opentelemetry-jaeger/src/exporter/config/mod.rs @@ -85,13 +85,13 @@ fn build_config_and_process( pub(crate) fn install_tracer_provider_and_get_tracer( tracer_provider: TracerProvider, ) -> Result { - let tracer = opentelemetry::trace::TracerProvider::versioned_tracer( + let tracer = opentelemetry::trace::TracerProvider::tracer_builder( &tracer_provider, "opentelemetry-jaeger", - Some(env!("CARGO_PKG_VERSION")), - Some(semcov::SCHEMA_URL), - None, - ); + ) + .with_version(env!("CARGO_PKG_VERSION")) + .with_schema_url(semcov::SCHEMA_URL) + .build(); let _ = global::set_tracer_provider(tracer_provider); Ok(tracer) } diff --git a/opentelemetry-otlp/src/logs.rs b/opentelemetry-otlp/src/logs.rs index a9ec267d0c..cc3cc0364d 100644 --- a/opentelemetry-otlp/src/logs.rs +++ b/opentelemetry-otlp/src/logs.rs @@ -183,12 +183,10 @@ fn build_simple_with_exporter( provider_builder = provider_builder.with_config(config); } let provider = provider_builder.build(); - let logger = provider.versioned_logger( - Cow::Borrowed("opentelemetry-otlp"), - Some(Cow::Borrowed(env!("CARGO_PKG_VERSION"))), - None, - None, - ); + let logger = provider + .logger_builder(Cow::Borrowed("opentelemetry-otlp")) + .with_version(Cow::Borrowed(env!("CARGO_PKG_VERSION"))) + .build(); let _ = global::set_logger_provider(provider); logger } @@ -209,12 +207,10 @@ fn build_batch_with_exporter( provider_builder = provider_builder.with_config(config); } let provider = provider_builder.build(); - let logger = provider.versioned_logger( - Cow::Borrowed("opentelemetry-otlp"), - Some(Cow::Borrowed(env!("CARGO_PKG_VERSION"))), - None, - None, - ); + let logger = provider + .logger_builder(Cow::Borrowed("opentelemetry-otlp")) + .with_version(Cow::Borrowed(env!("CARGO_PKG_VERSION"))) + .build(); let _ = global::set_logger_provider(provider); logger } diff --git a/opentelemetry-otlp/src/span.rs b/opentelemetry-otlp/src/span.rs index 76383f2f04..2c66b1f72f 100644 --- a/opentelemetry-otlp/src/span.rs +++ b/opentelemetry-otlp/src/span.rs @@ -140,12 +140,11 @@ fn build_simple_with_exporter( provider_builder = provider_builder.with_config(config); } let provider = provider_builder.build(); - let tracer = provider.versioned_tracer( - "opentelemetry-otlp", - Some(env!("CARGO_PKG_VERSION")), - Some(SCHEMA_URL), - None, - ); + let tracer = provider + .tracer_builder("opentelemetry-otlp") + .with_version(env!("CARGO_PKG_VERSION")) + .with_schema_url(SCHEMA_URL) + .build(); let _ = global::set_tracer_provider(provider); tracer } @@ -166,12 +165,11 @@ fn build_batch_with_exporter( provider_builder = provider_builder.with_config(config); } let provider = provider_builder.build(); - let tracer = provider.versioned_tracer( - "opentelemetry-otlp", - Some(env!("CARGO_PKG_VERSION")), - Some(SCHEMA_URL), - None, - ); + let tracer = provider + .tracer_builder("opentelemetry-otlp") + .with_version(env!("CARGO_PKG_VERSION")) + .with_schema_url(SCHEMA_URL) + .build(); let _ = global::set_tracer_provider(provider); tracer } diff --git a/opentelemetry-sdk/src/logs/log_emitter.rs b/opentelemetry-sdk/src/logs/log_emitter.rs index 475cf72f77..562b6339c4 100644 --- a/opentelemetry-sdk/src/logs/log_emitter.rs +++ b/opentelemetry-sdk/src/logs/log_emitter.rs @@ -43,12 +43,19 @@ impl opentelemetry::logs::LoggerProvider for LoggerProvider { name }; - self.library_logger(Arc::new(InstrumentationLibrary::new( - component_name, - version, - schema_url, - attributes, - ))) + let mut builder = self.logger_builder(component_name); + + if let Some(v) = version { + builder = builder.with_version(v); + } + if let Some(s) = schema_url { + builder = builder.with_schema_url(s); + } + if let Some(a) = attributes { + builder = builder.with_attributes(a); + } + + builder.build() } fn library_logger(&self, library: Arc) -> Self::Logger { diff --git a/opentelemetry-sdk/src/logs/mod.rs b/opentelemetry-sdk/src/logs/mod.rs index 3bb815c28c..e75515c886 100644 --- a/opentelemetry-sdk/src/logs/mod.rs +++ b/opentelemetry-sdk/src/logs/mod.rs @@ -16,7 +16,7 @@ mod tests { use super::*; use crate::testing::logs::InMemoryLogsExporter; use opentelemetry::logs::{LogRecord, Logger, LoggerProvider as _, Severity}; - use opentelemetry::{logs::AnyValue, Key}; + use opentelemetry::{logs::AnyValue, Key, KeyValue}; #[test] fn logging_sdk_test() { @@ -55,4 +55,45 @@ mod tests { .expect("Attributes are expected"); assert_eq!(attributes.len(), 2); } + + #[test] + fn logger_attributes() { + let provider = LoggerProvider::builder().build(); + let logger = provider + .logger_builder("test_logger") + .with_schema_url("https://opentelemetry.io/schema/1.0.0") + .with_attributes(vec![(KeyValue::new("test_k", "test_v"))]) + .build(); + let instrumentation_library = logger.instrumentation_library(); + let attributes = &instrumentation_library.attributes; + assert_eq!( + instrumentation_library.schema_url, + Some("https://opentelemetry.io/schema/1.0.0".into()) + ); + assert_eq!(attributes.len(), 1); + assert_eq!(attributes[0].key, "test_k".into()); + assert_eq!(attributes[0].value, "test_v".into()); + } + + #[test] + #[allow(deprecated)] + fn versioned_logger_options() { + let provider = LoggerProvider::builder().build(); + let logger = provider.versioned_logger( + "test_logger", + Some("v1.2.3".into()), + Some("https://opentelemetry.io/schema/1.0.0".into()), + Some(vec![(KeyValue::new("test_k", "test_v"))]), + ); + let instrumentation_library = logger.instrumentation_library(); + let attributes = &instrumentation_library.attributes; + assert_eq!(instrumentation_library.version, Some("v1.2.3".into())); + assert_eq!( + instrumentation_library.schema_url, + Some("https://opentelemetry.io/schema/1.0.0".into()) + ); + assert_eq!(attributes.len(), 1); + assert_eq!(attributes[0].key, "test_k".into()); + assert_eq!(attributes[0].value, "test_v".into()); + } } diff --git a/opentelemetry-sdk/src/metrics/meter_provider.rs b/opentelemetry-sdk/src/metrics/meter_provider.rs index d02b3fc2bc..1133f0f1a0 100644 --- a/opentelemetry-sdk/src/metrics/meter_provider.rs +++ b/opentelemetry-sdk/src/metrics/meter_provider.rs @@ -133,7 +133,19 @@ impl MeterProvider for SdkMeterProvider { return Meter::new(Arc::new(NoopMeterCore::new())); } - let scope = Scope::new(name, version, schema_url, attributes); + let mut builder = Scope::builder(name); + + if let Some(v) = version { + builder = builder.with_version(v); + } + if let Some(s) = schema_url { + builder = builder.with_schema_url(s); + } + if let Some(a) = attributes { + builder = builder.with_attributes(a); + } + + let scope = builder.build(); if let Ok(mut meters) = self.meters.lock() { let meter = meters diff --git a/opentelemetry-sdk/src/trace/mod.rs b/opentelemetry-sdk/src/trace/mod.rs index 63354a871c..17aeb0071c 100644 --- a/opentelemetry-sdk/src/trace/mod.rs +++ b/opentelemetry-sdk/src/trace/mod.rs @@ -327,4 +327,40 @@ mod tests { ); assert_eq!(span.span_context().trace_state().get("foo"), Some("bar")); } + + #[test] + fn tracer_attributes() { + let provider = TracerProvider::builder().build(); + let tracer = provider + .tracer_builder("test_tracer") + .with_attributes(vec![KeyValue::new("test_k", "test_v")]) + .build(); + let instrumentation_library = tracer.instrumentation_library(); + let attributes = &instrumentation_library.attributes; + assert_eq!(attributes.len(), 1); + assert_eq!(attributes[0].key, "test_k".into()); + assert_eq!(attributes[0].value, "test_v".into()); + } + + #[test] + #[allow(deprecated)] + fn versioned_tracer_options() { + let provider = TracerProvider::builder().build(); + let tracer = provider.versioned_tracer( + "test_tracer", + Some(String::from("v1.2.3")), + Some(String::from("https://opentelemetry.io/schema/1.0.0")), + Some(vec![(KeyValue::new("test_k", "test_v"))]), + ); + let instrumentation_library = tracer.instrumentation_library(); + let attributes = &instrumentation_library.attributes; + assert_eq!(instrumentation_library.version, Some("v1.2.3".into())); + assert_eq!( + instrumentation_library.schema_url, + Some("https://opentelemetry.io/schema/1.0.0".into()) + ); + assert_eq!(attributes.len(), 1); + assert_eq!(attributes[0].key, "test_k".into()); + assert_eq!(attributes[0].value, "test_v".into()); + } } diff --git a/opentelemetry-sdk/src/trace/provider.rs b/opentelemetry-sdk/src/trace/provider.rs index cc0991acd7..bab9e2047d 100644 --- a/opentelemetry-sdk/src/trace/provider.rs +++ b/opentelemetry-sdk/src/trace/provider.rs @@ -136,12 +136,19 @@ impl opentelemetry::trace::TracerProvider for TracerProvider { name }; - self.library_tracer(Arc::new(InstrumentationLibrary::new( - component_name, - version, - schema_url, - attributes, - ))) + let mut builder = self.tracer_builder(component_name); + + if let Some(v) = version { + builder = builder.with_version(v); + } + if let Some(s) = schema_url { + builder = builder.with_schema_url(s); + } + if let Some(a) = attributes { + builder = builder.with_attributes(a); + } + + builder.build() } fn library_tracer(&self, library: Arc) -> Self::Tracer { diff --git a/opentelemetry-zipkin/src/exporter/mod.rs b/opentelemetry-zipkin/src/exporter/mod.rs index 1fdc602cca..0bd2d19016 100644 --- a/opentelemetry-zipkin/src/exporter/mod.rs +++ b/opentelemetry-zipkin/src/exporter/mod.rs @@ -151,13 +151,11 @@ impl ZipkinPipelineBuilder { let mut provider_builder = TracerProvider::builder().with_simple_exporter(exporter); provider_builder = provider_builder.with_config(config); let provider = provider_builder.build(); - let tracer = opentelemetry::trace::TracerProvider::versioned_tracer( - &provider, - "opentelemetry-zipkin", - Some(env!("CARGO_PKG_VERSION")), - Some(semcov::SCHEMA_URL), - None, - ); + let tracer = + opentelemetry::trace::TracerProvider::tracer_builder(&provider, "opentelemetry-zipkin") + .with_version(env!("CARGO_PKG_VERSION")) + .with_schema_url(semcov::SCHEMA_URL) + .build(); let _ = global::set_tracer_provider(provider); Ok(tracer) } @@ -170,13 +168,11 @@ impl ZipkinPipelineBuilder { let mut provider_builder = TracerProvider::builder().with_batch_exporter(exporter, runtime); provider_builder = provider_builder.with_config(config); let provider = provider_builder.build(); - let tracer = opentelemetry::trace::TracerProvider::versioned_tracer( - &provider, - "opentelemetry-zipkin", - Some(env!("CARGO_PKG_VERSION")), - Some(semcov::SCHEMA_URL), - None, - ); + let tracer = + opentelemetry::trace::TracerProvider::tracer_builder(&provider, "opentelemetry-zipkin") + .with_version(env!("CARGO_PKG_VERSION")) + .with_schema_url(semcov::SCHEMA_URL) + .build(); let _ = global::set_tracer_provider(provider); Ok(tracer) } diff --git a/opentelemetry/CHANGELOG.md b/opentelemetry/CHANGELOG.md index 235201a7eb..1680551f7d 100644 --- a/opentelemetry/CHANGELOG.md +++ b/opentelemetry/CHANGELOG.md @@ -10,6 +10,10 @@ - Remove `urlencoding` crate dependency. [#1613](https://github.com/open-telemetry/opentelemetry-rust/pull/1613) +### Changed + +- Deprecate `versioned_logger()` and `versioned_tracer()` in favor of `logger_builder()` and `tracer_builder()` respectively [1567](https://github.com/open-telemetry/opentelemetry-rust/pull/1567). + ## v0.22.0 ### Added diff --git a/opentelemetry/src/common.rs b/opentelemetry/src/common.rs index ba7338d6b2..d18d95cb40 100644 --- a/opentelemetry/src/common.rs +++ b/opentelemetry/src/common.rs @@ -449,12 +449,10 @@ pub struct InstrumentationLibrary { /// # Examples /// /// ``` - /// let library = opentelemetry::InstrumentationLibrary::new( - /// "my-crate", - /// Some(env!("CARGO_PKG_VERSION")), - /// Some("https://opentelemetry.io/schemas/1.17.0"), - /// None, - /// ); + /// let library = opentelemetry::InstrumentationLibrary::builder("my-crate"). + /// with_version(env!("CARGO_PKG_VERSION")). + /// with_schema_url("https://opentelemetry.io/schemas/1.17.0"). + /// build(); /// ``` pub version: Option>, @@ -487,7 +485,10 @@ impl hash::Hash for InstrumentationLibrary { } impl InstrumentationLibrary { + /// Deprecated, use [`InstrumentationLibrary::builder()`] + /// /// Create an new instrumentation library. + #[deprecated(since = "0.23.0", note = "Please use builder() instead")] pub fn new( name: impl Into>, version: Option>>, @@ -501,4 +502,92 @@ impl InstrumentationLibrary { attributes: attributes.unwrap_or_default(), } } + + /// Create a new builder to create an [InstrumentationLibrary] + pub fn builder(name: impl Into>) -> InstrumentationLibraryBuilder { + InstrumentationLibraryBuilder { + name: name.into(), + version: None, + schema_url: None, + attributes: None, + } + } +} + +/// Configuration options for [InstrumentationLibrary]. +/// +/// An instrumentation library is a library or crate providing instrumentation. +/// It should be named to follow any naming conventions of the instrumented +/// library (e.g. 'middleware' for a web framework). +/// +/// Apart from the name, all other fields are optional. +/// +/// See the [instrumentation libraries] spec for more information. +/// +/// [instrumentation libraries]: https://github.com/open-telemetry/opentelemetry-specification/blob/v1.9.0/specification/overview.md#instrumentation-libraries +#[derive(Debug)] +pub struct InstrumentationLibraryBuilder { + name: Cow<'static, str>, + + version: Option>, + + schema_url: Option>, + + attributes: Option>, +} + +impl InstrumentationLibraryBuilder { + /// Configure the version for the instrumentation library + /// + /// # Examples + /// + /// ``` + /// let library = opentelemetry::InstrumentationLibrary::builder("my-crate") + /// .with_version("v0.1.0") + /// .build(); + /// ``` + pub fn with_version(mut self, version: impl Into>) -> Self { + self.version = Some(version.into()); + self + } + + /// Configure the Schema URL for the instrumentation library + /// + /// # Examples + /// + /// ``` + /// let library = opentelemetry::InstrumentationLibrary::builder("my-crate") + /// .with_schema_url("https://opentelemetry.io/schemas/1.17.0") + /// .build(); + /// ``` + pub fn with_schema_url(mut self, schema_url: impl Into>) -> Self { + self.schema_url = Some(schema_url.into()); + self + } + + /// Configure the attributes for the instrumentation library + /// + /// # Examples + /// + /// ``` + /// use opentelemetry::KeyValue; + /// + /// let library = opentelemetry::InstrumentationLibrary::builder("my-crate") + /// .with_attributes(vec![KeyValue::new("k", "v")]) + /// .build(); + /// ``` + pub fn with_attributes(mut self, attributes: impl Into>) -> Self { + self.attributes = Some(attributes.into()); + self + } + + /// Create a new [InstrumentationLibrary] from this configuration + pub fn build(self) -> InstrumentationLibrary { + InstrumentationLibrary { + name: self.name, + version: self.version, + schema_url: self.schema_url, + attributes: self.attributes.unwrap_or_default(), + } + } } diff --git a/opentelemetry/src/global/mod.rs b/opentelemetry/src/global/mod.rs index 47b3688b19..a19da68e2f 100644 --- a/opentelemetry/src/global/mod.rs +++ b/opentelemetry/src/global/mod.rs @@ -56,12 +56,10 @@ //! 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_provider().versioned_tracer( -//! "my-library-name", -//! Some(env!("CARGO_PKG_VERSION")), -//! Some("https://opentelemetry.io/schemas/1.17.0"), -//! None, -//! ); +//! let tracer = global::tracer_provider().tracer_builder("my-library-name"). +//! with_version(env!("CARGO_PKG_VERSION")). +//! with_schema_url("https://opentelemetry.io/schemas/1.17.0"). +//! build(); //! //! tracer.in_span("doing_library_work", |cx| { //! // Traced library logic here... diff --git a/opentelemetry/src/lib.rs b/opentelemetry/src/lib.rs index 09c8b58770..2b61b62602 100644 --- a/opentelemetry/src/lib.rs +++ b/opentelemetry/src/lib.rs @@ -222,7 +222,10 @@ mod common; #[doc(hidden)] pub mod testing; -pub use common::{Array, ExportError, InstrumentationLibrary, Key, KeyValue, StringValue, Value}; +pub use common::{ + Array, ExportError, InstrumentationLibrary, InstrumentationLibraryBuilder, Key, KeyValue, + StringValue, Value, +}; #[cfg(feature = "metrics")] #[cfg_attr(docsrs, doc(cfg(feature = "metrics")))] diff --git a/opentelemetry/src/logs/logger.rs b/opentelemetry/src/logs/logger.rs index b9321e348d..6b7c09d7b8 100644 --- a/opentelemetry/src/logs/logger.rs +++ b/opentelemetry/src/logs/logger.rs @@ -1,6 +1,6 @@ use std::{borrow::Cow, sync::Arc}; -use crate::{logs::LogRecord, InstrumentationLibrary, KeyValue}; +use crate::{logs::LogRecord, InstrumentationLibrary, InstrumentationLibraryBuilder, KeyValue}; #[cfg(feature = "logs_level_enabled")] use super::Severity; @@ -25,11 +25,15 @@ pub trait LoggerProvider { /// The [`Logger`] type that this provider will return. type Logger: Logger; + /// Deprecated, use [`LoggerProvider::logger_builder()`] + /// /// Returns a new versioned logger 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. + /// Create a new versioned `Logger` instance. + #[deprecated(since = "0.23.0", note = "Please use logger_builder() instead")] fn versioned_logger( &self, name: impl Into>, @@ -37,9 +41,46 @@ pub trait LoggerProvider { schema_url: Option>, attributes: Option>, ) -> Self::Logger { - self.library_logger(Arc::new(InstrumentationLibrary::new( - name, version, schema_url, attributes, - ))) + let mut builder = self.logger_builder(name); + if let Some(v) = version { + builder = builder.with_version(v); + } + if let Some(s) = schema_url { + builder = builder.with_schema_url(s); + } + if let Some(a) = attributes { + builder = builder.with_attributes(a); + } + builder.build() + } + + /// Returns a new builder for creating a [`Logger`] instance + /// + /// 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. + /// + /// # Examples + /// + /// ``` + /// use opentelemetry::{global, logs::LoggerProvider}; + /// + /// let provider = global::logger_provider(); + /// + /// // logger used in applications/binaries + /// let logger = provider.logger_builder("my_app").build(); + /// + /// // logger used in libraries/crates that optionally includes version and schema url + /// let logger = provider.logger_builder("my_library") + /// .with_version(env!("CARGO_PKG_VERSION")) + /// .with_schema_url("https://opentelemetry.io/schema/1.0.0") + /// .build(); + /// ``` + fn logger_builder(&self, name: impl Into>) -> LoggerBuilder<'_, Self> { + LoggerBuilder { + provider: self, + library_builder: InstrumentationLibrary::builder(name), + } } /// Returns a new versioned logger with the given instrumentation library. @@ -53,13 +94,14 @@ pub trait LoggerProvider { /// /// // logger used in applications/binaries /// let logger = provider.logger("my_app"); + /// /// // logger used in libraries/crates that optionally includes version and schema url - /// let library = std::sync::Arc::new(InstrumentationLibrary::new( - /// env!("CARGO_PKG_NAME"), - /// Some(env!("CARGO_PKG_VERSION")), - /// Some("https://opentelemetry.io/schema/1.0.0"), - /// None, - /// )); + /// let library = std::sync::Arc::new( + /// InstrumentationLibrary::builder(env!("CARGO_PKG_NAME")) + /// .with_version(env!("CARGO_PKG_VERSION")) + /// .with_schema_url("https://opentelemetry.io/schema/1.0.0") + /// .build(), + /// ); /// let logger = provider.library_logger(library); /// ``` fn library_logger(&self, library: Arc) -> Self::Logger; @@ -70,6 +112,34 @@ pub trait LoggerProvider { /// providing instrumentation. If the name is empty, then an /// implementation-defined default name may be used instead. fn logger(&self, name: impl Into>) -> Self::Logger { - self.versioned_logger(name, None, None, None) + self.logger_builder(name).build() + } +} + +#[derive(Debug)] +pub struct LoggerBuilder<'a, T: LoggerProvider + ?Sized> { + provider: &'a T, + library_builder: InstrumentationLibraryBuilder, +} + +impl<'a, T: LoggerProvider + ?Sized> LoggerBuilder<'a, T> { + pub fn with_version(mut self, version: impl Into>) -> Self { + self.library_builder = self.library_builder.with_version(version); + self + } + + pub fn with_schema_url(mut self, schema_url: impl Into>) -> Self { + self.library_builder = self.library_builder.with_schema_url(schema_url); + self + } + + pub fn with_attributes(mut self, attributes: impl Into>) -> Self { + self.library_builder = self.library_builder.with_attributes(attributes); + self + } + + pub fn build(self) -> T::Logger { + self.provider + .library_logger(Arc::new(self.library_builder.build())) } } diff --git a/opentelemetry/src/trace/mod.rs b/opentelemetry/src/trace/mod.rs index 434c6ca85d..5e3edc3519 100644 --- a/opentelemetry/src/trace/mod.rs +++ b/opentelemetry/src/trace/mod.rs @@ -51,12 +51,10 @@ //! let tracer_provider = global::tracer_provider(); //! //! // Get a tracer for this library -//! let tracer = tracer_provider.versioned_tracer( -//! "my_name", -//! Some(env!("CARGO_PKG_VERSION")), -//! Some("https://opentelemetry.io/schemas/1.17.0"), -//! None -//! ); +//! let tracer = tracer_provider.tracer_builder("my_name"). +//! with_version(env!("CARGO_PKG_VERSION")). +//! with_schema_url("https://opentelemetry.io/schemas/1.17.0"). +//! build(); //! //! // Create spans //! let mut span = tracer.start("doing_work"); diff --git a/opentelemetry/src/trace/tracer_provider.rs b/opentelemetry/src/trace/tracer_provider.rs index 5f18264be1..3772f76f00 100644 --- a/opentelemetry/src/trace/tracer_provider.rs +++ b/opentelemetry/src/trace/tracer_provider.rs @@ -1,4 +1,4 @@ -use crate::{trace::Tracer, InstrumentationLibrary, KeyValue}; +use crate::{trace::Tracer, InstrumentationLibrary, InstrumentationLibraryBuilder, KeyValue}; use std::{borrow::Cow, sync::Arc}; /// Types that can create instances of [`Tracer`]. @@ -29,22 +29,18 @@ pub trait TracerProvider { /// 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"), - /// Some(vec![KeyValue::new("key", "value")]), - /// ); + /// let tracer = provider.tracer_builder("my_library"). + /// with_version(env!("CARGO_PKG_VERSION")). + /// with_schema_url("https://opentelemetry.io/schema/1.0.0"). + /// with_attributes(vec![KeyValue::new("key", "value")]). + /// build(); /// ``` fn tracer(&self, name: impl Into>) -> Self::Tracer { - self.versioned_tracer( - name, - None::>, - None::>, - None, - ) + self.tracer_builder(name).build() } + /// Deprecated, use [`TracerProvider::tracer_builder()`] + /// /// Returns a new versioned tracer with a given name. /// /// The `name` should be the application name or the name of the library @@ -69,6 +65,7 @@ pub trait TracerProvider { /// None, /// ); /// ``` + #[deprecated(since = "0.23.0", note = "Please use tracer_builder() instead")] fn versioned_tracer( &self, name: impl Into>, @@ -76,9 +73,47 @@ pub trait TracerProvider { schema_url: Option>>, attributes: Option>, ) -> Self::Tracer { - self.library_tracer(Arc::new(InstrumentationLibrary::new( - name, version, schema_url, attributes, - ))) + let mut builder = self.tracer_builder(name); + if let Some(v) = version { + builder = builder.with_version(v); + } + if let Some(s) = schema_url { + builder = builder.with_version(s); + } + if let Some(a) = attributes { + builder = builder.with_attributes(a); + } + + builder.build() + } + + /// Returns a new builder for creating a [`Tracer`] instance + /// + /// 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. + /// + /// # Examples + /// + /// ``` + /// use opentelemetry::{global, trace::TracerProvider}; + /// + /// let provider = global::tracer_provider(); + /// + /// // tracer used in applications/binaries + /// let tracer = provider.tracer_builder("my_app").build(); + /// + /// // tracer used in libraries/crates that optionally includes version and schema url + /// let tracer = provider.tracer_builder("my_library") + /// .with_version(env!("CARGO_PKG_VERSION")) + /// .with_schema_url("https://opentelemetry.io/schema/1.0.0") + /// .build(); + /// ``` + fn tracer_builder(&self, name: impl Into>) -> TracerBuilder<'_, Self> { + TracerBuilder { + provider: self, + library_builder: InstrumentationLibrary::builder(name), + } } /// Returns a new versioned tracer with the given instrumentation library. @@ -94,13 +129,42 @@ pub trait TracerProvider { /// let tracer = provider.tracer("my_app"); /// /// // tracer used in libraries/crates that optionally includes version and schema url - /// let library = std::sync::Arc::new(InstrumentationLibrary::new( - /// env!("CARGO_PKG_NAME"), - /// Some(env!("CARGO_PKG_VERSION")), - /// Some("https://opentelemetry.io/schema/1.0.0"), - /// None, - /// )); + /// let library = std::sync::Arc::new( + /// InstrumentationLibrary::builder(env!("CARGO_PKG_NAME")) + /// .with_version(env!("CARGO_PKG_VERSION")) + /// .with_schema_url("https://opentelemetry.io/schema/1.0.0") + /// .build(), + /// ); + /// /// let tracer = provider.library_tracer(library); /// ``` fn library_tracer(&self, library: Arc) -> Self::Tracer; } + +#[derive(Debug)] +pub struct TracerBuilder<'a, T: TracerProvider + ?Sized> { + provider: &'a T, + library_builder: InstrumentationLibraryBuilder, +} + +impl<'a, T: TracerProvider + ?Sized> TracerBuilder<'a, T> { + pub fn with_version(mut self, version: impl Into>) -> Self { + self.library_builder = self.library_builder.with_version(version); + self + } + + pub fn with_schema_url(mut self, schema_url: impl Into>) -> Self { + self.library_builder = self.library_builder.with_schema_url(schema_url); + self + } + + pub fn with_attributes(mut self, attributes: impl Into>) -> Self { + self.library_builder = self.library_builder.with_attributes(attributes); + self + } + + pub fn build(self) -> T::Tracer { + self.provider + .library_tracer(Arc::new(self.library_builder.build())) + } +} From 7adf897413a8554b8aad6390fe4b476c493bd545 Mon Sep 17 00:00:00 2001 From: Daniel Izquierdo Date: Thu, 21 Mar 2024 06:32:46 +0900 Subject: [PATCH 02/10] Move type out of parameters Co-authored-by: Zhongyang Wu --- opentelemetry/src/common.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry/src/common.rs b/opentelemetry/src/common.rs index d18d95cb40..caa4867144 100644 --- a/opentelemetry/src/common.rs +++ b/opentelemetry/src/common.rs @@ -504,7 +504,7 @@ impl InstrumentationLibrary { } /// Create a new builder to create an [InstrumentationLibrary] - pub fn builder(name: impl Into>) -> InstrumentationLibraryBuilder { + pub fn builder>>(name: T) -> InstrumentationLibraryBuilder { InstrumentationLibraryBuilder { name: name.into(), version: None, From 49633d173d49712619034538aa52b4da1ce87e9c Mon Sep 17 00:00:00 2001 From: Daniel Izquierdo Date: Sun, 31 Mar 2024 21:04:15 +0000 Subject: [PATCH 03/10] Assert library name in logger/tracer builder tests --- opentelemetry-sdk/src/logs/mod.rs | 1 + opentelemetry-sdk/src/trace/mod.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/opentelemetry-sdk/src/logs/mod.rs b/opentelemetry-sdk/src/logs/mod.rs index e75515c886..69e5064048 100644 --- a/opentelemetry-sdk/src/logs/mod.rs +++ b/opentelemetry-sdk/src/logs/mod.rs @@ -66,6 +66,7 @@ mod tests { .build(); let instrumentation_library = logger.instrumentation_library(); let attributes = &instrumentation_library.attributes; + assert_eq!(instrumentation_library.name, "test_logger"); assert_eq!( instrumentation_library.schema_url, Some("https://opentelemetry.io/schema/1.0.0".into()) diff --git a/opentelemetry-sdk/src/trace/mod.rs b/opentelemetry-sdk/src/trace/mod.rs index 17aeb0071c..ff162c472d 100644 --- a/opentelemetry-sdk/src/trace/mod.rs +++ b/opentelemetry-sdk/src/trace/mod.rs @@ -354,6 +354,7 @@ mod tests { ); let instrumentation_library = tracer.instrumentation_library(); let attributes = &instrumentation_library.attributes; + assert_eq!(instrumentation_library.name, "test_tracer"); assert_eq!(instrumentation_library.version, Some("v1.2.3".into())); assert_eq!( instrumentation_library.schema_url, From 6498a959ef37d139950ebb3c0d4244fa0b49801d Mon Sep 17 00:00:00 2001 From: Daniel Izquierdo Date: Sun, 31 Mar 2024 21:12:15 +0000 Subject: [PATCH 04/10] Make changelog more self-contained --- opentelemetry/CHANGELOG.md | 48 +++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/opentelemetry/CHANGELOG.md b/opentelemetry/CHANGELOG.md index b815301433..d2804ef7b2 100644 --- a/opentelemetry/CHANGELOG.md +++ b/opentelemetry/CHANGELOG.md @@ -13,7 +13,53 @@ ### Changed -- Deprecate `versioned_logger()` and `versioned_tracer()` in favor of `logger_builder()` and `tracer_builder()` respectively [1567](https://github.com/open-telemetry/opentelemetry-rust/pull/1567). +- Deprecate `versioned_logger()` in favor of `logger_builder()` [1567](https://github.com/open-telemetry/opentelemetry-rust/pull/1567). + +Before: + +``` +let logger = provider.versioned_logger( + "my-logger-name", + Some("X.Y.Z"), + Some("https://opentelemetry.io/schema/1.0.0"), + Some(vec![KeyValue::new("key", "value")]), +); +``` + +After: + +``` +let logger = provider + .logger_builder("my-tracername") + .with_version(env!("CARGO_PKG_VERSION")) + .with_schema_url(semcov::SCHEMA_URL) + .with_attributes(vec![KeyValue::new("key", "value")]) + .build(); +``` + +- Deprecate `versioned_tracer()` in favor of `tracer_builder()` [1567](https://github.com/open-telemetry/opentelemetry-rust/pull/1567). + +Before: + +``` +let tracer = provider.versioned_tracer( + "my-tracer-name", + Some("X.Y.Z"), + Some("https://opentelemetry.io/schema/1.0.0"), + Some(vec![KeyValue::new("key", "value")]), +); +``` + +After: + +``` +let tracer = provider + .tracer_builder("my-tracername") + .with_version(env!("CARGO_PKG_VERSION")) + .with_schema_url(semcov::SCHEMA_URL) + .with_attributes(vec![KeyValue::new("key", "value")]) + .build(); +``` ## v0.22.0 From c751ce184a77a0583a1f902c0c63155891569b1e Mon Sep 17 00:00:00 2001 From: Daniel Izquierdo Date: Sun, 7 Apr 2024 06:55:51 +0000 Subject: [PATCH 05/10] Accept IntoIterator instead of Vec --- opentelemetry/src/common.rs | 7 +++++-- opentelemetry/src/logs/logger.rs | 5 ++++- opentelemetry/src/trace/tracer_provider.rs | 5 ++++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/opentelemetry/src/common.rs b/opentelemetry/src/common.rs index caa4867144..511ca6e257 100644 --- a/opentelemetry/src/common.rs +++ b/opentelemetry/src/common.rs @@ -576,8 +576,11 @@ impl InstrumentationLibraryBuilder { /// .with_attributes(vec![KeyValue::new("k", "v")]) /// .build(); /// ``` - pub fn with_attributes(mut self, attributes: impl Into>) -> Self { - self.attributes = Some(attributes.into()); + pub fn with_attributes(mut self, attributes: I) -> Self + where + I: IntoIterator, + { + self.attributes = Some(attributes.into_iter().collect()); self } diff --git a/opentelemetry/src/logs/logger.rs b/opentelemetry/src/logs/logger.rs index 6b7c09d7b8..6d4d48f973 100644 --- a/opentelemetry/src/logs/logger.rs +++ b/opentelemetry/src/logs/logger.rs @@ -133,7 +133,10 @@ impl<'a, T: LoggerProvider + ?Sized> LoggerBuilder<'a, T> { self } - pub fn with_attributes(mut self, attributes: impl Into>) -> Self { + pub fn with_attributes(mut self, attributes: I) -> Self + where + I: IntoIterator, + { self.library_builder = self.library_builder.with_attributes(attributes); self } diff --git a/opentelemetry/src/trace/tracer_provider.rs b/opentelemetry/src/trace/tracer_provider.rs index 3772f76f00..a4a39c1bf7 100644 --- a/opentelemetry/src/trace/tracer_provider.rs +++ b/opentelemetry/src/trace/tracer_provider.rs @@ -158,7 +158,10 @@ impl<'a, T: TracerProvider + ?Sized> TracerBuilder<'a, T> { self } - pub fn with_attributes(mut self, attributes: impl Into>) -> Self { + pub fn with_attributes(mut self, attributes: I) -> Self + where + I: IntoIterator, + { self.library_builder = self.library_builder.with_attributes(attributes); self } From 57bc2f28c734fdd432b86e6feee56b7e8b55a0c6 Mon Sep 17 00:00:00 2001 From: Daniel Izquierdo Date: Fri, 19 Apr 2024 06:14:20 +0900 Subject: [PATCH 06/10] Fix logger name in changelog Co-authored-by: Cijo Thomas --- opentelemetry/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry/CHANGELOG.md b/opentelemetry/CHANGELOG.md index d2804ef7b2..ae26fdf45a 100644 --- a/opentelemetry/CHANGELOG.md +++ b/opentelemetry/CHANGELOG.md @@ -30,7 +30,7 @@ After: ``` let logger = provider - .logger_builder("my-tracername") + .logger_builder("my-logger-name") .with_version(env!("CARGO_PKG_VERSION")) .with_schema_url(semcov::SCHEMA_URL) .with_attributes(vec![KeyValue::new("key", "value")]) From 9d681c69faeaff979be13145a9f6512d103ca54c Mon Sep 17 00:00:00 2001 From: Daniel Izquierdo Date: Fri, 19 Apr 2024 06:14:51 +0900 Subject: [PATCH 07/10] Use version from env in changelog sample Co-authored-by: Cijo Thomas --- opentelemetry/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry/CHANGELOG.md b/opentelemetry/CHANGELOG.md index ae26fdf45a..eb10438980 100644 --- a/opentelemetry/CHANGELOG.md +++ b/opentelemetry/CHANGELOG.md @@ -20,7 +20,7 @@ Before: ``` let logger = provider.versioned_logger( "my-logger-name", - Some("X.Y.Z"), + Some(env!("CARGO_PKG_VERSION")), Some("https://opentelemetry.io/schema/1.0.0"), Some(vec![KeyValue::new("key", "value")]), ); From c8a618d2a4b2506326baf9bf6ce50f7702b05b36 Mon Sep 17 00:00:00 2001 From: Daniel Izquierdo Date: Fri, 19 Apr 2024 06:15:37 +0900 Subject: [PATCH 08/10] Improve tracer name in changelog sample Co-authored-by: Cijo Thomas --- opentelemetry/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry/CHANGELOG.md b/opentelemetry/CHANGELOG.md index eb10438980..473a4d1a83 100644 --- a/opentelemetry/CHANGELOG.md +++ b/opentelemetry/CHANGELOG.md @@ -54,7 +54,7 @@ After: ``` let tracer = provider - .tracer_builder("my-tracername") + .tracer_builder("my-tracer-name") .with_version(env!("CARGO_PKG_VERSION")) .with_schema_url(semcov::SCHEMA_URL) .with_attributes(vec![KeyValue::new("key", "value")]) From d64bddc6c1ae854047f74d6e24b041e1265edff9 Mon Sep 17 00:00:00 2001 From: Daniel Izquierdo Date: Fri, 19 Apr 2024 06:17:18 +0900 Subject: [PATCH 09/10] Use harcoded schema URL in changelog sample Co-authored-by: Cijo Thomas --- opentelemetry/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry/CHANGELOG.md b/opentelemetry/CHANGELOG.md index 473a4d1a83..946e400f6f 100644 --- a/opentelemetry/CHANGELOG.md +++ b/opentelemetry/CHANGELOG.md @@ -32,7 +32,7 @@ After: let logger = provider .logger_builder("my-logger-name") .with_version(env!("CARGO_PKG_VERSION")) - .with_schema_url(semcov::SCHEMA_URL) + .with_schema_url("https://opentelemetry.io/schema/1.0.0") .with_attributes(vec![KeyValue::new("key", "value")]) .build(); ``` From 8a36aede9b5663fb4bd42e495550799744811a6c Mon Sep 17 00:00:00 2001 From: Daniel Izquierdo Date: Thu, 18 Apr 2024 21:22:25 +0000 Subject: [PATCH 10/10] Make changelog tracer sample consistent with logger --- opentelemetry/CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opentelemetry/CHANGELOG.md b/opentelemetry/CHANGELOG.md index 946e400f6f..e593fcbfa8 100644 --- a/opentelemetry/CHANGELOG.md +++ b/opentelemetry/CHANGELOG.md @@ -44,7 +44,7 @@ Before: ``` let tracer = provider.versioned_tracer( "my-tracer-name", - Some("X.Y.Z"), + Some(env!("CARGO_PKG_VERSION")), Some("https://opentelemetry.io/schema/1.0.0"), Some(vec![KeyValue::new("key", "value")]), ); @@ -56,7 +56,7 @@ After: let tracer = provider .tracer_builder("my-tracer-name") .with_version(env!("CARGO_PKG_VERSION")) - .with_schema_url(semcov::SCHEMA_URL) + .with_schema_url("https://opentelemetry.io/schema/1.0.0") .with_attributes(vec![KeyValue::new("key", "value")]) .build(); ```