@@ -709,13 +709,81 @@ fn omits_scope_metadata_when_final_value_is_unsupported_across_trace_projections
709709
710710 let diagnostics = runtime_diagnostics. snapshot ( ) ;
711711 let diagnostic = diagnostics
712- . get ( "otel.metadata_promotion_value_unsupported" )
712+ . get ( "otel.metadata_promotion_value_unsupported.nv.source " )
713713 . expect ( "unsupported final metadata diagnostic" ) ;
714714 assert_eq ! ( diagnostic. count, 1 ) ;
715715 assert ! ( diagnostic. message. contains( "nv.source" ) ) ;
716716 }
717717}
718718
719+ #[ test]
720+ fn reports_each_unsupported_metadata_key_with_a_deterministic_diagnostic_code ( ) {
721+ let ( provider, exporter) = make_provider ( ) ;
722+ let runtime_diagnostics = SignalRuntimeDiagnostics :: new ( None ) ;
723+ let mut processor =
724+ OtelEventProcessor :: new_with_mark_projection_and_exclusions_and_mappings_and_runtime_diagnostics (
725+ provider,
726+ "unsupported-metadata-promotion-keys-test" . into ( ) ,
727+ OpenTelemetryType :: Full ,
728+ MarkProjection :: default ( ) ,
729+ default_mark_exclude_names ( ) ,
730+ Vec :: new ( ) ,
731+ vec ! [ "tenant." . to_string( ) ] ,
732+ runtime_diagnostics. clone ( ) ,
733+ ) ;
734+ let uuid = Uuid :: now_v7 ( ) ;
735+ let unsupported_metadata = json ! ( {
736+ "tenant.plan" : { "name" : "enterprise" } ,
737+ "tenant.flags" : null,
738+ "tenant.tags" : [ [ "nested" ] ] ,
739+ "tenant.mixed" : [ 1 , "string" ] ,
740+ } ) ;
741+
742+ processor. process ( & make_start_event_with_metadata (
743+ uuid,
744+ None ,
745+ "unsupported-metadata-promotion-keys-scope" ,
746+ unsupported_metadata. clone ( ) ,
747+ ) ) ;
748+ processor. process ( & make_end_event_with_metadata (
749+ uuid,
750+ None ,
751+ "unsupported-metadata-promotion-keys-scope" ,
752+ ScopeType :: Agent ,
753+ unsupported_metadata,
754+ ) ) ;
755+ processor. force_flush ( ) . unwrap ( ) ;
756+
757+ let spans = exporter. get_finished_spans ( ) . unwrap ( ) ;
758+ assert_eq ! ( spans. len( ) , 1 ) ;
759+ let span_attributes = attr_map ( & spans[ 0 ] . attributes ) ;
760+ for key in [ "tenant.flags" , "tenant.mixed" , "tenant.plan" , "tenant.tags" ] {
761+ assert ! ( !span_attributes. contains_key( key) ) ;
762+ }
763+
764+ let diagnostics = runtime_diagnostics. snapshot ( ) ;
765+ let expected_keys = [ "tenant.flags" , "tenant.mixed" , "tenant.plan" , "tenant.tags" ] ;
766+ assert_eq ! (
767+ diagnostics
768+ . entries( )
769+ . iter( )
770+ . map( |diagnostic| diagnostic. code. as_str( ) )
771+ . collect:: <Vec <_>>( ) ,
772+ expected_keys
773+ . iter( )
774+ . map( |key| format!( "otel.metadata_promotion_value_unsupported.{key}" ) )
775+ . collect:: <Vec <_>>( )
776+ ) ;
777+ for key in expected_keys {
778+ let code = format ! ( "otel.metadata_promotion_value_unsupported.{key}" ) ;
779+ let diagnostic = diagnostics
780+ . get ( & code)
781+ . expect ( "metadata-key-specific promotion diagnostic" ) ;
782+ assert_eq ! ( diagnostic. count, 2 ) ;
783+ assert ! ( diagnostic. message. contains( key) ) ;
784+ }
785+ }
786+
719787#[ test]
720788fn promotes_start_only_scope_metadata_across_trace_projections ( ) {
721789 for otel_type in [
0 commit comments