@@ -293,6 +293,7 @@ impl opentelemetry::trace::TracerProvider for SdkTracerProvider {
293293pub struct TracerProviderBuilder {
294294 processors : Vec < Box < dyn SpanProcessor > > ,
295295 config : crate :: trace:: Config ,
296+ resource : Option < Resource > ,
296297}
297298
298299impl TracerProviderBuilder {
@@ -410,18 +411,28 @@ impl TracerProviderBuilder {
410411 ///
411412 /// By default, if this option is not used, the default [Resource] will be used.
412413 ///
414+ /// *Note*: Calls to this method are additive, each call merges the provided
415+ /// resource with the previous one.
416+ ///
413417 /// [Tracer]: opentelemetry::trace::Tracer
414418 pub fn with_resource ( self , resource : Resource ) -> Self {
415- TracerProviderBuilder {
416- config : self . config . with_resource ( resource) ,
417- ..self
418- }
419+ let resource = match self . resource {
420+ Some ( existing) => Some ( existing. merge ( & resource) ) ,
421+ None => Some ( resource) ,
422+ } ;
423+
424+ TracerProviderBuilder { resource, ..self }
419425 }
420426
421427 /// Create a new provider from this configuration.
422428 pub fn build ( self ) -> SdkTracerProvider {
423429 let mut config = self . config ;
424430
431+ // Now, we can update the config with the resource.
432+ if let Some ( resource) = self . resource {
433+ config = config. with_resource ( resource) ;
434+ } ;
435+
425436 // Standard config will contain an owned [`Resource`] (either sdk default or use supplied)
426437 // we can optimize the common case with a static ref to avoid cloning the underlying
427438 // resource data for each span.
@@ -462,8 +473,8 @@ mod tests {
462473 SERVICE_NAME , TELEMETRY_SDK_LANGUAGE , TELEMETRY_SDK_NAME , TELEMETRY_SDK_VERSION ,
463474 } ;
464475 use crate :: trace:: provider:: TracerProviderInner ;
465- use crate :: trace:: SpanData ;
466476 use crate :: trace:: { Config , Span , SpanProcessor } ;
477+ use crate :: trace:: { SdkTracerProvider , SpanData } ;
467478 use crate :: Resource ;
468479 use opentelemetry:: trace:: { Tracer , TracerProvider } ;
469480 use opentelemetry:: { Context , Key , KeyValue , Value } ;
@@ -730,6 +741,38 @@ mod tests {
730741 assert ! ( test_tracer_1. provider( ) . is_shutdown( ) ) ;
731742 }
732743
744+ #[ test]
745+ fn with_resource_multiple_calls_ensure_additive ( ) {
746+ let resource = SdkTracerProvider :: builder ( )
747+ . with_resource ( Resource :: new ( vec ! [ KeyValue :: new( "key1" , "value1" ) ] ) )
748+ . with_resource ( Resource :: new ( vec ! [ KeyValue :: new( "key2" , "value2" ) ] ) )
749+ . with_resource (
750+ Resource :: builder_empty ( )
751+ . with_schema_url ( vec ! [ ] , "http://example.com" )
752+ . build ( ) ,
753+ )
754+ . with_resource ( Resource :: new ( vec ! [ KeyValue :: new( "key3" , "value3" ) ] ) )
755+ . build ( )
756+ . inner
757+ . config
758+ . resource
759+ . to_owned ( ) ;
760+
761+ assert_eq ! (
762+ resource. get( & Key :: from_static_str( "key1" ) ) ,
763+ Some ( Value :: from( "value1" ) )
764+ ) ;
765+ assert_eq ! (
766+ resource. get( & Key :: from_static_str( "key2" ) ) ,
767+ Some ( Value :: from( "value2" ) )
768+ ) ;
769+ assert_eq ! (
770+ resource. get( & Key :: from_static_str( "key3" ) ) ,
771+ Some ( Value :: from( "value3" ) )
772+ ) ;
773+ assert_eq ! ( resource. schema_url( ) , Some ( "http://example.com" ) ) ;
774+ }
775+
733776 #[ derive( Debug ) ]
734777 struct CountingShutdownProcessor {
735778 shutdown_count : Arc < AtomicU32 > ,
0 commit comments