Skip to content

chore: Logging AOT Support #628

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

Merged
merged 38 commits into from
Sep 23, 2024
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
6f50d34
Initial commit. New Serialization context. .NET 8 serialization speci…
hjgraca Aug 2, 2024
34070d6
move to static PowertoolsLoggerHelpers
hjgraca Aug 20, 2024
98c6733
Merge branch 'develop' into aot(logging)-support-logging
hjgraca Aug 21, 2024
2bd8915
Merge branch 'develop' of https://github.com/hjgraca/powertools-lambd…
hjgraca Aug 27, 2024
cd9babf
Refactor case logic. new lambdacontext using LambdaCore. Tests, docs …
hjgraca Aug 29, 2024
70c996d
Merge branch 'develop' of https://github.com/hjgraca/powertools-lambd…
hjgraca Aug 29, 2024
19e82b8
Fix AOT warnings, new way to extract properties from Exceptions. New …
hjgraca Aug 29, 2024
5216450
remove non-deterministic string from tests
hjgraca Aug 29, 2024
fca9fcd
Merge branch 'develop' of https://github.com/hjgraca/powertools-lambd…
hjgraca Aug 30, 2024
35e613b
remove comments
hjgraca Sep 2, 2024
4f12325
merge
hjgraca Sep 2, 2024
42138f7
refactor, change the way we create Logger in tests to use LoggerProvider
hjgraca Sep 11, 2024
c7e95b4
refactor configuration and sampling rate code
hjgraca Sep 11, 2024
27e7433
address sonar issues
hjgraca Sep 11, 2024
1a97e37
add Serialize method to the correct place
hjgraca Sep 11, 2024
6c23b03
add tests for serializer
hjgraca Sep 11, 2024
f65d3cb
refactoring and serializer tests
hjgraca Sep 11, 2024
86e624d
refactor and add tests for logging handler.
hjgraca Sep 13, 2024
80815ea
Refactor Aspect Injection to Factory. Add more tests for full path us…
hjgraca Sep 16, 2024
68395c3
fix sonar and cleanup
hjgraca Sep 16, 2024
681de15
fix sonar issues
hjgraca Sep 17, 2024
a18f29e
more tests
hjgraca Sep 17, 2024
e9e71b0
fix sonar issues
hjgraca Sep 17, 2024
e92559b
remove ApiGateway and LoadBalancer Events from serializer
hjgraca Sep 17, 2024
67dc1cf
fix LogLevel and default to None when not set. more tests
hjgraca Sep 18, 2024
0595e8e
fix serialization on first request. the context was not set properly,…
hjgraca Sep 20, 2024
0b4e96b
replace ApplicationException with JsonSerializerException
hjgraca Sep 20, 2024
86b8f85
addressed issue when anonymous type on AddKeys. Refactored serializat…
hjgraca Sep 20, 2024
af66bcd
Fix custom serializer on AOT. Add tests
hjgraca Sep 23, 2024
6446e95
for aot, ILogFormatter instance needs to be passed to PowertoolsSourc…
hjgraca Sep 23, 2024
52f6066
comments
hjgraca Sep 23, 2024
4d52cc1
add documentation.
hjgraca Sep 23, 2024
0ffbbbc
update doc
hjgraca Sep 23, 2024
8e81bfa
Merge branch 'develop' of https://github.com/hjgraca/powertools-lambd…
hjgraca Sep 23, 2024
b6f7988
refactor AOT examples to each folder. Add Logging AOT examples and up…
hjgraca Sep 23, 2024
cbb78fa
update examples
hjgraca Sep 23, 2024
eabc183
update doc and examples
hjgraca Sep 23, 2024
e1d1181
fix sonar issues
hjgraca Sep 23, 2024
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
4 changes: 4 additions & 0 deletions docs/core/logging.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ When debugging in non-production environments, you can instruct Logger to log th

