Skip to content

Commit a3a62af

Browse files
committed
Try using a builder pattern for all signal providers
1 parent 58ec379 commit a3a62af

File tree

7 files changed

+188
-21
lines changed

7 files changed

+188
-21
lines changed

opentelemetry-sdk/src/logs/log_emitter.rs

+12-6
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,18 @@ impl opentelemetry::logs::LoggerProvider for LoggerProvider {
4343
name
4444
};
4545

46-
self.library_logger(Arc::new(InstrumentationLibrary::new(
47-
component_name,
48-
version,
49-
schema_url,
50-
attributes,
51-
)))
46+
let mut builder = InstrumentationLibrary::builder(component_name);
47+
if let Some(v) = version {
48+
builder = builder.with_version(v);
49+
}
50+
if let Some(s) = schema_url {
51+
builder = builder.with_schema_url(s);
52+
}
53+
if let Some(a) = attributes {
54+
builder = builder.with_attributes(a);
55+
}
56+
57+
self.library_logger(Arc::new(builder.build()))
5258
}
5359

5460
fn library_logger(&self, library: Arc<InstrumentationLibrary>) -> Self::Logger {

opentelemetry-sdk/src/metrics/meter_provider.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,19 @@ impl MeterProvider for SdkMeterProvider {
125125
return Meter::new(Arc::new(NoopMeterCore::new()));
126126
}
127127

128-
let scope = Scope::new(name, version, schema_url, attributes);
128+
let mut builder = Scope::builder(name);
129+
130+
if let Some(v) = version {
131+
builder = builder.with_version(v);
132+
}
133+
if let Some(s) = schema_url {
134+
builder = builder.with_schema_url(s);
135+
}
136+
if let Some(a) = attributes {
137+
builder = builder.with_attributes(a);
138+
}
139+
140+
let scope = builder.build();
129141

130142
if let Ok(mut meters) = self.meters.lock() {
131143
let meter = meters

opentelemetry-sdk/src/trace/provider.rs

+13-6
Original file line numberDiff line numberDiff line change
@@ -136,12 +136,19 @@ impl opentelemetry::trace::TracerProvider for TracerProvider {
136136
name
137137
};
138138

139-
self.library_tracer(Arc::new(InstrumentationLibrary::new(
140-
component_name,
141-
version,
142-
schema_url,
143-
attributes,
144-
)))
139+
let mut builder = InstrumentationLibrary::builder(component_name);
140+
141+
if let Some(v) = version {
142+
builder = builder.with_version(v);
143+
}
144+
if let Some(s) = schema_url {
145+
builder = builder.with_schema_url(s);
146+
}
147+
if let Some(a) = attributes {
148+
builder = builder.with_attributes(a);
149+
}
150+
151+
self.library_tracer(Arc::new(builder.build()))
145152
}
146153

147154
fn library_tracer(&self, library: Arc<InstrumentationLibrary>) -> Self::Tracer {

opentelemetry/src/common.rs

+65
Original file line numberDiff line numberDiff line change
@@ -487,7 +487,10 @@ impl hash::Hash for InstrumentationLibrary {
487487
}
488488

489489
impl InstrumentationLibrary {
490+
/// Deprecated, use [`InstrumentationLibrary::builder()`]
491+
///
490492
/// Create an new instrumentation library.
493+
#[deprecated]
491494
pub fn new(
492495
name: impl Into<Cow<'static, str>>,
493496
version: Option<impl Into<Cow<'static, str>>>,
@@ -501,4 +504,66 @@ impl InstrumentationLibrary {
501504
attributes: attributes.unwrap_or_default(),
502505
}
503506
}
507+
508+
/// Create a new builder to create an [InstrumentationLibrary]
509+
pub fn builder(name: impl Into<Cow<'static, str>>) -> InstrumentationLibraryBuilder {
510+
InstrumentationLibraryBuilder::new(name)
511+
}
512+
}
513+
514+
/// Configuration options for [InstrumentationLibrary].
515+
///
516+
/// An instrumentation library is a library or crate providing instrumentation.
517+
/// It should be named to follow any naming conventions of the instrumented
518+
/// library (e.g. 'middleware' for a web framework).
519+
///
520+
/// Apart from the name, all other fields are optional.
521+
///
522+
/// See the [instrumentation libraries] spec for more information.
523+
///
524+
/// [instrumentation libraries]: https://github.com/open-telemetry/opentelemetry-specification/blob/v1.9.0/specification/overview.md#instrumentation-libraries
525+
#[derive(Debug)]
526+
pub struct InstrumentationLibraryBuilder {
527+
name: Cow<'static, str>,
528+
529+
version: Option<Cow<'static, str>>,
530+
531+
schema_url: Option<Cow<'static, str>>,
532+
533+
attributes: Option<Vec<KeyValue>>,
534+
}
535+
536+
impl InstrumentationLibraryBuilder {
537+
pub fn new(name: impl Into<Cow<'static, str>>) -> Self {
538+
InstrumentationLibraryBuilder {
539+
name: name.into(),
540+
version: None,
541+
schema_url: None,
542+
attributes: None,
543+
}
544+
}
545+
546+
pub fn with_version(mut self, version: impl Into<Cow<'static, str>>) -> Self {
547+
self.version = Some(version.into());
548+
self
549+
}
550+
551+
pub fn with_schema_url(mut self, schema_url: impl Into<Cow<'static, str>>) -> Self {
552+
self.schema_url = Some(schema_url.into());
553+
self
554+
}
555+
556+
pub fn with_attributes(mut self, attributes: impl Into<Vec<KeyValue>>) -> Self {
557+
self.attributes = Some(attributes.into());
558+
self
559+
}
560+
561+
pub fn build(self) -> InstrumentationLibrary {
562+
InstrumentationLibrary {
563+
name: self.name,
564+
version: self.version,
565+
schema_url: self.schema_url,
566+
attributes: self.attributes.unwrap_or_default(),
567+
}
568+
}
504569
}

opentelemetry/src/lib.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,10 @@ mod common;
222222
#[doc(hidden)]
223223
pub mod testing;
224224

225-
pub use common::{Array, ExportError, InstrumentationLibrary, Key, KeyValue, StringValue, Value};
225+
pub use common::{
226+
Array, ExportError, InstrumentationLibrary, InstrumentationLibraryBuilder, Key, KeyValue,
227+
StringValue, Value,
228+
};
226229

227230
#[cfg(feature = "metrics")]
228231
#[cfg_attr(docsrs, doc(cfg(feature = "metrics")))]

opentelemetry/src/logs/logger.rs

+11-3
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,17 @@ pub trait LoggerProvider {
3737
schema_url: Option<Cow<'static, str>>,
3838
attributes: Option<Vec<KeyValue>>,
3939
) -> Self::Logger {
40-
self.library_logger(Arc::new(InstrumentationLibrary::new(
41-
name, version, schema_url, attributes,
42-
)))
40+
let mut builder = InstrumentationLibrary::builder(name);
41+
if let Some(v) = version {
42+
builder = builder.with_version(v);
43+
}
44+
if let Some(s) = schema_url {
45+
builder = builder.with_schema_url(s);
46+
}
47+
if let Some(a) = attributes {
48+
builder = builder.with_attributes(a);
49+
}
50+
self.library_logger(Arc::new(builder.build()))
4351
}
4452

4553
/// Returns a new versioned logger with the given instrumentation library.

opentelemetry/src/trace/tracer_provider.rs

+70-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{trace::Tracer, InstrumentationLibrary, KeyValue};
1+
use crate::{trace::Tracer, InstrumentationLibrary, InstrumentationLibraryBuilder, KeyValue};
22
use std::{borrow::Cow, sync::Arc};
33

44
/// Types that can create instances of [`Tracer`].
@@ -76,9 +76,47 @@ pub trait TracerProvider {
7676
schema_url: Option<impl Into<Cow<'static, str>>>,
7777
attributes: Option<Vec<KeyValue>>,
7878
) -> Self::Tracer {
79-
self.library_tracer(Arc::new(InstrumentationLibrary::new(
80-
name, version, schema_url, attributes,
81-
)))
79+
let mut builder = InstrumentationLibrary::builder(name);
80+
if let Some(v) = version {
81+
builder = builder.with_version(v);
82+
}
83+
if let Some(s) = schema_url {
84+
builder = builder.with_version(s);
85+
}
86+
if let Some(a) = attributes {
87+
builder = builder.with_attributes(a);
88+
}
89+
90+
self.library_tracer(Arc::new(builder.build()))
91+
}
92+
93+
/// Returns a new builder for creating a [`Tracer`] instance
94+
///
95+
/// The `name` should be the application name or the name of the library
96+
/// providing instrumentation. If the name is empty, then an
97+
/// implementation-defined default name may be used instead.
98+
///
99+
/// # Examples
100+
///
101+
/// ```
102+
/// use opentelemetry::{global, trace::TracerProvider};
103+
///
104+
/// let provider = global::tracer_provider();
105+
///
106+
/// // tracer used in applications/binaries
107+
/// let tracer = provider::tracer_builder("my_app").build();
108+
///
109+
/// // tracer used in libraries/crates that optionally includes version and schema url
110+
/// let tracer = provider::tracer_builder("my_library")
111+
/// .with_version(env!("CARGO_PKG_VERSION"))
112+
/// .with_schema_url("https://opentelemetry.io/schema/1.0.0")
113+
/// .build();
114+
/// ```
115+
fn tracer_builder(&self, name: impl Into<Cow<'static, str>>) -> TracerBuilder<'_, Self> {
116+
TracerBuilder {
117+
provider: self,
118+
library_builder: InstrumentationLibraryBuilder::new(name),
119+
}
82120
}
83121

84122
/// Returns a new versioned tracer with the given instrumentation library.
@@ -104,3 +142,31 @@ pub trait TracerProvider {
104142
/// ```
105143
fn library_tracer(&self, library: Arc<InstrumentationLibrary>) -> Self::Tracer;
106144
}
145+
146+
#[derive(Debug)]
147+
pub struct TracerBuilder<'a, T: TracerProvider + ?Sized> {
148+
provider: &'a T,
149+
library_builder: InstrumentationLibraryBuilder,
150+
}
151+
152+
impl<'a, T: TracerProvider + ?Sized> TracerBuilder<'a, T> {
153+
pub fn with_version(mut self, version: impl Into<Cow<'static, str>>) -> Self {
154+
self.library_builder = self.library_builder.with_version(version);
155+
self
156+
}
157+
158+
pub fn with_schema_url(mut self, schema_url: impl Into<Cow<'static, str>>) -> Self {
159+
self.library_builder = self.library_builder.with_schema_url(schema_url);
160+
self
161+
}
162+
163+
pub fn with_attributes(mut self, attributes: impl Into<Vec<KeyValue>>) -> Self {
164+
self.library_builder = self.library_builder.with_attributes(attributes);
165+
self
166+
}
167+
168+
pub fn build(self) -> T::Tracer {
169+
self.provider
170+
.library_tracer(Arc::new(self.library_builder.build()))
171+
}
172+
}

0 commit comments

Comments
 (0)