Skip to content

chore: Aot support for Logging and Metrics (WIP) #556

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions libraries/AWS.Lambda.Powertools.sln
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AWS.Lambda.Powertools.Param
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AWS.Lambda.Powertools.Parameters.Tests", "tests\AWS.Lambda.Powertools.Parameters.Tests\AWS.Lambda.Powertools.Parameters.Tests.csproj", "{386A9769-59BF-4BE3-99D4-A9603E300729}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AWS.Lambda.Powertools.AotCompatibility", "tests\AWS.Lambda.Powertools.AotCompatibility\AWS.Lambda.Powertools.AotCompatibility.csproj", "{2B782D22-675D-42D4-A041-90A27275A403}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -216,6 +218,18 @@ Global
{386A9769-59BF-4BE3-99D4-A9603E300729}.Release|x64.Build.0 = Release|Any CPU
{386A9769-59BF-4BE3-99D4-A9603E300729}.Release|x86.ActiveCfg = Release|Any CPU
{386A9769-59BF-4BE3-99D4-A9603E300729}.Release|x86.Build.0 = Release|Any CPU
{2B782D22-675D-42D4-A041-90A27275A403}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2B782D22-675D-42D4-A041-90A27275A403}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2B782D22-675D-42D4-A041-90A27275A403}.Debug|x64.ActiveCfg = Debug|Any CPU
{2B782D22-675D-42D4-A041-90A27275A403}.Debug|x64.Build.0 = Debug|Any CPU
{2B782D22-675D-42D4-A041-90A27275A403}.Debug|x86.ActiveCfg = Debug|Any CPU
{2B782D22-675D-42D4-A041-90A27275A403}.Debug|x86.Build.0 = Debug|Any CPU
{2B782D22-675D-42D4-A041-90A27275A403}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2B782D22-675D-42D4-A041-90A27275A403}.Release|Any CPU.Build.0 = Release|Any CPU
{2B782D22-675D-42D4-A041-90A27275A403}.Release|x64.ActiveCfg = Release|Any CPU
{2B782D22-675D-42D4-A041-90A27275A403}.Release|x64.Build.0 = Release|Any CPU
{2B782D22-675D-42D4-A041-90A27275A403}.Release|x86.ActiveCfg = Release|Any CPU
{2B782D22-675D-42D4-A041-90A27275A403}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection

GlobalSection(NestedProjects) = preSolution
Expand All @@ -233,5 +247,6 @@ Global
{F8B4100F-4014-4A1E-8130-D281453B79ED} = {73C9B1E5-3893-47E8-B373-17E5F5D7E6F5}
{12B940EF-A5D3-459D-BD36-A603834D1F7D} = {1CFF5568-8486-475F-81F6-06105C437528}
{3E1D77BD-70AF-4767-B00A-4A321D5AB2C3} = {1CFF5568-8486-475F-81F6-06105C437528}
{2B782D22-675D-42D4-A041-90A27275A403} = {1CFF5568-8486-475F-81F6-06105C437528}
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@
<PackageReference Include="Amazon.Lambda.KinesisEvents" />
<PackageReference Include="Amazon.Lambda.SQSEvents" />
<ProjectReference Include="..\AWS.Lambda.Powertools.Common\AWS.Lambda.Powertools.Common.csproj" PrivateAssets="all" />
<PackageReference Include="Amazon.Lambda.Core" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
<ItemGroup>
<!-- Package versions are Centrally managed in Directory.Packages.props file -->
<!-- More info https://learn.microsoft.com/en-us/nuget/consume-packages/central-package-management -->
<PackageReference Include="Amazon.Lambda.Core" />
<PackageReference Include="AspectInjector"/>
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
*
* http://aws.amazon.com/apache2.0
*
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
Expand All @@ -15,6 +15,7 @@

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
Expand All @@ -32,19 +33,19 @@ public class UniversalWrapperAspect
/// <summary>
/// The delegate cache
/// </summary>
private static readonly Dictionary<MethodBase, Handler> _delegateCache = new();
private static readonly Dictionary<MethodBase, Handler> DelegateCache = new();

