diff --git a/libraries/AWS.Lambda.Powertools.sln b/libraries/AWS.Lambda.Powertools.sln index 62c1cec1..d3ed829b 100644 --- a/libraries/AWS.Lambda.Powertools.sln +++ b/libraries/AWS.Lambda.Powertools.sln @@ -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 @@ -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 @@ -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 diff --git a/libraries/src/AWS.Lambda.Powertools.BatchProcessing/AWS.Lambda.Powertools.BatchProcessing.csproj b/libraries/src/AWS.Lambda.Powertools.BatchProcessing/AWS.Lambda.Powertools.BatchProcessing.csproj index ed58f6f6..c766cac7 100644 --- a/libraries/src/AWS.Lambda.Powertools.BatchProcessing/AWS.Lambda.Powertools.BatchProcessing.csproj +++ b/libraries/src/AWS.Lambda.Powertools.BatchProcessing/AWS.Lambda.Powertools.BatchProcessing.csproj @@ -13,5 +13,6 @@ + diff --git a/libraries/src/AWS.Lambda.Powertools.Common/AWS.Lambda.Powertools.Common.csproj b/libraries/src/AWS.Lambda.Powertools.Common/AWS.Lambda.Powertools.Common.csproj index 9d3e6682..3084c61f 100644 --- a/libraries/src/AWS.Lambda.Powertools.Common/AWS.Lambda.Powertools.Common.csproj +++ b/libraries/src/AWS.Lambda.Powertools.Common/AWS.Lambda.Powertools.Common.csproj @@ -12,6 +12,7 @@ + diff --git a/libraries/src/AWS.Lambda.Powertools.Common/Aspects/UniversalWrapperAspect.cs b/libraries/src/AWS.Lambda.Powertools.Common/Aspects/UniversalWrapperAspect.cs index fedf4503..d076909f 100644 --- a/libraries/src/AWS.Lambda.Powertools.Common/Aspects/UniversalWrapperAspect.cs +++ b/libraries/src/AWS.Lambda.Powertools.Common/Aspects/UniversalWrapperAspect.cs @@ -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 @@ -15,6 +15,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Linq.Expressions; using System.Reflection; @@ -32,19 +33,19 @@ public class UniversalWrapperAspect /// /// The delegate cache /// - private static readonly Dictionary _delegateCache = new(); + private static readonly Dictionary DelegateCache = new(); /// /// The asynchronous generic handler /// - private static readonly MethodInfo _asyncGenericHandler = + private static readonly MethodInfo AsyncGenericHandler = typeof(UniversalWrapperAttribute).GetMethod(nameof(UniversalWrapperAttribute.WrapAsync), BindingFlags.NonPublic | BindingFlags.Instance); /// /// The synchronize generic handler /// - private static readonly MethodInfo _syncGenericHandler = + private static readonly MethodInfo SyncGenericHandler = typeof(UniversalWrapperAttribute).GetMethod(nameof(UniversalWrapperAttribute.WrapSync), BindingFlags.NonPublic | BindingFlags.Instance); @@ -93,6 +94,7 @@ public object Handle( /// Type of the return. /// The wrappers. /// Handler. + [UnconditionalSuppressMessage("AOT", "IL3050:Calling members annotated with 'RequiresDynamicCodeAttribute' may break functionality when AOT compiling.", Justification = "")] private static Handler CreateMethodHandler(Type returnType, IEnumerable wrappers) { var targetParam = Expression.Parameter(typeof(Func), "orig"); @@ -106,13 +108,13 @@ private static Handler CreateMethodHandler(Type returnType, IEnumerable).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"); @@ -127,9 +129,9 @@ private static Handler CreateMethodHandler(Type returnType, IEnumerable(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(Expression.Convert(Expression.Invoke(next, origArgs), typeof(object)), + targetParam, origArgs, eventArgsParam); var handlerCompiled = handler.Compile(); @@ -146,14 +148,14 @@ private static Handler CreateMethodHandler(Type returnType, IEnumerable 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; + } } /// diff --git a/libraries/src/AWS.Lambda.Powertools.Common/Core/PowertoolsSourceGenerationContext.cs b/libraries/src/AWS.Lambda.Powertools.Common/Core/PowertoolsSourceGenerationContext.cs new file mode 100644 index 00000000..92a7c2e1 --- /dev/null +++ b/libraries/src/AWS.Lambda.Powertools.Common/Core/PowertoolsSourceGenerationContext.cs @@ -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))] +[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))] +[JsonSerializable(typeof(Dictionary))] +[JsonSerializable(typeof(IEnumerable))] +[JsonSerializable(typeof(Dictionary))] +[JsonSerializable(typeof(Byte[]))] +[JsonSerializable(typeof(MemoryStream))] +public partial class PowertoolsSourceGenerationContext : JsonSerializerContext +{ + // make public +} \ No newline at end of file diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/AWS.Lambda.Powertools.Logging.csproj b/libraries/src/AWS.Lambda.Powertools.Logging/AWS.Lambda.Powertools.Logging.csproj index 6feca1a2..cfa87700 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/AWS.Lambda.Powertools.Logging.csproj +++ b/libraries/src/AWS.Lambda.Powertools.Logging/AWS.Lambda.Powertools.Logging.csproj @@ -11,6 +11,9 @@ + + + diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/Converters/ExceptionConverter.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/Converters/ExceptionConverter.cs index 7a85abf7..d7bf1c71 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/Converters/ExceptionConverter.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/Converters/ExceptionConverter.cs @@ -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; @@ -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; @@ -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; } diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingAspectHandler.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingAspectHandler.cs index 441cdc22..64541827 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingAspectHandler.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingAspectHandler.cs @@ -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; + /// /// Class LoggingAspectHandler. /// Implements the @@ -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()); @@ -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++) @@ -394,4 +409,14 @@ internal static void ResetForTest() Logger.LoggerProvider = null; Logger.RemoveAllKeys(); } -} \ No newline at end of file +} + +#if NET8_0_OR_GREATER +[JsonSourceGenerationOptions(WriteIndented = true)] +[JsonSerializable(typeof(ApplicationLoadBalancerRequest))] +[JsonSerializable(typeof(APIGatewayProxyRequest))] +public partial class PowertoolsSourceGenerationContext2 : PowertoolsSourceGenerationContext +{ + // make public +} +#endif \ No newline at end of file diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLambdaContext.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLambdaContext.cs new file mode 100644 index 00000000..ada35393 --- /dev/null +++ b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLambdaContext.cs @@ -0,0 +1,151 @@ +using System.Linq; +using Amazon.Lambda.Core; +using AWS.Lambda.Powertools.Common; + +namespace AWS.Lambda.Powertools.Logging.Internal; + +internal class PowertoolsLambdaContext +{ + /// + /// The AWS request ID associated with the request. + /// This is the same ID returned to the client that called invoke(). + /// This ID is reused for retries on the same request. + /// + internal string AwsRequestId { get; private set; } + + /// Name of the Lambda function that is running. + internal string FunctionName { get; private set; } + + /// + /// The Lambda function version that is executing. + /// If an alias is used to invoke the function, then this will be + /// the version the alias points to. + /// + internal string FunctionVersion { get; private set; } + + /// + /// The ARN used to invoke this function. + /// It can be function ARN or alias ARN. + /// An unqualified ARN executes the $LATEST version and aliases execute + /// the function version they are pointing to. + /// + internal string InvokedFunctionArn { get; private set; } + + /// + /// The CloudWatch log group name associated with the invoked function. + /// It can be null if the IAM user provided does not have permission for + /// CloudWatch actions. + /// + internal string LogGroupName { get; private set; } + + /// + /// The CloudWatch log stream name for this function execution. + /// It can be null if the IAM user provided does not have permission + /// for CloudWatch actions. + /// + internal string LogStreamName { get; private set; } + + /// + /// Memory limit, in MB, you configured for the Lambda function. + /// + internal int MemoryLimitInMB { get; private set; } + + /// + /// The instance + /// + internal static PowertoolsLambdaContext Instance { get; private set; } + + /// + /// Extract the lambda context from Lambda handler arguments. + /// + /// + /// The instance containing the + /// event data. + /// + internal static bool Extract(AspectEventArgs eventArgs) + { + if (Instance is not null) + return false; + + if (eventArgs?.Args is null) + return false; + + // foreach (var arg in eventArgs.Args) + // { + // if (arg is null) + // continue; + // + // var argType = arg.GetType(); + // if (!argType.Name.EndsWith("LambdaContext")) + // continue; + // + + // + // foreach (var prop in argType.GetProperties()) + // { + // if (prop.Name.Equals("AwsRequestId", StringComparison.CurrentCultureIgnoreCase)) + // { + // Instance.AwsRequestId = prop.GetValue(arg) as string; + // } + // else if (prop.Name.Equals("FunctionName", StringComparison.CurrentCultureIgnoreCase)) + // { + // Instance.FunctionName = prop.GetValue(arg) as string; + // } + // else if (prop.Name.Equals("FunctionVersion", StringComparison.CurrentCultureIgnoreCase)) + // { + // Instance.FunctionVersion = prop.GetValue(arg) as string; + // } + // else if (prop.Name.Equals("InvokedFunctionArn", StringComparison.CurrentCultureIgnoreCase)) + // { + // Instance.InvokedFunctionArn = prop.GetValue(arg) as string; + // } + // else if (prop.Name.Equals("LogGroupName", StringComparison.CurrentCultureIgnoreCase)) + // { + // Instance.LogGroupName = prop.GetValue(arg) as string; + // } + // else if (prop.Name.Equals("LogStreamName", StringComparison.CurrentCultureIgnoreCase)) + // { + // Instance.LogStreamName = prop.GetValue(arg) as string; + // } + // else if (prop.Name.Equals("MemoryLimitInMB", StringComparison.CurrentCultureIgnoreCase)) + // { + // var propVal = prop.GetValue(arg); + // if (propVal is null || !int.TryParse(propVal.ToString(), out var intVal)) continue; + // Instance.MemoryLimitInMB = intVal; + // } + // } + + // if (!IsPlacedOnRequestHandler(eventArgs.Method)) + // { + // return false; + // } + + var context = (ILambdaContext)eventArgs.Args.FirstOrDefault(x => x is ILambdaContext); + + if (context == null) + { + return false; + } + + Instance = new PowertoolsLambdaContext + { + AwsRequestId = context.AwsRequestId, + FunctionName = context.FunctionName, + FunctionVersion = context.FunctionVersion, + InvokedFunctionArn = context.InvokedFunctionArn, + LogGroupName = context.LogGroupName, + LogStreamName = context.LogStreamName, + MemoryLimitInMB = context.MemoryLimitInMB + }; + + return true; + } + + /// + /// Clear the extracted lambda context. + /// + internal static void Clear() + { + Instance = null; + } +} \ No newline at end of file diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs index e723ed22..ada89f89 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs @@ -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 @@ -15,12 +15,15 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq; using System.Text.Encodings.Web; using System.Text.Json; using AWS.Lambda.Powertools.Common; using AWS.Lambda.Powertools.Logging.Internal.Converters; using Microsoft.Extensions.Logging; +using DateOnlyConverter = AWS.Lambda.Powertools.Logging.Internal.Converters.DateOnlyConverter; +using TimeOnlyConverter = AWS.Lambda.Powertools.Logging.Internal.Converters.TimeOnlyConverter; namespace AWS.Lambda.Powertools.Logging.Internal; @@ -40,7 +43,7 @@ internal sealed class PowertoolsLogger : ILogger /// The name /// private readonly string _name; - + /// /// The current configuration /// @@ -55,7 +58,7 @@ internal sealed class PowertoolsLogger : ILogger /// The system wrapper /// private readonly ISystemWrapper _systemWrapper; - + /// /// The JsonSerializer options /// @@ -80,10 +83,10 @@ public PowertoolsLogger( { (_name, _powertoolsConfigurations, _systemWrapper, _getCurrentConfig) = (name, powertoolsConfigurations, systemWrapper, getCurrentConfig); - + _powertoolsConfigurations.SetExecutionEnvironment(this); _currentConfig = GetCurrentConfig(); - + if (_lambdaLogLevelEnabled && _logLevel < _lambdaLogLevel) { var message = @@ -148,10 +151,10 @@ internal void EndScope() private static Dictionary GetScopeKeys(TState state) { var keys = new Dictionary(); - - if (state is null) + + if (state is null) return keys; - + switch (state) { case IEnumerable> pairs: @@ -161,6 +164,7 @@ private static Dictionary GetScopeKeys(TState state) if (!string.IsNullOrWhiteSpace(key)) keys.TryAdd(key, value); } + break; } case IEnumerable> pairs: @@ -170,6 +174,7 @@ private static Dictionary GetScopeKeys(TState state) if (!string.IsNullOrWhiteSpace(key)) keys.TryAdd(key, value); } + break; } default: @@ -178,10 +183,11 @@ private static Dictionary GetScopeKeys(TState state) { keys.TryAdd(property.Name, property.GetValue(state)); } + break; } } - + return keys; } @@ -219,11 +225,48 @@ public void Log(LogLevel logLevel, EventId eventId, TState state, Except : formatter(state, exception); var logFormatter = Logger.GetFormatter(); - var logEntry = logFormatter is null? - GetLogEntry(logLevel, timestamp, message, exception) : - GetFormattedLogEntry(logLevel, timestamp, message, exception, logFormatter); + +#if NET8_0_OR_GREATER + + var logEntry = logFormatter is null + ? GetLogEntry(logLevel, timestamp, ToDictionary(message), exception) + : ToDictionary(GetFormattedLogEntry(logLevel, timestamp, ToDictionary(message), exception, logFormatter)); + + _systemWrapper.LogLine(JsonSerializer.Serialize(logEntry, JsonSerializerOptions)); + + static object ToDictionary(object values) + { + if (values is string) + { + return values; + } + var dict = new Dictionary(StringComparer.OrdinalIgnoreCase); + + if (values != null) + { + foreach (PropertyDescriptor propertyDescriptor in TypeDescriptor.GetProperties(values)) + { + object obj = propertyDescriptor.GetValue(values); + if (obj.GetType().Name.Contains("Anonymous")) + { + dict.Add(propertyDescriptor.Name,ToDictionary(obj)); + } + else + { + dict.Add(propertyDescriptor.Name, obj); + } + } + } + + return dict; + } +#else + var logEntry = logFormatter is null + ? GetLogEntry(logLevel, timestamp, message, exception) + : GetFormattedLogEntry(logLevel, timestamp, message, exception, logFormatter); _systemWrapper.LogLine(JsonSerializer.Serialize(logEntry, JsonSerializerOptions)); +#endif } /// @@ -387,16 +430,16 @@ private LoggerConfiguration GetCurrentConfig() var currConfig = _getCurrentConfig(); _logLevel = _powertoolsConfigurations.GetLogLevel(currConfig?.MinimumLevel); var samplingRate = currConfig?.SamplingRate ?? _powertoolsConfigurations.LoggerSampleRate; - var loggerOutputCase = _powertoolsConfigurations.GetLoggerOutputCase(currConfig?.LoggerOutputCase); + var loggerOutputCase = _powertoolsConfigurations.GetLoggerOutputCase(currConfig?.LoggerOutputCase); _lambdaLogLevel = _powertoolsConfigurations.GetLambdaLogLevel(); _lambdaLogLevelEnabled = _lambdaLogLevel != LogLevel.None; - + var minLogLevel = _logLevel; if (_lambdaLogLevelEnabled) { minLogLevel = _lambdaLogLevel; } - + var config = new LoggerConfiguration { Service = currConfig?.Service, @@ -460,7 +503,7 @@ private static bool CustomFormatter(TState state, Exception exception, o message = stateKeys.First(k => k.Key != "{OriginalFormat}").Value; return true; } - + /// /// Builds JsonSerializer options. /// @@ -468,7 +511,7 @@ private JsonSerializerOptions BuildJsonSerializerOptions() { var jsonOptions = CurrentConfig.LoggerOutputCase switch { - LoggerOutputCase.CamelCase => new JsonSerializerOptions(JsonSerializerDefaults.Web) + LoggerOutputCase.CamelCase => new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, DictionaryKeyPolicy = JsonNamingPolicy.CamelCase @@ -492,7 +535,10 @@ private JsonSerializerOptions BuildJsonSerializerOptions() jsonOptions.Converters.Add(new TimeOnlyConverter()); jsonOptions.Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping; - + +#if NET8_0_OR_GREATER + jsonOptions.TypeInfoResolver = PowertoolsSourceGenerationContext.Default; +#endif return jsonOptions; } } \ No newline at end of file diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/LogEntryLambdaContext.cs b/libraries/src/AWS.Lambda.Powertools.Logging/LogEntryLambdaContext.cs index b83c933e..d0135dad 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/LogEntryLambdaContext.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/LogEntryLambdaContext.cs @@ -13,12 +13,15 @@ * permissions and limitations under the License. */ +using System; +using Amazon.Lambda.Core; + namespace AWS.Lambda.Powertools.Logging; /// /// Powertools Log Entry Lambda Context /// -public class LogEntryLambdaContext +public class LogEntryLambdaContext : ILambdaContext { /// /// The AWS request ID associated with the request. @@ -26,7 +29,9 @@ public class LogEntryLambdaContext /// This ID is reused for retries on the same request. /// public string AwsRequestId { get; internal set; } - + + public IClientContext ClientContext { get; } + /// /// Name of the Lambda function that is running. /// @@ -38,7 +43,11 @@ public class LogEntryLambdaContext /// the version the alias points to. /// public string FunctionVersion { get; internal set; } - + + public ICognitoIdentity Identity { get; } + + public string LogStreamName { get; } + /// /// The ARN used to invoke this function. /// It can be function ARN or alias ARN. @@ -46,11 +55,16 @@ public class LogEntryLambdaContext /// the function version they are pointing to. /// public int MemoryLimitInMB { get; internal set; } - + + public TimeSpan RemainingTime { get; } + /// /// The CloudWatch log group name associated with the invoked function. /// It can be null if the IAM user provided does not have permission for /// CloudWatch actions. /// public string InvokedFunctionArn { get; internal set; } + + public ILambdaLogger Logger { get; } + public string LogGroupName { get; } } \ No newline at end of file diff --git a/libraries/src/AWS.Lambda.Powertools.Metrics/AWS.Lambda.Powertools.Metrics.csproj b/libraries/src/AWS.Lambda.Powertools.Metrics/AWS.Lambda.Powertools.Metrics.csproj index 77110d09..1217ec9e 100644 --- a/libraries/src/AWS.Lambda.Powertools.Metrics/AWS.Lambda.Powertools.Metrics.csproj +++ b/libraries/src/AWS.Lambda.Powertools.Metrics/AWS.Lambda.Powertools.Metrics.csproj @@ -8,11 +8,8 @@ + - - - - diff --git a/libraries/src/AWS.Lambda.Powertools.Common/Core/PowertoolsLambdaContext.cs b/libraries/src/AWS.Lambda.Powertools.Metrics/Internal/PowertoolsLambdaContext.cs similarity index 50% rename from libraries/src/AWS.Lambda.Powertools.Common/Core/PowertoolsLambdaContext.cs rename to libraries/src/AWS.Lambda.Powertools.Metrics/Internal/PowertoolsLambdaContext.cs index 7f9b3fee..323306ea 100644 --- a/libraries/src/AWS.Lambda.Powertools.Common/Core/PowertoolsLambdaContext.cs +++ b/libraries/src/AWS.Lambda.Powertools.Metrics/Internal/PowertoolsLambdaContext.cs @@ -1,4 +1,7 @@ using System; +using System.Linq; +using System.Reflection; +using Amazon.Lambda.Core; namespace AWS.Lambda.Powertools.Common; @@ -47,12 +50,12 @@ internal class PowertoolsLambdaContext /// Memory limit, in MB, you configured for the Lambda function. /// internal int MemoryLimitInMB { get; private set; } - + /// /// The instance /// internal static PowertoolsLambdaContext Instance { get; private set; } - + /// /// Extract the lambda context from Lambda handler arguments. /// @@ -68,55 +71,68 @@ internal static bool Extract(AspectEventArgs eventArgs) if (eventArgs?.Args is null) return false; - foreach (var arg in eventArgs.Args) - { - if (arg is null) - continue; - - var argType = arg.GetType(); - if (!argType.Name.EndsWith("LambdaContext")) - continue; + // foreach (var arg in eventArgs.Args) + // { + // if (arg is null) + // continue; + // + // var argType = arg.GetType(); + // if (!argType.Name.EndsWith("LambdaContext")) + // continue; + // + Instance = new PowertoolsLambdaContext(); + // + // foreach (var prop in argType.GetProperties()) + // { + // if (prop.Name.Equals("AwsRequestId", StringComparison.CurrentCultureIgnoreCase)) + // { + // Instance.AwsRequestId = prop.GetValue(arg) as string; + // } + // else if (prop.Name.Equals("FunctionName", StringComparison.CurrentCultureIgnoreCase)) + // { + // Instance.FunctionName = prop.GetValue(arg) as string; + // } + // else if (prop.Name.Equals("FunctionVersion", StringComparison.CurrentCultureIgnoreCase)) + // { + // Instance.FunctionVersion = prop.GetValue(arg) as string; + // } + // else if (prop.Name.Equals("InvokedFunctionArn", StringComparison.CurrentCultureIgnoreCase)) + // { + // Instance.InvokedFunctionArn = prop.GetValue(arg) as string; + // } + // else if (prop.Name.Equals("LogGroupName", StringComparison.CurrentCultureIgnoreCase)) + // { + // Instance.LogGroupName = prop.GetValue(arg) as string; + // } + // else if (prop.Name.Equals("LogStreamName", StringComparison.CurrentCultureIgnoreCase)) + // { + // Instance.LogStreamName = prop.GetValue(arg) as string; + // } + // else if (prop.Name.Equals("MemoryLimitInMB", StringComparison.CurrentCultureIgnoreCase)) + // { + // var propVal = prop.GetValue(arg); + // if (propVal is null || !int.TryParse(propVal.ToString(), out var intVal)) continue; + // Instance.MemoryLimitInMB = intVal; + // } + // } - Instance = new PowertoolsLambdaContext(); - - foreach (var prop in argType.GetProperties()) - { - if (prop.Name.Equals("AwsRequestId", StringComparison.CurrentCultureIgnoreCase)) - { - Instance.AwsRequestId = prop.GetValue(arg) as string; - } - else if (prop.Name.Equals("FunctionName", StringComparison.CurrentCultureIgnoreCase)) - { - Instance.FunctionName = prop.GetValue(arg) as string; - } - else if (prop.Name.Equals("FunctionVersion", StringComparison.CurrentCultureIgnoreCase)) - { - Instance.FunctionVersion = prop.GetValue(arg) as string; - } - else if (prop.Name.Equals("InvokedFunctionArn", StringComparison.CurrentCultureIgnoreCase)) - { - Instance.InvokedFunctionArn = prop.GetValue(arg) as string; - } - else if (prop.Name.Equals("LogGroupName", StringComparison.CurrentCultureIgnoreCase)) - { - Instance.LogGroupName = prop.GetValue(arg) as string; - } - else if (prop.Name.Equals("LogStreamName", StringComparison.CurrentCultureIgnoreCase)) - { - Instance.LogStreamName = prop.GetValue(arg) as string; - } - else if (prop.Name.Equals("MemoryLimitInMB", StringComparison.CurrentCultureIgnoreCase)) - { - var propVal = prop.GetValue(arg); - if (propVal is null || !int.TryParse(propVal.ToString(), out var intVal)) continue; - Instance.MemoryLimitInMB = intVal; - } - } + var context = (ILambdaContext)eventArgs.Args.FirstOrDefault(x => x is ILambdaContext); - return true; + if (context == null) + { + return false; } - - return false; + + var pt = (ILambdaContext)eventArgs.Args[1]; + Instance.AwsRequestId = pt.AwsRequestId; + Instance.FunctionName = pt.FunctionName; + Instance.FunctionVersion = pt.FunctionVersion; + Instance.InvokedFunctionArn = pt.InvokedFunctionArn; + Instance.LogGroupName = pt.LogGroupName; + Instance.LogStreamName = pt.LogStreamName; + Instance.MemoryLimitInMB = pt.MemoryLimitInMB; + + return true; } /// diff --git a/libraries/src/AWS.Lambda.Powertools.Metrics/Model/MetricResolution.cs b/libraries/src/AWS.Lambda.Powertools.Metrics/Model/MetricResolution.cs index 3c6536ff..34d3141f 100644 --- a/libraries/src/AWS.Lambda.Powertools.Metrics/Model/MetricResolution.cs +++ b/libraries/src/AWS.Lambda.Powertools.Metrics/Model/MetricResolution.cs @@ -6,7 +6,7 @@ namespace AWS.Lambda.Powertools.Metrics; /// /// Enum MetricResolution /// -// [JsonConverter(typeof(StringEnumConverter))] + public enum MetricResolution { /// diff --git a/libraries/src/AWS.Lambda.Powertools.Metrics/Model/MetricUnit.cs b/libraries/src/AWS.Lambda.Powertools.Metrics/Model/MetricUnit.cs index fd4b9760..132b10f3 100644 --- a/libraries/src/AWS.Lambda.Powertools.Metrics/Model/MetricUnit.cs +++ b/libraries/src/AWS.Lambda.Powertools.Metrics/Model/MetricUnit.cs @@ -21,7 +21,11 @@ namespace AWS.Lambda.Powertools.Metrics; /// /// Enum MetricUnit /// +#if NET8_0_OR_GREATER +[JsonConverter(typeof(JsonStringEnumConverter))] +#else [JsonConverter(typeof(StringEnumConverter))] +#endif public enum MetricUnit { /// diff --git a/libraries/src/AWS.Lambda.Powertools.Metrics/Model/RootNode.cs b/libraries/src/AWS.Lambda.Powertools.Metrics/Model/RootNode.cs index a7783819..1e7189e2 100644 --- a/libraries/src/AWS.Lambda.Powertools.Metrics/Model/RootNode.cs +++ b/libraries/src/AWS.Lambda.Powertools.Metrics/Model/RootNode.cs @@ -65,6 +65,14 @@ public string Serialize() { if (string.IsNullOrWhiteSpace(AWS.GetNamespace())) throw new SchemaValidationException("namespace"); +#if NET8_0_OR_GREATER + var options = new JsonSerializerOptions + { + TypeInfoResolver = MetricsSerializationContext.Default + }; + return JsonSerializer.Serialize(this, options); +#else return JsonSerializer.Serialize(this); +#endif } } \ No newline at end of file diff --git a/libraries/src/AWS.Lambda.Powertools.Metrics/Serializer/MetricsSerializationContext.cs b/libraries/src/AWS.Lambda.Powertools.Metrics/Serializer/MetricsSerializationContext.cs new file mode 100644 index 00000000..bf7fdf75 --- /dev/null +++ b/libraries/src/AWS.Lambda.Powertools.Metrics/Serializer/MetricsSerializationContext.cs @@ -0,0 +1,35 @@ +/* + * 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.Collections.Generic; +using System.Text.Json.Serialization; + +namespace AWS.Lambda.Powertools.Metrics; + +[JsonSerializable(typeof(string))] +[JsonSerializable(typeof(double))] +[JsonSerializable(typeof(List))] +[JsonSerializable(typeof(MetricUnit))] +[JsonSerializable(typeof(MetricDefinition))] +[JsonSerializable(typeof(DimensionSet))] +[JsonSerializable(typeof(Metadata))] +[JsonSerializable(typeof(MetricDirective))] +[JsonSerializable(typeof(MetricResolution))] +[JsonSerializable(typeof(MetricsContext))] +[JsonSerializable(typeof(RootNode))] +public partial class MetricsSerializationContext : JsonSerializerContext +{ + +} \ No newline at end of file diff --git a/libraries/src/AWS.Lambda.Powertools.Parameters/AWS.Lambda.Powertools.Parameters.csproj b/libraries/src/AWS.Lambda.Powertools.Parameters/AWS.Lambda.Powertools.Parameters.csproj index ba1020ce..b9f4f921 100644 --- a/libraries/src/AWS.Lambda.Powertools.Parameters/AWS.Lambda.Powertools.Parameters.csproj +++ b/libraries/src/AWS.Lambda.Powertools.Parameters/AWS.Lambda.Powertools.Parameters.csproj @@ -18,6 +18,7 @@ + diff --git a/libraries/src/AWS.Lambda.Powertools.Tracing/AWS.Lambda.Powertools.Tracing.csproj b/libraries/src/AWS.Lambda.Powertools.Tracing/AWS.Lambda.Powertools.Tracing.csproj index 9698055a..3209ef3a 100644 --- a/libraries/src/AWS.Lambda.Powertools.Tracing/AWS.Lambda.Powertools.Tracing.csproj +++ b/libraries/src/AWS.Lambda.Powertools.Tracing/AWS.Lambda.Powertools.Tracing.csproj @@ -15,6 +15,7 @@ + diff --git a/libraries/src/Directory.Build.props b/libraries/src/Directory.Build.props index 0260344d..5fa585bc 100644 --- a/libraries/src/Directory.Build.props +++ b/libraries/src/Directory.Build.props @@ -17,6 +17,8 @@ true true + true + diff --git a/libraries/src/Directory.Packages.props b/libraries/src/Directory.Packages.props index ca1d81f4..f64acd2b 100644 --- a/libraries/src/Directory.Packages.props +++ b/libraries/src/Directory.Packages.props @@ -3,7 +3,9 @@ true - + + + diff --git a/libraries/tests/AWS.Lambda.Powertools.AotCompatibility/AWS.Lambda.Powertools.AotCompatibility.csproj b/libraries/tests/AWS.Lambda.Powertools.AotCompatibility/AWS.Lambda.Powertools.AotCompatibility.csproj new file mode 100644 index 00000000..ded061ef --- /dev/null +++ b/libraries/tests/AWS.Lambda.Powertools.AotCompatibility/AWS.Lambda.Powertools.AotCompatibility.csproj @@ -0,0 +1,45 @@ + + + + net8.0;net8.0 + enable + enable + + false + true + Exe + + + + false + + + + + true + true + false + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + diff --git a/libraries/tests/AWS.Lambda.Powertools.AotCompatibility/GlobalUsings.cs b/libraries/tests/AWS.Lambda.Powertools.AotCompatibility/GlobalUsings.cs new file mode 100644 index 00000000..8c927eb7 --- /dev/null +++ b/libraries/tests/AWS.Lambda.Powertools.AotCompatibility/GlobalUsings.cs @@ -0,0 +1 @@ +global using Xunit; \ No newline at end of file diff --git a/libraries/tests/AWS.Lambda.Powertools.AotCompatibility/HandlerTest.cs b/libraries/tests/AWS.Lambda.Powertools.AotCompatibility/HandlerTest.cs new file mode 100644 index 00000000..576510aa --- /dev/null +++ b/libraries/tests/AWS.Lambda.Powertools.AotCompatibility/HandlerTest.cs @@ -0,0 +1,26 @@ +using Amazon.Lambda.TestUtilities; + +namespace AWS.Lambda.Powertools.AotCompatibility; + +public class HandlerTest +{ + [Fact] + public async Task Test1() + { + var handler = new Handlers.Handler(); + + + var context = new TestLambdaContext() + { + FunctionName = "PowertoolsLoggingSample-HelloWorldFunction-Gg8rhPwO7Wa1", + FunctionVersion = "1", + MemoryLimitInMB = 215, + AwsRequestId = Guid.NewGuid().ToString("D") + }; + + // Act + var response = await handler.Handle("whatever", context); + + Assert.Equal("whatever", response); + } +} \ No newline at end of file diff --git a/libraries/tests/AWS.Lambda.Powertools.AotCompatibility/Handlers/Handler.cs b/libraries/tests/AWS.Lambda.Powertools.AotCompatibility/Handlers/Handler.cs new file mode 100644 index 00000000..98f25d74 --- /dev/null +++ b/libraries/tests/AWS.Lambda.Powertools.AotCompatibility/Handlers/Handler.cs @@ -0,0 +1,47 @@ +/* + * 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 Amazon.Lambda.Core; +using AWS.Lambda.Powertools.Logging; +using AWS.Lambda.Powertools.Metrics; +using AWS.Lambda.Powertools.Tracing; + +namespace AWS.Lambda.Powertools.AotCompatibility.Handlers; + +public class Handler +{ + [Logging(LogEvent = true)] + [Metrics(CaptureColdStart = true, Namespace = "PT Demo NS")] + [Tracing(Namespace = "PT Demo NS", CaptureMode = TracingCaptureMode.ResponseAndError)] + public async Task Handle(string input, ILambdaContext context) + { + Logger.LogInformation("Hello world!"); + + Metrics.Metrics.AddMetric("Metric1", 1, MetricUnit.Count); + + DoSomething(); + + Tracing.Tracing.AddAnnotation("Annotation1", "My Anottation"); + + await Task.Delay(1); + return input; + } + + [Tracing(SegmentName = "Do Something Method")] + public void DoSomething() + { + Tracing.Tracing.AddAnnotation("Annotation1", "My Anottation"); + } +} \ No newline at end of file diff --git a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/AWS.Lambda.Powertools.Logging.Tests.csproj b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/AWS.Lambda.Powertools.Logging.Tests.csproj index 9d49d514..f06175ec 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/AWS.Lambda.Powertools.Logging.Tests.csproj +++ b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/AWS.Lambda.Powertools.Logging.Tests.csproj @@ -11,8 +11,8 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Handlers/ExceptionFunctionHandler.cs b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Handlers/ExceptionFunctionHandler.cs index 23005388..b13a7019 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Handlers/ExceptionFunctionHandler.cs +++ b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Handlers/ExceptionFunctionHandler.cs @@ -8,7 +8,7 @@ namespace AWS.Lambda.Powertools.Logging.Tests.Handlers; public class ExceptionFunctionHandler { - [Logging] + [Logging(LogEvent = true)] public async Task Handle(string input) { ThisThrows(); diff --git a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/LogFormatterTest.cs b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/LogFormatterTest.cs index 158d8fe8..23867070 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/LogFormatterTest.cs +++ b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/LogFormatterTest.cs @@ -127,6 +127,7 @@ public void Log_WhenCustomFormatter_LogsCustomFormat() logger.LogInformation(scopeExtraKeys, message); // Assert + logFormatter.Received(1).FormatLogEntry(Arg.Is ( x => diff --git a/libraries/tests/AWS.Lambda.Powertools.Common.Tests/Core/PowertoolsLambdaContextTest.cs b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLambdaContextTest.cs similarity index 78% rename from libraries/tests/AWS.Lambda.Powertools.Common.Tests/Core/PowertoolsLambdaContextTest.cs rename to libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLambdaContextTest.cs index d6f87fae..a6fe8e86 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Common.Tests/Core/PowertoolsLambdaContextTest.cs +++ b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLambdaContextTest.cs @@ -1,24 +1,20 @@ using System; +using Amazon.Lambda.Core; +using Amazon.Lambda.TestUtilities; +using AWS.Lambda.Powertools.Logging.Internal; using Xunit; namespace AWS.Lambda.Powertools.Common.Tests; public class PowertoolsLambdaContextTest { - private class TestLambdaContext - { - public string AwsRequestId { get; set; } - public string FunctionName { get; set; } - public string FunctionVersion { get; set; } - public string InvokedFunctionArn { get; set; } - public string LogGroupName { get; set; } - public string LogStreamName { get; set; } - public int MemoryLimitInMB { get; set; } - } - - private static TestLambdaContext NewLambdaContext() + + + [Fact] + public void Extract_WhenHasLambdaContextArgument_InitializesLambdaContextInfo() { - return new TestLambdaContext + // Arrange + var lambdaContext = new TestLambdaContext { AwsRequestId = Guid.NewGuid().ToString(), FunctionName = Guid.NewGuid().ToString(), @@ -28,16 +24,11 @@ private static TestLambdaContext NewLambdaContext() LogStreamName = Guid.NewGuid().ToString(), MemoryLimitInMB = new Random().Next() }; - } - - [Fact] - public void Extract_WhenHasLambdaContextArgument_InitializesLambdaContextInfo() - { - // Arrange - var lambdaContext = NewLambdaContext(); + var eventArg = new {Source = "Test"}; var eventArgs = new AspectEventArgs { + Method = GetType().GetMethod(nameof(Extract_WhenHasLambdaContextArgument_InitializesLambdaContextInfo)), Name = Guid.NewGuid().ToString(), Args = new object [] { diff --git a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs index c49852af..d58a8165 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs +++ b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs @@ -19,6 +19,7 @@ using System.IO; using System.Linq; using System.Text; +using System.Text.Json.Serialization; using AWS.Lambda.Powertools.Common; using AWS.Lambda.Powertools.Logging.Internal; using AWS.Lambda.Powertools.Logging.Tests.Utilities; @@ -431,7 +432,7 @@ public void Log_AttributeSetsCaseToCamelCase_OutputsCamelCaseLog() PropOne = "Value 1", PropTwo = "Value 2" }; - + logger.LogInformation(message); // Assert