@@ -616,7 +616,8 @@ fn load_otel_receiver(otel_dir: &Path) -> Result<serde_yaml::Value, Error> {
616616 Ok ( serde_yaml:: Value :: Mapping ( receiver_section) )
617617}
618618
619- /// Replace the `otlp_config.receiver` subtree in the Datadog schema with the resolved OTel subtree.
619+ /// Merge the resolved OTel receiver subtree into the Datadog schema's `otlp_config.receiver` while
620+ /// honoring default values not native to OTel.
620621fn patch_receiver ( datadog_schema : & mut serde_yaml:: Value , otel_receiver : serde_yaml:: Value ) -> Result < ( ) , Error > {
621622 let Some ( otlp_config) = datadog_schema
622623 . get_mut ( "properties" )
@@ -629,10 +630,52 @@ fn patch_receiver(datadog_schema: &mut serde_yaml::Value, otel_receiver: serde_y
629630 return Ok ( ( ) ) ;
630631 } ;
631632
632- * receiver = otel_receiver;
633+ let datadog_receiver = std:: mem:: take ( receiver) ;
634+ let mut merged = otel_receiver;
635+ merge_receiver_node ( & mut merged, & datadog_receiver) ;
636+ * receiver = merged;
633637 Ok ( ( ) )
634638}
635639
640+ /// Recursively overlay Datadog-specific metadata from the core schema onto the resolved OTel node.
641+ fn merge_receiver_node ( otel : & mut serde_yaml:: Value , datadog : & serde_yaml:: Value ) {
642+ let Some ( otel_map) = otel. as_mapping_mut ( ) else { return } ;
643+ let Some ( datadog_map) = datadog. as_mapping ( ) else {
644+ return ;
645+ } ;
646+
647+ // Overlay all Datadog metadata fields onto the OTel node, except `properties`
648+ // which is merged recursively to preserve OTel's additional keys.
649+ for ( key, val) in datadog_map. iter ( ) {
650+ if key. as_str ( ) == Some ( "properties" ) {
651+ continue ;
652+ }
653+ otel_map. insert ( key. clone ( ) , val. clone ( ) ) ;
654+ }
655+
656+ // Recursively merge `properties` containers.
657+ if let ( Some ( otel_props) , Some ( datadog_props) ) = (
658+ otel_map. get_mut ( "properties" ) . and_then ( |v| v. as_mapping_mut ( ) ) ,
659+ datadog_map. get ( "properties" ) . and_then ( |v| v. as_mapping ( ) ) ,
660+ ) {
661+ // Merge overlapping OTEL properties with corresponding Datadog properties.
662+ let otel_keys: Vec < serde_yaml:: Value > = otel_props. keys ( ) . cloned ( ) . collect ( ) ;
663+ for key in & otel_keys {
664+ if let Some ( datadog_val) = datadog_props. get ( key) {
665+ if let Some ( otel_val) = otel_props. get_mut ( key) {
666+ merge_receiver_node ( otel_val, datadog_val) ;
667+ }
668+ }
669+ }
670+ // Add Datadog-only properties that don't exist in OTEL.
671+ for ( key, val) in datadog_props. iter ( ) {
672+ if !otel_props. contains_key ( key) {
673+ otel_props. insert ( key. clone ( ) , val. clone ( ) ) ;
674+ }
675+ }
676+ }
677+ }
678+
636679/// Resolve OTel schema references into a flat tree.
637680fn resolve_otel_refs (
638681 value : & mut serde_yaml:: Value , otel_dir : & Path , current_defs : & serde_yaml:: Mapping ,
0 commit comments