/// <summary>
/// The asynchronous generic handler
/// </summary>
private static readonly MethodInfo _asyncGenericHandler =
private static readonly MethodInfo AsyncGenericHandler =
typeof(UniversalWrapperAttribute).GetMethod(nameof(UniversalWrapperAttribute.WrapAsync),
BindingFlags.NonPublic | BindingFlags.Instance);

/// <summary>
/// The synchronize generic handler
/// </summary>
private static readonly MethodInfo _syncGenericHandler =
private static readonly MethodInfo SyncGenericHandler =
typeof(UniversalWrapperAttribute).GetMethod(nameof(UniversalWrapperAttribute.WrapSync),
BindingFlags.NonPublic | BindingFlags.Instance);

Expand Down Expand Up @@ -93,6 +94,7 @@ public object Handle(
/// <param name="returnType">Type of the return.</param>
/// <param name="wrappers">The wrappers.</param>
/// <returns>Handler.</returns>
[UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "<Pending>")]
private static Handler CreateMethodHandler(Type returnType, IEnumerable<UniversalWrapperAttribute> wrappers)
{
var targetParam = Expression.Parameter(typeof(Func<object[], object>), "orig");
Expand All @@ -106,13 +108,13 @@ private static Handler CreateMethodHandler(Type returnType, IEnumerable<Universa
? returnType.GenericTypeArguments[0]
: Type.GetType("System.Threading.Tasks.VoidTaskResult");
returnType = typeof(Task<>).MakeGenericType(taskType);
wrapperMethod = _asyncGenericHandler.MakeGenericMethod(taskType);
wrapperMethod = AsyncGenericHandler.MakeGenericMethod(taskType);
}
else
{
if (returnType == typeof(void))
returnType = typeof(object);
wrapperMethod = _syncGenericHandler.MakeGenericMethod(returnType);
wrapperMethod = SyncGenericHandler.MakeGenericMethod(returnType);
}

var converArgs = Expression.Parameter(typeof(object[]), "args");
Expand All @@ -127,9 +129,9 @@ private static Handler CreateMethodHandler(Type returnType, IEnumerable<Universa
argsParam);
}

var orig_args = Expression.Parameter(typeof(object[]), "orig_args");
var handler = Expression.Lambda<Handler>(Expression.Convert(Expression.Invoke(next, orig_args), typeof(object)),
targetParam, orig_args, eventArgsParam);
var origArgs = Expression.Parameter(typeof(object[]), "orig_args");
var handler = Expression.Lambda<Handler>(Expression.Convert(Expression.Invoke(next, origArgs), typeof(object)),
targetParam, origArgs, eventArgsParam);

var handlerCompiled = handler.Compile();