You can set a Correlation ID using `CorrelationIdPath` parameter by passing a [JSON Pointer expression](https://datatracker.ietf.org/doc/html/draft-ietf-appsawg-json-pointer-03){target="_blank"}.

!!! Attention
The JSON Pointer expression is `case sensitive`. In the bellow example `/headers/my_request_id_header` would work but `/Headers/my_request_id_header` would not find the element.


=== "Function.cs"

```c# hl_lines="6"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public interface IPowertoolsConfigurations
/// Gets the logger sample rate.
/// </summary>
/// <value>The logger sample rate.</value>
double? LoggerSampleRate { get; }
double LoggerSampleRate { get; }

/// <summary>
/// Gets a value indicating whether [logger log event].
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
* permissions and limitations under the License.
*/

using System.Globalization;

namespace AWS.Lambda.Powertools.Common;

/// <summary>
Expand Down Expand Up @@ -157,10 +159,10 @@ public bool GetEnvironmentVariableOrDefault(string variable, bool defaultValue)
/// Gets the logger sample rate.
/// </summary>
/// <value>The logger sample rate.</value>
public double? LoggerSampleRate =>
double.TryParse(_systemWrapper.GetEnvironmentVariable(Constants.LoggerSampleRateNameEnv), out var result)
public double LoggerSampleRate =>
double.TryParse(_systemWrapper.GetEnvironmentVariable(Constants.LoggerSampleRateNameEnv), NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out var result)
? result
: null;
: 0;

/// <summary>
/// Gets a value indicating whether [logger log event].
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@
<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="Microsoft.Extensions.Logging"/>
<PackageReference Include="Amazon.Lambda.Core" />
<PackageReference Include="Amazon.Lambda.Serialization.SystemTextJson" />
<PackageReference Include="Microsoft.Extensions.Logging" />
<ProjectReference Include="..\AWS.Lambda.Powertools.Common\AWS.Lambda.Powertools.Common.csproj" Condition="'$(Configuration)'=='Debug'"/>
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using AWS.Lambda.Powertools.Logging.Serializers;

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

Expand Down Expand Up @@ -57,15 +58,13 @@
public override void Write(Utf8JsonWriter writer, Exception value, JsonSerializerOptions options)
{
var exceptionType = value.GetType();
var properties = exceptionType.GetProperties()
.Where(prop => prop.Name != nameof(Exception.TargetSite))
.Select(prop => new { prop.Name, Value = prop.GetValue(value) });
var properties = ExceptionPropertyExtractor.ExtractProperties(value);

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

var props = properties.ToArray();
if (!props.Any())
if (props.Length == 0)
return;

writer.WriteStartObject();
Expand All @@ -76,17 +75,16 @@
switch (prop.Value)
{
case IntPtr intPtr:
writer.WriteNumber(ApplyPropertyNamingPolicy(prop.Name, options), intPtr.ToInt64());
writer.WriteNumber(ApplyPropertyNamingPolicy(prop.Key, options), intPtr.ToInt64());

Check warning on line 78 in libraries/src/AWS.Lambda.Powertools.Logging/Internal/Converters/ExceptionConverter.cs

View check run for this annotation

Codecov / codecov/patch

libraries/src/AWS.Lambda.Powertools.Logging/Internal/Converters/ExceptionConverter.cs#L78

Added line #L78 was not covered by tests
break;
case UIntPtr uIntPtr:
writer.WriteNumber(ApplyPropertyNamingPolicy(prop.Name, options), uIntPtr.ToUInt64());
writer.WriteNumber(ApplyPropertyNamingPolicy(prop.Key, options), uIntPtr.ToUInt64());

Check warning on line 81 in libraries/src/AWS.Lambda.Powertools.Logging/Internal/Converters/ExceptionConverter.cs

View check run for this annotation

Codecov / codecov/patch

libraries/src/AWS.Lambda.Powertools.Logging/Internal/Converters/ExceptionConverter.cs#L81

Added line #L81 was not covered by tests
break;
case Type propType:
writer.WriteString(ApplyPropertyNamingPolicy(prop.Name, options), propType.FullName);
writer.WriteString(ApplyPropertyNamingPolicy(prop.Key, options), propType.FullName);

Check warning on line 84 in libraries/src/AWS.Lambda.Powertools.Logging/Internal/Converters/ExceptionConverter.cs

View check run for this annotation

Codecov / codecov/patch

libraries/src/AWS.Lambda.Powertools.Logging/Internal/Converters/ExceptionConverter.cs#L84

Added line #L84 was not covered by tests
break;
default:
writer.WritePropertyName(ApplyPropertyNamingPolicy(prop.Name, options));
JsonSerializer.Serialize(writer, prop.Value, options);
case string propString:
writer.WriteString(ApplyPropertyNamingPolicy(prop.Key, options), propString);
break;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;

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

/// <summary>
/// Class ExceptionPropertyExtractor.
/// This class is used to extract properties from an exception object.
/// It uses a dictionary of type to function mappings to extract specific properties based on the exception type.
/// If no specific extractor is found, it falls back to the base Exception extractor.
/// </summary>
internal static class ExceptionPropertyExtractor
{
/// <summary>
/// The property extractors
/// </summary>
private static readonly Dictionary<Type, Func<Exception, IEnumerable<KeyValuePair<string, object>>>> PropertyExtractors = new()
{
{ typeof(Exception), GetBaseExceptionProperties },
};

Check warning on line 20 in libraries/src/AWS.Lambda.Powertools.Logging/Internal/Converters/ExceptionPropertyExtractor.cs

View check run for this annotation

Codecov / codecov/patch

libraries/src/AWS.Lambda.Powertools.Logging/Internal/Converters/ExceptionPropertyExtractor.cs#L17-L20

Added lines #L17 - L20 were not covered by tests

/// <summary>
/// Use this method to extract properties from and Exception based type
/// This method is used when building for native AOT
/// </summary>
/// <param name="exception"></param>
/// <returns></returns>
public static IEnumerable<KeyValuePair<string, object>> ExtractProperties(Exception exception)
{
return GetBaseExceptionProperties(exception);
}

/// <summary>
/// Get the base Exception properties
/// </summary>
/// <param name="ex"></param>
/// <returns></returns>
private static IEnumerable<KeyValuePair<string, object>> GetBaseExceptionProperties(Exception ex)
{
yield return new KeyValuePair<string, object>(nameof(Exception.Message), ex.Message);
yield return new KeyValuePair<string, object>(nameof(Exception.Source), ex.Source);
yield return new KeyValuePair<string, object>(nameof(Exception.StackTrace), ex.StackTrace);
}
}
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.Linq;

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

/// <summary>
/// Class PowertoolsLoggerHelpers.
/// </summary>
internal static class PowertoolsLoggerHelpers
{
/// <summary>
/// Converts an object to a dictionary.
/// </summary>
/// <param name="anonymousObject">The object to convert.</param>
/// <returns>
/// If the object has a namespace, returns the object as-is.
/// Otherwise, returns a dictionary representation of the object's properties.
/// </returns>
internal static object ObjectToDictionary(object anonymousObject)
{
if (anonymousObject.GetType().Namespace is not null)
{
return anonymousObject;
}

return anonymousObject.GetType().GetProperties()
.ToDictionary(prop => prop.Name, prop => ObjectToDictionary(prop.GetValue(anonymousObject, null)));
}
}
Loading
Loading