Skip to content

Commit 46ea570

Browse files
committed
feat: reduce the public api for resource builder
1 parent f7c780d commit 46ea570

File tree

2 files changed

+145
-189
lines changed

2 files changed

+145
-189
lines changed

opentelemetry-sdk/src/resource/builder.rs

Lines changed: 0 additions & 174 deletions
This file was deleted.

opentelemetry-sdk/src/resource/mod.rs

Lines changed: 145 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,12 @@
2020
//!
2121
//! The OS and Process resource detectors are packaged separately in the
2222
//! [`opentelemetry-resource-detector` crate](https://github.com/open-telemetry/opentelemetry-rust-contrib/tree/main/opentelemetry-resource-detectors).
23-
mod builder;
2423
mod env;
2524
mod telemetry;
2625

2726
mod attributes;
2827
pub(crate) use attributes::*;
2928

30-
pub use builder::ResourceBuilder;
3129
pub use env::EnvResourceDetector;
3230
pub use env::SdkProvidedResourceDetector;
3331
pub use telemetry::TelemetryResourceDetector;
@@ -63,27 +61,23 @@ impl Default for Resource {
6361
}
6462
}
6563

66-
impl From<ResourceBuilder> for Resource {
67-
fn from(value: ResourceBuilder) -> Self {
68-
value.build()
69-
}
70-
}
71-
7264
impl Resource {
7365
/// Creates a Builder that allows you to configure multiple aspects of the Resource.
7466
///
75-
/// If you want to start from a [Resource::default()] see [Resource::builder_default()].
76-
///
77-
/// Starts with a [Resource::empty()].
67+
/// Starts with a [Resource::default()].
7868
pub fn builder() -> ResourceBuilder {
79-
ResourceBuilder::new()
69+
ResourceBuilder {
70+
resource: Resource::default(),
71+
}
8072
}
8173

8274
/// Creates a Builder that allows you to configure multiple aspects of the Resource.
8375
///
84-
/// Starts with a [Resource::default()].
85-
pub fn builder_default() -> ResourceBuilder {
86-
ResourceBuilder::default()
76+
/// Starts with a [Resource::empty()].
77+
pub fn builder_empty() -> ResourceBuilder {
78+
ResourceBuilder {
79+
resource: Resource::empty(),
80+
}
8781
}
8882

8983
/// Creates an empty resource.
@@ -286,6 +280,65 @@ pub trait ResourceDetector {
286280
fn detect(&self) -> Resource;
287281
}
288282

283+
/// Builder for [Resource]
284+
#[derive(Debug)]
285+
pub struct ResourceBuilder {
286+
resource: Resource,
287+
}
288+
289+
impl ResourceBuilder {
290+
/// Add a single [ResourceDetector] to your resource.
291+
pub fn with_detector(self, detector: Box<dyn ResourceDetector>) -> Self {
292+
self.with_detectors(vec![detector])
293+
}
294+
295+
/// Add multiple [ResourceDetector] to your resource.
296+
pub fn with_detectors(mut self, detectors: Vec<Box<dyn ResourceDetector>>) -> Self {
297+
self.resource = self.resource.merge(&Resource::from_detectors(detectors));
298+
self
299+
}
300+
301+
/// Add a [KeyValue] to the resource.
302+
pub fn with_attribute(self, kv: KeyValue) -> Self {
303+
self.with_attributes(vec![kv])
304+
}
305+
306+
/// Add multiple [KeyValue]s to the resource.
307+
pub fn with_attributes<T: IntoIterator<Item = KeyValue>>(mut self, kvs: T) -> Self {
308+
self.resource = self.resource.merge(&Resource::new(kvs));
309+
self
310+
}
311+
312+
/// Add `service.name` resource attribute.
313+
pub fn with_service_name(self, name: impl Into<Value>) -> Self {
314+
self.with_attribute(KeyValue::new(SERVICE_NAME, name.into()))
315+
}
316+
317+
/// This will merge the provided `schema_url` with the current state of the Resource being built. It
318+
/// will use the following rules to determine which `schema_url` should be used.
319+
///
320+
/// ### [Schema url]
321+
/// Schema url is determined by the following rules, in order:
322+
/// 1. If the current builder resource doesn't have a `schema_url`, the provided `schema_url` will be used.
323+
/// 2. If the current builder resource has a `schema_url`, and the provided `schema_url` is different from the builder resource, `schema_url` will be empty.
324+
/// 3. If the provided `schema_url` is the same as the current builder resource, it will be used.
325+
///
326+
/// [Schema url]: https://github.com/open-telemetry/opentelemetry-specification/blob/v1.9.0/specification/schemas/overview.md#schema-url
327+
pub fn with_schema_url<KV, S>(mut self, attributes: KV, schema_url: S) -> Self
328+
where
329+
KV: IntoIterator<Item = KeyValue>,
330+
S: Into<Cow<'static, str>>,
331+
{
332+
self.resource = Resource::from_schema_url(attributes, schema_url).merge(&self.resource);
333+
self
334+
}
335+
336+
/// Create a [Resource] with the options provided to the [ResourceBuilder].
337+
pub fn build(self) -> Resource {
338+
self.resource
339+
}
340+
}
341+
289342
#[cfg(test)]
290343
mod tests {
291344
use rstest::rstest;
@@ -411,4 +464,81 @@ mod tests {
411464
},
412465
)
413466
}
467+
468+
#[rstest]
469+
#[case(Some("http://schema/a"), Some("http://schema/b"), None)]
470+
#[case(None, Some("http://schema/b"), Some("http://schema/b"))]
471+
#[case(
472+
Some("http://schema/a"),
473+
Some("http://schema/a"),
474+
Some("http://schema/a")
475+
)]
476+
fn builder_with_schema_url(
477+
#[case] schema_url_a: Option<&'static str>,
478+
#[case] schema_url_b: Option<&'static str>,
479+
#[case] expected_schema_url: Option<&'static str>,
480+
) {
481+
let base_builder = if let Some(url) = schema_url_a {
482+
ResourceBuilder {
483+
resource: Resource::from_schema_url(vec![KeyValue::new("key", "")], url),
484+
}
485+
} else {
486+
ResourceBuilder {
487+
resource: Resource::empty(),
488+
}
489+
};
490+
491+
let resource = base_builder
492+
.with_schema_url(
493+
vec![KeyValue::new("key", "")],
494+
schema_url_b.expect("should always be Some for this test"),
495+
)
496+
.build();
497+
498+
assert_eq!(
499+
resource.schema_url().map(|s| s as &str),
500+
expected_schema_url,
501+
"Merging schema_url_a {:?} with schema_url_b {:?} did not yield expected result {:?}",
502+
schema_url_a,
503+
schema_url_b,
504+
expected_schema_url
505+
);
506+
}
507+
508+
#[test]
509+
fn builder_detect_resource() {
510+
temp_env::with_vars(
511+
[
512+
(
513+
"OTEL_RESOURCE_ATTRIBUTES",
514+
Some("key=value, k = v , a= x, a=z"),
515+
),
516+
("IRRELEVANT", Some("20200810")),
517+
],
518+
|| {
519+
let resource = Resource::builder_empty()
520+
.with_detector(Box::new(EnvResourceDetector::new()))
521+
.with_service_name("testing_service")
522+
.with_attribute(KeyValue::new("test1", "test_value"))
523+
.with_attributes(vec![
524+
KeyValue::new("test1", "test_value1"),
525+
KeyValue::new("test2", "test_value2"),
526+
])
527+
.build();
528+
529+
assert_eq!(
530+
resource,
531+
Resource::new(vec![
532+
KeyValue::new("key", "value"),
533+
KeyValue::new("test1", "test_value1"),
534+
KeyValue::new("test2", "test_value2"),
535+
KeyValue::new(SERVICE_NAME, "testing_service"),
536+
KeyValue::new("k", "v"),
537+
KeyValue::new("a", "x"),
538+
KeyValue::new("a", "z"),
539+
])
540+
)
541+
},
542+
)
543+
}
414544
}

0 commit comments

Comments
 (0)