Expand All @@ -146,14 +148,14 @@ private static Handler CreateMethodHandler(Type returnType, IEnumerable<Universa
private static Handler GetMethodHandler(MethodBase method, Type returnType,
IEnumerable<UniversalWrapperAttribute> wrappers)
{
if (!_delegateCache.TryGetValue(method, out var handler))
lock (method)
{
if (!_delegateCache.TryGetValue(method, out handler))
_delegateCache[method] = handler = CreateMethodHandler(returnType, wrappers);
}

return handler;
lock (method)
{
if (!DelegateCache.TryGetValue(method, out var handler))
if (!DelegateCache.TryGetValue(method, out handler))
DelegateCache[method] = handler = CreateMethodHandler(returnType, wrappers);

return handler;
}
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace AWS.Lambda.Powertools.Common;

[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Dictionary<string, object>))]
[JsonSerializable(typeof(bool))]
[JsonSerializable(typeof(string))]
[JsonSerializable(typeof(Int32))]
[JsonSerializable(typeof(Double))]
[JsonSerializable(typeof(DateOnly))]
[JsonSerializable(typeof(TimeOnly))]
[JsonSerializable(typeof(InvalidOperationException))]
[JsonSerializable(typeof(Exception))]
[JsonSerializable(typeof(IEnumerable<object>))]
[JsonSerializable(typeof(Dictionary<string, string>))]
[JsonSerializable(typeof(IEnumerable<string>))]
[JsonSerializable(typeof(Dictionary<string, int>))]
[JsonSerializable(typeof(Byte[]))]
[JsonSerializable(typeof(MemoryStream))]
public partial class PowertoolsSourceGenerationContext : JsonSerializerContext
{
// make public
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
<ItemGroup>
<!-- Package versions are Centrally managed in Directory.Packages.props file -->
<!-- More info https://learn.microsoft.com/en-us/nuget/consume-packages/central-package-management -->
<PackageReference Include="Amazon.Lambda.APIGatewayEvents" />
<PackageReference Include="Amazon.Lambda.ApplicationLoadBalancerEvents" />
<PackageReference Include="Amazon.Lambda.Core" />
<PackageReference Include="Microsoft.Extensions.Logging" />
<ProjectReference Include="..\AWS.Lambda.Powertools.Common\AWS.Lambda.Powertools.Common.csproj" PrivateAssets="All" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@
*/

using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using AWS.Lambda.Powertools.Common;
using System.Collections.Generic;

namespace AWS.Lambda.Powertools.Logging.Internal.Converters;

Expand Down Expand Up @@ -63,7 +66,7 @@ public override void Write(Utf8JsonWriter writer, Exception value, JsonSerialize

if (options.DefaultIgnoreCondition == JsonIgnoreCondition.WhenWritingNull)
properties = properties.Where(prop => prop.Value != null);

var props = properties.ToArray();
if (!props.Any())
return;
Expand All @@ -86,6 +89,7 @@ public override void Write(Utf8JsonWriter writer, Exception value, JsonSerialize
break;
default:
writer.WritePropertyName(ApplyPropertyNamingPolicy(prop.Name, options));

JsonSerializer.Serialize(writer, prop.Value, options);
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,21 @@
*/

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.ExceptionServices;
using System.Text.Json;
using System.Text.Json.Serialization;
using Amazon.Lambda.APIGatewayEvents;
using Amazon.Lambda.ApplicationLoadBalancerEvents;
using AWS.Lambda.Powertools.Common;
using AWS.Lambda.Powertools.Logging.Internal.Converters;
using Microsoft.Extensions.Logging;

namespace AWS.Lambda.Powertools.Logging.Internal;


/// <summary>
/// Class LoggingAspectHandler.
/// Implements the <see cref="IMethodAspectHandler" />
Expand Down Expand Up @@ -283,6 +287,9 @@ private static JsonSerializerOptions BuildJsonSerializerOptions()
var jsonOptions = new JsonSerializerOptions
{
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
#if NET8_0_OR_GREATER
TypeInfoResolver = PowertoolsSourceGenerationContext.Default
#endif
};
jsonOptions.Converters.Add(new ByteArrayConverter());
jsonOptions.Converters.Add(new ExceptionConverter());
Expand Down Expand Up @@ -319,7 +326,15 @@ private void CaptureCorrelationId(object eventArg)
try
{
var correlationId = string.Empty;

#if NET8_0_OR_GREATER

JsonSerializerOptions.TypeInfoResolver = PowertoolsSourceGenerationContext2.Default;
var jsonDoc = JsonDocument.Parse(JsonSerializer.Serialize(eventArg,eventArg.GetType(), JsonSerializerOptions));
// var jsonDoc = JsonDocument.Parse(JsonSerializer.Serialize(eventArg, PowertoolsSourceGenerationContext2.Default.ApplicationLoadBalancerRequest));
#else
var jsonDoc = JsonDocument.Parse(JsonSerializer.Serialize(eventArg, JsonSerializerOptions));
#endif
var element = jsonDoc.RootElement;

for (var i = 0; i < correlationIdPaths.Length; i++)
Expand Down Expand Up @@ -394,4 +409,14 @@ internal static void ResetForTest()
Logger.LoggerProvider = null;
Logger.RemoveAllKeys();
}
}
}

#if NET8_0_OR_GREATER
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(ApplicationLoadBalancerRequest))]
[JsonSerializable(typeof(APIGatewayProxyRequest))]
public partial class PowertoolsSourceGenerationContext2 : PowertoolsSourceGenerationContext
{
// make public
}
#endif
Loading