From aced50d17e8e52d80d12efd99dc0d268fe5fd864 Mon Sep 17 00:00:00 2001 From: Henrique <999396+hjgraca@users.noreply.github.com> Date: Wed, 2 Oct 2024 15:54:46 +0100 Subject: [PATCH 1/3] Remove TypeInfoResolver from non AOT mode. --- .../Utils/RuntimeFeatureWrapper.cs | 29 +++++++++++ .../PowertoolsLoggingSerializer.cs | 19 +++++-- .../PowertoolsLoggingSerializerTests.cs | 51 ++++++++++++++++++- 3 files changed, 94 insertions(+), 5 deletions(-) create mode 100644 libraries/src/AWS.Lambda.Powertools.Common/Utils/RuntimeFeatureWrapper.cs diff --git a/libraries/src/AWS.Lambda.Powertools.Common/Utils/RuntimeFeatureWrapper.cs b/libraries/src/AWS.Lambda.Powertools.Common/Utils/RuntimeFeatureWrapper.cs new file mode 100644 index 00000000..9c12eeef --- /dev/null +++ b/libraries/src/AWS.Lambda.Powertools.Common/Utils/RuntimeFeatureWrapper.cs @@ -0,0 +1,29 @@ +using System; +using System.Runtime.CompilerServices; + +namespace AWS.Lambda.Powertools.Common.Utils; + +/// +/// Wrapper for RuntimeFeature +/// +public static class RuntimeFeatureWrapper +{ + private static Func _isDynamicCodeSupportedFunc = () => RuntimeFeature.IsDynamicCodeSupported; + + /// + /// Check to see if IsDynamicCodeSupported + /// + public static bool IsDynamicCodeSupported => _isDynamicCodeSupportedFunc(); + +// For testing purposes + internal static void SetIsDynamicCodeSupported(bool value) + { + _isDynamicCodeSupportedFunc = () => value; + } + +// To reset after tests + internal static void Reset() + { + _isDynamicCodeSupportedFunc = () => RuntimeFeature.IsDynamicCodeSupported; + } +} \ No newline at end of file diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Serializers/PowertoolsLoggingSerializer.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Serializers/PowertoolsLoggingSerializer.cs index ef6085d9..54958829 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/Serializers/PowertoolsLoggingSerializer.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/Serializers/PowertoolsLoggingSerializer.cs @@ -23,6 +23,7 @@ using System.Text.Json.Serialization.Metadata; using Amazon.Lambda.Serialization.SystemTextJson; using AWS.Lambda.Powertools.Common; +using AWS.Lambda.Powertools.Common.Utils; using AWS.Lambda.Powertools.Logging.Internal.Converters; using Microsoft.Extensions.Logging; @@ -69,6 +70,13 @@ internal static string Serialize(object value, Type inputType) var options = GetSerializerOptions(); return JsonSerializer.Serialize(value, options); #else + if (RuntimeFeatureWrapper.IsDynamicCodeSupported) + { + var options = GetSerializerOptions(); +#pragma warning disable + return JsonSerializer.Serialize(value, options); + } + var typeInfo = GetTypeInfo(inputType); if (typeInfo == null) { @@ -154,10 +162,15 @@ private static JsonSerializerOptions BuildJsonSerializerOptions() _jsonOptions.PropertyNameCaseInsensitive = true; #if NET8_0_OR_GREATER - _jsonOptions.TypeInfoResolverChain.Add(PowertoolsLoggingSerializationContext.Default); - foreach (var context in AdditionalContexts) + + // Only add TypeInfoResolver if AOT mode + if (!RuntimeFeatureWrapper.IsDynamicCodeSupported) { - _jsonOptions.TypeInfoResolverChain.Add(context); + _jsonOptions.TypeInfoResolverChain.Add(PowertoolsLoggingSerializationContext.Default); + foreach (var context in AdditionalContexts) + { + _jsonOptions.TypeInfoResolverChain.Add(context); + } } #endif return _jsonOptions; diff --git a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Serializers/PowertoolsLoggingSerializerTests.cs b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Serializers/PowertoolsLoggingSerializerTests.cs index e26053ac..8c539036 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Serializers/PowertoolsLoggingSerializerTests.cs +++ b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Serializers/PowertoolsLoggingSerializerTests.cs @@ -15,10 +15,12 @@ using System; using System.Collections.Generic; +using System.Runtime.CompilerServices; using System.Text.Encodings.Web; using System.Text.Json; using System.Text.Json.Serialization; using Amazon.Lambda.Serialization.SystemTextJson; +using AWS.Lambda.Powertools.Common.Utils; using AWS.Lambda.Powertools.Logging.Internal; using AWS.Lambda.Powertools.Logging.Internal.Converters; using AWS.Lambda.Powertools.Logging.Serializers; @@ -48,8 +50,10 @@ public void SerializerOptions_ShouldNotBeNull() [Fact] public void SerializerOptions_ShouldHaveCorrectDefaultSettings() { - var options = PowertoolsLoggingSerializer.GetSerializerOptions(); - + RuntimeFeatureWrapper.SetIsDynamicCodeSupported(false); + + var options = PowertoolsLoggingSerializer.GetSerializerOptions(); + Assert.Collection(options.Converters, converter => Assert.IsType(converter), converter => Assert.IsType(converter), @@ -70,6 +74,33 @@ public void SerializerOptions_ShouldHaveCorrectDefaultSettings() resolver => Assert.IsType(resolver)); #endif } + + [Fact] + public void SerializerOptions_ShouldHaveCorrectDefaultSettings_WhenDynamic() + { + RuntimeFeatureWrapper.SetIsDynamicCodeSupported(true); + + var options = PowertoolsLoggingSerializer.GetSerializerOptions(); + + Assert.Collection(options.Converters, + converter => Assert.IsType(converter), + converter => Assert.IsType(converter), + converter => Assert.IsType(converter), + converter => Assert.IsType(converter), + converter => Assert.IsType(converter), + converter => Assert.IsType(converter), +#if NET8_0_OR_GREATER + converter => Assert.IsType>(converter)); +#elif NET6_0 + converter => Assert.IsType(converter)); +#endif + + Assert.Equal(JavaScriptEncoder.UnsafeRelaxedJsonEscaping, options.Encoder); + +#if NET8_0_OR_GREATER + Assert.Empty(options.TypeInfoResolverChain); +#endif + } [Fact] public void SerializerOptions_ShouldUseSnakeCaseByDefault() @@ -143,6 +174,7 @@ public void Serialize_UnknownType_ThrowsInvalidOperationException() // Arrange var unknownObject = new UnknownType(); + RuntimeFeatureWrapper.SetIsDynamicCodeSupported(false); // Act & Assert var exception = Assert.Throws(() => PowertoolsLoggingSerializer.Serialize(unknownObject, typeof(UnknownType))); @@ -150,6 +182,20 @@ public void Serialize_UnknownType_ThrowsInvalidOperationException() Assert.Contains("is not known to the serializer", exception.Message); Assert.Contains(typeof(UnknownType).ToString(), exception.Message); } + + [Fact] + public void Serialize_UnknownType_Should_Not_Throw_InvalidOperationException_When_Dynamic() + { + // Arrange + var unknownObject = new UnknownType{ SomeProperty = "Hello"}; + + RuntimeFeatureWrapper.SetIsDynamicCodeSupported(true); + // Act & Assert + var expected = + PowertoolsLoggingSerializer.Serialize(unknownObject, typeof(UnknownType)); + + Assert.Equal("{\"some_property\":\"Hello\"}", expected); + } private class UnknownType { @@ -175,5 +221,6 @@ public void Dispose() PowertoolsLoggingSerializer.ClearContext(); #endif PowertoolsLoggingSerializer.ClearOptions(); + RuntimeFeatureWrapper.Reset(); } } \ No newline at end of file From e7a0a568a58eeb7e535cfc9dd04264f5f6a5dcbd Mon Sep 17 00:00:00 2001 From: Henrique Graca <999396+hjgraca@users.noreply.github.com> Date: Wed, 2 Oct 2024 16:01:12 +0100 Subject: [PATCH 2/3] Update bug_report.yml --- .github/ISSUE_TEMPLATE/bug_report.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index a98a2dae..780ff58a 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -59,6 +59,8 @@ body: label: AWS Lambda function runtime options: - dotnet6 + - dotnet8 + - dotnet8 (AOT) validations: required: true - type: textarea From 83ff555371ef144854f82df7ed20557db4747b8b Mon Sep 17 00:00:00 2001 From: Henrique Graca <999396+hjgraca@users.noreply.github.com> Date: Wed, 2 Oct 2024 16:03:20 +0100 Subject: [PATCH 3/3] Update version for release --- version.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/version.json b/version.json index bad6b158..1a74e63c 100644 --- a/version.json +++ b/version.json @@ -1,12 +1,12 @@ { "Core": { - "Logging": "1.6.0", + "Logging": "1.6.1", "Metrics": "1.7.1", "Tracing": "1.5.1" }, "Utilities": { "Parameters": "1.3.0", "Idempotency": "1.2.2", - "BatchProcessing": "1.1.2" + "BatchProcessing": "1.2.0" } }