11using System ;
2+ using System . Diagnostics . CodeAnalysis ;
23using Amazon . XRay . Recorder . Core ;
34using Amazon . XRay . Recorder . Core . Internal . Emitters ;
45using Amazon . XRay . Recorder . Core . Internal . Entities ;
@@ -172,7 +173,7 @@ private static bool IsSerializationError(Exception e)
172173
173174 var message = e . Message ?? string . Empty ;
174175 var stackTrace = e . StackTrace ?? string . Empty ;
175- var typeName = e . GetType ( ) . Name ?? string . Empty ;
176+ var typeName = e . GetType ( ) . Name ;
176177
177178 return message . Contains ( "LitJson" ) ||
178179 message . Contains ( "JsonMapper" ) ||
@@ -461,20 +462,18 @@ private static object SanitizeCollectionTypes(object value, Type type, int depth
461462 }
462463
463464 /// <summary>
464- /// Sanitizes array values.
465+ /// Sanitizes array values
465466 /// </summary>
466467 /// <param name="array">The array to sanitize</param>
467468 /// <param name="type">The array type</param>
468469 /// <param name="depth">Current recursion depth</param>
469470 /// <returns>Sanitized array</returns>
470471 private static object SanitizeArray ( Array array , Type type , int depth )
471472 {
472- var elementType = type . GetElementType ( ) ;
473-
474- // If it's an array of safe types and all elements are actually safe, return original array
475- if ( elementType != null && IsSafeType ( elementType ) && IsArrayElementsSafe ( array ) )
473+ // Check if it's a known safe array type
474+ if ( IsKnownSafeArrayType ( type ) )
476475 {
477- return array ; // Return original array
476+ return array ; // Return original array for known safe types
478477 }
479478
480479 // Otherwise, sanitize to object array
@@ -487,6 +486,20 @@ private static object SanitizeArray(Array array, Type type, int depth)
487486 return sanitizedArray ;
488487 }
489488
489+ /// <summary>
490+ /// Checks if an array type is known to be safe without reflection
491+ /// </summary>
492+ private static bool IsKnownSafeArrayType ( Type type )
493+ {
494+ return type == typeof ( string [ ] ) ||
495+ type == typeof ( int [ ] ) ||
496+ type == typeof ( long [ ] ) ||
497+ type == typeof ( double [ ] ) ||
498+ type == typeof ( float [ ] ) ||
499+ type == typeof ( bool [ ] ) ||
500+ type == typeof ( decimal [ ] ) ;
501+ }
502+
490503 /// <summary>
491504 /// Checks if all elements in an array are safe types.
492505 /// </summary>
@@ -540,63 +553,28 @@ private static object SanitizeEnumerable(System.Collections.IEnumerable enumerab
540553 }
541554
542555 /// <summary>
543- /// Sanitizes complex objects by converting them to dictionaries .
556+ /// Sanitizes complex objects by converting them to safe string representation .
544557 /// </summary>
545558 /// <param name="value">The object to sanitize</param>
546559 /// <param name="type">The object type</param>
547560 /// <param name="depth">Current recursion depth</param>
548- /// <returns>Sanitized dictionary representation</returns>
561+ /// <returns>Sanitized string representation</returns>
549562 private static object SanitizeComplexObject ( object value , Type type , int depth )
550563 {
551564 try
552565 {
553- var properties =
554- type . GetProperties ( System . Reflection . BindingFlags . Public | System . Reflection . BindingFlags . Instance ) ;
555- var sanitizedObject = new System . Collections . Generic . Dictionary < string , object > ( ) ;
556-
557- foreach ( var prop in properties )
558- {
559- var propertyValue = GetPropertyValueSafely ( prop , value , depth ) ;
560- if ( propertyValue != null )
561- {
562- sanitizedObject [ prop . Name ] = propertyValue ;
563- }
564- }
565-
566- return sanitizedObject ;
566+ // For Native AOT compatibility, we avoid reflection and convert to string
567+ // This ensures the object can be serialized without issues
568+ return $ "[{ type . Name } ] { value . ToString ( ) } ";
567569 }
568570 catch ( Exception ex )
569571 {
570- // If all else fails, convert to string
571- return $ "[Object conversion failed: { ex . Message } ] { value . ToString ( ) } ";
572+ // If all else fails, return a safe fallback
573+ return $ "[Object conversion failed: { ex . Message } ]";
572574 }
573575 }
574576
575- /// <summary>
576- /// Safely gets a property value from an object.
577- /// </summary>
578- /// <param name="prop">The property to read</param>
579- /// <param name="value">The object to read from</param>
580- /// <param name="depth">Current recursion depth</param>
581- /// <returns>The property value or null if it can't be read</returns>
582- private static object GetPropertyValueSafely ( System . Reflection . PropertyInfo prop , object value , int depth )
583- {
584- try
585- {
586- if ( prop . CanRead && prop . GetIndexParameters ( ) . Length == 0 ) // Skip indexers
587- {
588- var propValue = prop . GetValue ( value ) ;
589- return SanitizeValueRecursive ( propValue , depth + 1 ) ;
590- }
591- }
592- catch ( Exception ex )
593- {
594- // If we can't read a property, record the error
595- return $ "[Error reading property: { ex . Message } ]";
596- }
597577
598- return null ;
599- }
600578
601579 /// <summary>
602580 /// Determines if a type is safe for X-Ray without sanitization
@@ -632,38 +610,40 @@ private static bool NeedsTypeSanitization(Type type)
632610 type == typeof ( Guid ) || type . IsEnum )
633611 return true ;
634612
635- // Check for nullable versions of problematic types
636- if ( type . IsGenericType && type . GetGenericTypeDefinition ( ) == typeof ( Nullable < > ) )
637- {
638- var underlyingType = Nullable . GetUnderlyingType ( type ) ;
639- return underlyingType != null && NeedsTypeSanitization ( underlyingType ) ;
640- }
613+ // Check for specific nullable types without reflection
614+ if ( IsKnownNullableProblematicType ( type ) )
615+ return true ;
641616
642617 return false ;
643618 }
644619
620+ /// <summary>
621+ /// Checks for known nullable problematic types without using reflection
622+ /// </summary>
623+ private static bool IsKnownNullableProblematicType ( Type type )
624+ {
625+ return type == typeof ( IntPtr ? ) || type == typeof ( UIntPtr ? ) ||
626+ type == typeof ( uint ? ) || type == typeof ( ulong ? ) ||
627+ type == typeof ( ushort ? ) || type == typeof ( byte ? ) || type == typeof ( sbyte ? ) ||
628+ type == typeof ( DateTime ? ) || type == typeof ( TimeSpan ? ) ||
629+ type == typeof ( Guid ? ) ;
630+ }
631+
645632 /// <summary>
646633 /// Safely sanitizes the current entity to prevent JSON serialization errors.
647- /// This method uses reflection to access and sanitize all data in the entity.
648634 /// </summary>
635+ [ UnconditionalSuppressMessage ( "Trimming" , "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code" , Justification = "Entity properties are preserved by X-Ray SDK" ) ]
649636 private void SanitizeCurrentEntitySafely ( )
650637 {
651638 try
652639 {
653640 var entity = _awsxRayRecorder ? . TraceContext ? . GetEntity ( ) ;
654641 if ( entity == null ) return ;
655642
656- // Sanitize Metadata
643+ // Sanitize known entity properties without reflection
657644 SanitizeEntityMetadata ( entity ) ;
658-
659- // Sanitize Annotations
660645 SanitizeEntityAnnotations ( entity ) ;
661-
662- // Sanitize HTTP information
663646 SanitizeEntityHttpInformation ( entity ) ;
664-
665- // Sanitize any other properties that might contain problematic data
666- SanitizeEntityOtherProperties ( entity ) ;
667647 }
668648 catch ( Exception ex )
669649 {
@@ -675,6 +655,7 @@ private void SanitizeCurrentEntitySafely()
675655 /// <summary>
676656 /// Sanitizes the metadata in an entity
677657 /// </summary>
658+ [ UnconditionalSuppressMessage ( "Trimming" , "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code" , Justification = "Entity.Metadata property is preserved by X-Ray SDK" ) ]
678659 private static void SanitizeEntityMetadata ( Entity entity )
679660 {
680661 try
@@ -719,6 +700,7 @@ private static void SanitizeEntityMetadata(Entity entity)
719700 /// <summary>
720701 /// Sanitizes the annotations in an entity
721702 /// </summary>
703+ [ UnconditionalSuppressMessage ( "Trimming" , "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code" , Justification = "Entity.Annotations property is preserved by X-Ray SDK" ) ]
722704 private static void SanitizeEntityAnnotations ( Entity entity )
723705 {
724706 try
@@ -748,6 +730,7 @@ private static void SanitizeEntityAnnotations(Entity entity)
748730 /// <summary>
749731 /// Sanitizes HTTP information in an entity
750732 /// </summary>
733+ [ UnconditionalSuppressMessage ( "Trimming" , "IL2026:Members annotated with 'RequiresUnreferencedCodeAttribute' require dynamic access otherwise can break functionality when trimming application code" , Justification = "Entity.Http property is preserved by X-Ray SDK" ) ]
751734 private static void SanitizeEntityHttpInformation ( Entity entity )
752735 {
753736 try
@@ -774,63 +757,5 @@ private static void SanitizeEntityHttpInformation(Entity entity)
774757 }
775758 }
776759
777- /// <summary>
778- /// Sanitizes other properties in an entity that might contain problematic data
779- /// </summary>
780- private static void SanitizeEntityOtherProperties ( Entity entity )
781- {
782- try
783- {
784- // Get all properties of the entity
785- var properties = entity . GetType ( )
786- . GetProperties ( System . Reflection . BindingFlags . Public | System . Reflection . BindingFlags . Instance ) ;
787-
788- foreach ( var property in properties )
789- {
790- try
791- {
792- // Skip properties we've already handled
793- if ( property . Name == "Metadata" || property . Name == "Annotations" || property . Name == "Http" )
794- continue ;
795-
796- // Skip properties that can't be written to
797- if ( ! property . CanWrite || ! property . CanRead )
798- continue ;
799-
800- // Skip indexers
801- if ( property . GetIndexParameters ( ) . Length > 0 )
802- continue ;
803-
804- var value = property . GetValue ( entity ) ;
805- if ( value == null )
806- continue ;
807-
808- var valueType = value . GetType ( ) ;
809760
810- // Only sanitize properties that might contain problematic data
811- if ( NeedsTypeSanitization ( valueType ) ||
812- valueType . IsClass && valueType != typeof ( string ) &&
813- ! valueType . IsPrimitive && ! valueType . IsEnum )
814- {
815- var sanitizedValue = SanitizeValueForMetadata ( value ) ;
816-
817- // Only update if the sanitized value is different and compatible
818- if ( ! ReferenceEquals ( value , sanitizedValue ) &&
819- ( sanitizedValue == null || property . PropertyType . IsInstanceOfType ( sanitizedValue ) ) )
820- {
821- property . SetValue ( entity , sanitizedValue ) ;
822- }
823- }
824- }
825- catch ( Exception ex )
826- {
827- Console . WriteLine ( $ "Warning: Failed to sanitize property { property . Name } : { ex . Message } ") ;
828- }
829- }
830- }
831- catch ( Exception ex )
832- {
833- Console . WriteLine ( $ "Warning: Other properties sanitization failed: { ex . Message } ") ;
834- }
835- }
836761}
0 commit comments