From 1f7df12793e80001af55a0d26a9a8f270f3578c3 Mon Sep 17 00:00:00 2001
From: Henrique Graca <999396+hjgraca@users.noreply.github.com>
Date: Wed, 11 Oct 2023 11:46:36 +0100
Subject: [PATCH 1/3] Add DateOnly and TimeOnly converters
---
.../Internal/Converters/DateOnlyConverter.cs | 52 ++++++++++++
.../Internal/Converters/TimeOnlyConverter.cs | 52 ++++++++++++
.../Internal/LoggingAspectHandler.cs | 2 +
.../Internal/PowertoolsLogger.cs | 2 +
.../PowertoolsLoggerTest.cs | 82 +++++++++++++++++++
5 files changed, 190 insertions(+)
create mode 100644 libraries/src/AWS.Lambda.Powertools.Logging/Internal/Converters/DateOnlyConverter.cs
create mode 100644 libraries/src/AWS.Lambda.Powertools.Logging/Internal/Converters/TimeOnlyConverter.cs
diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/Converters/DateOnlyConverter.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/Converters/DateOnlyConverter.cs
new file mode 100644
index 000000000..a6f969e59
--- /dev/null
+++ b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/Converters/DateOnlyConverter.cs
@@ -0,0 +1,52 @@
+/*
+ * 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.Globalization;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace AWS.Lambda.Powertools.Logging.Internal.Converters;
+
+///
+/// DateOnly JSON converter
+///
+public class DateOnlyConverter : JsonConverter
+{
+ private const string DateFormat = "yyyy-MM-dd";
+
+ ///
+ /// Converts DateOnly from JSON.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override DateOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ return DateOnly.ParseExact(reader.GetString()!, DateFormat, CultureInfo.InvariantCulture);
+ }
+
+ ///
+ /// Converts DateOnly to JSON.
+ ///
+ ///
+ ///
+ ///
+ public override void Write(Utf8JsonWriter writer, DateOnly value, JsonSerializerOptions options)
+ {
+ writer.WriteStringValue(value.ToString(DateFormat, CultureInfo.InvariantCulture));
+ }
+}
\ No newline at end of file
diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/Converters/TimeOnlyConverter.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/Converters/TimeOnlyConverter.cs
new file mode 100644
index 000000000..737362ca0
--- /dev/null
+++ b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/Converters/TimeOnlyConverter.cs
@@ -0,0 +1,52 @@
+/*
+ * 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.Globalization;
+using System.Text.Json;
+using System.Text.Json.Serialization;
+
+namespace AWS.Lambda.Powertools.Logging.Internal.Converters;
+
+///
+/// TimeOnly JSON converter
+///
+internal class TimeOnlyConverter : JsonConverter
+{
+ private const string TimeFormat = "HH:mm:ss.FFFFFFF";
+
+ ///
+ /// Converts TimeOnly from JSON.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public override TimeOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
+ {
+ return TimeOnly.ParseExact(reader.GetString()!, TimeFormat, CultureInfo.InvariantCulture);
+ }
+
+ ///
+ /// Converts TimeOnly to JSON.
+ ///
+ ///
+ ///
+ ///
+ public override void Write(Utf8JsonWriter writer, TimeOnly value, JsonSerializerOptions options)
+ {
+ writer.WriteStringValue(value.ToString(TimeFormat, CultureInfo.InvariantCulture));
+ }
+}
\ No newline at end of file
diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingAspectHandler.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingAspectHandler.cs
index 4b2624902..441cdc222 100644
--- a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingAspectHandler.cs
+++ b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingAspectHandler.cs
@@ -288,6 +288,8 @@ private static JsonSerializerOptions BuildJsonSerializerOptions()
jsonOptions.Converters.Add(new ExceptionConverter());
jsonOptions.Converters.Add(new MemoryStreamConverter());
jsonOptions.Converters.Add(new ConstantClassConverter());
+ jsonOptions.Converters.Add(new DateOnlyConverter());
+ jsonOptions.Converters.Add(new TimeOnlyConverter());
return jsonOptions;
}
diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs
index 265090aa9..707d4a8ee 100644
--- a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs
+++ b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs
@@ -466,6 +466,8 @@ private JsonSerializerOptions BuildJsonSerializerOptions()
jsonOptions.Converters.Add(new ExceptionConverter());
jsonOptions.Converters.Add(new MemoryStreamConverter());
jsonOptions.Converters.Add(new ConstantClassConverter());
+ jsonOptions.Converters.Add(new DateOnlyConverter());
+ jsonOptions.Converters.Add(new TimeOnlyConverter());
jsonOptions.Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping;
diff --git a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs
index 71db59320..c0fd3c09c 100644
--- a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs
+++ b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs
@@ -1219,5 +1219,87 @@ public void Log_Set_Execution_Environment_Context()
$"{Constants.FeatureContextIdentifier}/Logger/{assemblyVersion}");
env.Received(1).GetEnvironmentVariable("AWS_EXECUTION_ENV");
}
+
+ [Fact]
+ public void Log_Should_Serialize_DateOnly()
+ {
+ // Arrange
+ var loggerName = Guid.NewGuid().ToString();
+ var service = Guid.NewGuid().ToString();
+ var logLevel = LogLevel.Information;
+ var randomSampleRate = 0.5;
+
+ var configurations = Substitute.For();
+ configurations.Service.Returns(service);
+ configurations.LogLevel.Returns(logLevel.ToString());
+
+ var systemWrapper = Substitute.For();
+ systemWrapper.GetRandom().Returns(randomSampleRate);
+
+ var logger = new PowertoolsLogger(loggerName, configurations, systemWrapper, () =>
+ new LoggerConfiguration
+ {
+ Service = null,
+ MinimumLevel = null,
+ LoggerOutputCase = LoggerOutputCase.CamelCase
+ });
+
+ var message = new
+ {
+ PropOne = "Value 1",
+ PropTwo = "Value 2",
+ Date = new DateOnly(2022, 1, 1)
+ };
+
+ logger.LogInformation(message);
+
+ // Assert
+ systemWrapper.Received(1).LogLine(
+ Arg.Is(s =>
+ s.Contains("\"message\":{\"propOne\":\"Value 1\",\"propTwo\":\"Value 2\",\"date\":\"2022-01-01\"}")
+ )
+ );
+ }
+
+ [Fact]
+ public void Log_Should_Serialize_TimeOnly()
+ {
+ // Arrange
+ var loggerName = Guid.NewGuid().ToString();
+ var service = Guid.NewGuid().ToString();
+ var logLevel = LogLevel.Information;
+ var randomSampleRate = 0.5;
+
+ var configurations = Substitute.For();
+ configurations.Service.Returns(service);
+ configurations.LogLevel.Returns(logLevel.ToString());
+
+ var systemWrapper = Substitute.For();
+ systemWrapper.GetRandom().Returns(randomSampleRate);
+
+ var logger = new PowertoolsLogger(loggerName, configurations, systemWrapper, () =>
+ new LoggerConfiguration
+ {
+ Service = null,
+ MinimumLevel = null,
+ LoggerOutputCase = LoggerOutputCase.CamelCase
+ });
+
+ var message = new
+ {
+ PropOne = "Value 1",
+ PropTwo = "Value 2",
+ Time = new TimeOnly(12, 0, 0)
+ };
+
+ logger.LogInformation(message);
+
+ // Assert
+ systemWrapper.Received(1).LogLine(
+ Arg.Is(s =>
+ s.Contains("\"message\":{\"propOne\":\"Value 1\",\"propTwo\":\"Value 2\",\"time\":\"12:00:00\"}")
+ )
+ );
+ }
}
}
\ No newline at end of file
From b3d666f5a7c023a4374519fecf535d88e876fc8d Mon Sep 17 00:00:00 2001
From: Henrique Graca <999396+hjgraca@users.noreply.github.com>
Date: Wed, 11 Oct 2023 14:56:08 +0100
Subject: [PATCH 2/3] fix code smell - dont need to be static
---
.../Internal/LoggingAspectHandler.cs | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingAspectHandler.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingAspectHandler.cs
index 441cdc222..38817e580 100644
--- a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingAspectHandler.cs
+++ b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingAspectHandler.cs
@@ -35,12 +35,12 @@ internal class LoggingAspectHandler : IMethodAspectHandler
///
/// The is cold start
///
- private static bool _isColdStart = true;
+ private bool _isColdStart = true;
///
/// The initialize context
///
- private static bool _initializeContext = true;
+ private bool _initializeContext = true;
///
/// Clear state?
@@ -388,8 +388,6 @@ private void LogEvent(object eventArg)
///
internal static void ResetForTest()
{
- _isColdStart = true;
- _initializeContext = true;
PowertoolsLambdaContext.Clear();
Logger.LoggerProvider = null;
Logger.RemoveAllKeys();
From f3ad52cea60d5923d28143fdbf80997476ee3f78 Mon Sep 17 00:00:00 2001
From: Henrique Graca <999396+hjgraca@users.noreply.github.com>
Date: Thu, 12 Oct 2023 10:16:07 +0100
Subject: [PATCH 3/3] make fields static
---
.../Internal/LoggingAspectHandler.cs | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingAspectHandler.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingAspectHandler.cs
index 38817e580..441cdc222 100644
--- a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingAspectHandler.cs
+++ b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/LoggingAspectHandler.cs
@@ -35,12 +35,12 @@ internal class LoggingAspectHandler : IMethodAspectHandler
///
/// The is cold start
///
- private bool _isColdStart = true;
+ private static bool _isColdStart = true;
///
/// The initialize context
///
- private bool _initializeContext = true;
+ private static bool _initializeContext = true;
///
/// Clear state?
@@ -388,6 +388,8 @@ private void LogEvent(object eventArg)
///
internal static void ResetForTest()
{
+ _isColdStart = true;
+ _initializeContext = true;
PowertoolsLambdaContext.Clear();
Logger.LoggerProvider = null;
Logger.RemoveAllKeys();