diff --git a/opentelemetry-sdk/src/resource/builder.rs b/opentelemetry-sdk/src/resource/builder.rs new file mode 100644 index 0000000000..99848e1b37 --- /dev/null +++ b/opentelemetry-sdk/src/resource/builder.rs @@ -0,0 +1,76 @@ +use super::{Resource, ResourceDetector}; + +/// Builder to allow easy composition of a Resource +#[derive(Debug, Default)] +pub struct ResourceBuilder { + resource: Resource, +} + +impl ResourceBuilder { + /// Create ResourceBuilder with an empty [Resource]. + pub fn new_empty() -> Self { + ResourceBuilder { + resource: Resource::empty(), + } + } + + /// Create ResourceBuilder with a default [Resource]. + pub fn new_default() -> Self { + ResourceBuilder { + resource: Resource::default(), + } + } + + /// Add a single [ResourceDetector] to your resource. + pub fn with_detector(self, detector: Box) -> Self { + self.with_detectors(vec![detector]) + } + + /// Add multiple [ResourceDetector] to your resource. + pub fn with_detectors(mut self, detectors: Vec>) -> Self { + self.resource = self.resource.merge(&Resource::from_detectors(detectors)); + self + } + + /// Create a [Resource] with the options provided to the [ResourceBuilder]. + pub fn build(self) -> Resource { + self.resource + } +} + +#[cfg(test)] +mod tests { + use opentelemetry::KeyValue; + + use crate::resource::EnvResourceDetector; + + use super::*; + + #[test] + fn detect_resource() { + temp_env::with_vars( + [ + ( + "OTEL_RESOURCE_ATTRIBUTES", + Some("key=value, k = v , a= x, a=z"), + ), + ("IRRELEVANT", Some("20200810")), + ], + || { + let resource = Resource::builder() + .with_detector(Box::new(EnvResourceDetector::new())) + .build(); + + assert_eq!( + resource, + Resource::new(vec![ + KeyValue::new("key", "value"), + KeyValue::new("k", "v"), + KeyValue::new("a", "x"), + KeyValue::new("a", "z"), + ]) + ) + }, + ) + } +} diff --git a/opentelemetry-sdk/src/resource/mod.rs b/opentelemetry-sdk/src/resource/mod.rs index 1b46279085..45613c61f4 100644 --- a/opentelemetry-sdk/src/resource/mod.rs +++ b/opentelemetry-sdk/src/resource/mod.rs @@ -20,6 +20,7 @@ //! //! The OS and Process resource detectors are packaged separately in the //! [`opentelemetry-resource-detector` crate](https://github.com/open-telemetry/opentelemetry-rust-contrib/tree/main/opentelemetry-resource-detectors). +mod builder; mod env; mod telemetry; @@ -36,6 +37,8 @@ use std::collections::{hash_map, HashMap}; use std::ops::Deref; use std::sync::Arc; +use self::builder::ResourceBuilder; + /// Inner structure of `Resource` holding the actual data. /// This structure is designed to be shared among `Resource` instances via `Arc`. #[derive(Debug, Clone, PartialEq)] @@ -62,6 +65,22 @@ impl Default for Resource { } impl Resource { + /// Creates a Builder that allows you to configure multiple aspects of the Resource. + /// + /// If you want to start from a [Resource::default()] see [Resource::builder_default()]. + /// + /// Starts with a [Resource::empty()]. + pub fn builder() -> ResourceBuilder { + ResourceBuilder::new_empty() + } + + /// Creates a Builder that allows you to configure multiple aspects of the Resource. + /// + /// Starts with a [Resource::default()]. + pub fn builder_default() -> ResourceBuilder { + ResourceBuilder::new_empty() + } + /// Creates an empty resource. /// This is the basic constructor that initializes a resource with no attributes and no schema URL. pub fn empty() -> Self {