From 4a800c636f98afcc79965fefecd9885544bff9e3 Mon Sep 17 00:00:00 2001 From: Henrique Graca <999396+hjgraca@users.noreply.github.com> Date: Fri, 5 Jan 2024 11:24:08 +0000 Subject: [PATCH 1/2] Handle Exceptions and Prevent application from crashing when using Logger --- .../LoggerExtensions.cs | 52 ++++++++++++------- ...AWS.Lambda.Powertools.Logging.Tests.csproj | 2 + .../Handlers/ExceptionFunctionHandler.cs | 32 ++++++++++++ .../Handlers/ExceptionFunctionHandlerTests.cs | 16 ++++++ 4 files changed, 83 insertions(+), 19 deletions(-) diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/LoggerExtensions.cs b/libraries/src/AWS.Lambda.Powertools.Logging/LoggerExtensions.cs index 8c8dd311..200cf46e 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/LoggerExtensions.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/LoggerExtensions.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 @@ -187,7 +187,7 @@ public static void Log(this ILogger logger, LogLevel logLevel, Exception excepti #region ExtraKeys Logger Extentions #region Debug - + /// /// Formats and writes a debug log message. /// @@ -242,15 +242,16 @@ public static void LogDebug(this ILogger logger, T extraKeys, Exception excep /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. /// logger.LogDebug(extraKeys, "Processing request from {Address}", address) - public static void LogDebug(this ILogger logger, T extraKeys, string message, params object[] args) where T : class + public static void LogDebug(this ILogger logger, T extraKeys, string message, params object[] args) + where T : class { Log(logger, LogLevel.Debug, extraKeys, message, args); } - + #endregion #region Trace - + /// /// Formats and writes a trace log message. /// @@ -305,7 +306,8 @@ public static void LogTrace(this ILogger logger, T extraKeys, Exception excep /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. /// logger.LogTrace(extraKeys, "Processing request from {Address}", address) - public static void LogTrace(this ILogger logger, T extraKeys, string message, params object[] args) where T : class + public static void LogTrace(this ILogger logger, T extraKeys, string message, params object[] args) + where T : class { Log(logger, LogLevel.Trace, extraKeys, message, args); } @@ -313,7 +315,7 @@ public static void LogTrace(this ILogger logger, T extraKeys, string message, #endregion #region Information - + /// /// Formats and writes an informational log message. /// @@ -368,11 +370,12 @@ public static void LogInformation(this ILogger logger, T extraKeys, Exception /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. /// logger.LogInformation(extraKeys, "Processing request from {Address}", address) - public static void LogInformation(this ILogger logger, T extraKeys, string message, params object[] args) where T : class + public static void LogInformation(this ILogger logger, T extraKeys, string message, params object[] args) + where T : class { Log(logger, LogLevel.Information, extraKeys, message, args); } - + #endregion #region Warning @@ -431,11 +434,12 @@ public static void LogWarning(this ILogger logger, T extraKeys, Exception exc /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. /// logger.LogWarning(extraKeys, "Processing request from {Address}", address) - public static void LogWarning(this ILogger logger, T extraKeys, string message, params object[] args) where T : class + public static void LogWarning(this ILogger logger, T extraKeys, string message, params object[] args) + where T : class { Log(logger, LogLevel.Warning, extraKeys, message, args); } - + #endregion #region Error @@ -494,7 +498,8 @@ public static void LogError(this ILogger logger, T extraKeys, Exception excep /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. /// logger.LogError(extraKeys, "Processing request from {Address}", address) - public static void LogError(this ILogger logger, T extraKeys, string message, params object[] args) where T : class + public static void LogError(this ILogger logger, T extraKeys, string message, params object[] args) + where T : class { Log(logger, LogLevel.Error, extraKeys, message, args); } @@ -557,7 +562,8 @@ public static void LogCritical(this ILogger logger, T extraKeys, Exception ex /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. /// logger.LogCritical(extraKeys, "Processing request from {Address}", address) - public static void LogCritical(this ILogger logger, T extraKeys, string message, params object[] args) where T : class + public static void LogCritical(this ILogger logger, T extraKeys, string message, params object[] args) + where T : class { Log(logger, LogLevel.Critical, extraKeys, message, args); } @@ -565,7 +571,7 @@ public static void LogCritical(this ILogger logger, T extraKeys, string messa #endregion #region Log - + /// /// Formats and writes a log message at the specified log level. /// @@ -630,11 +636,19 @@ public static void Log(this ILogger logger, LogLevel logLevel, T extraKeys, E /// Format string of the log message in message template format. Example: "User {User} logged in from {Address}" /// An object array that contains zero or more objects to format. /// logger.Log(LogLevel.Information, extraKeys, "Processing request from {Address}", address) - public static void Log(this ILogger logger, LogLevel logLevel, T extraKeys, string message, params object[] args) where T : class + public static void Log(this ILogger logger, LogLevel logLevel, T extraKeys, string message, params object[] args) + where T : class { - Log(logger, logLevel, extraKeys, 0, null, message, args); + try + { + Log(logger, logLevel, extraKeys, 0, null, message, args); + } + catch (Exception e) + { + logger.Log(LogLevel.Error, 0, e, "Powertools internal error"); + } } - + #endregion #endregion 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 197fec51..5567ec66 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 @@ -12,6 +12,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 a2928252..23005388 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Handlers/ExceptionFunctionHandler.cs +++ b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Handlers/ExceptionFunctionHandler.cs @@ -1,6 +1,8 @@ using System; +using System.Collections.Generic; using System.Globalization; using System.Threading.Tasks; +using Amazon.Lambda.Core; namespace AWS.Lambda.Powertools.Logging.Tests.Handlers; @@ -20,4 +22,34 @@ private void ThisThrows() { throw new NullReferenceException(); } + + [Logging(CorrelationIdPath = "/1//", LogEvent = true, Service = null, SamplingRate = 10000d)] + public string HandlerLoggerForExceptions(string input, ILambdaContext context) + { + // Edge cases and bad code to force exceptions + + Logger.LogInformation("Hello {input}", input); + Logger.LogError("Hello {input}", input); + Logger.LogCritical("Hello {input}", input); + Logger.LogDebug("Hello {input}", input); + Logger.LogTrace("Hello {input}", input); + + Logger.LogInformation("Testing with parameter Log Information Method {company}", new[] { "AWS" }); + + var customKeys = new Dictionary + { + {"test1", "value1"}, + {"test2", "value2"} + }; + Logger.LogInformation(customKeys, "Retrieved data for city {cityName} with count {company}", "AWS"); + + Logger.AppendKey("aws",1); + Logger.AppendKey("aws",3); + + Logger.RemoveKeys("test"); + + Logger.AppendKeys(new[]{ new KeyValuePair("aws",1), new KeyValuePair("aws",2)}); + + return "OK"; + } } \ No newline at end of file diff --git a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Handlers/ExceptionFunctionHandlerTests.cs b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Handlers/ExceptionFunctionHandlerTests.cs index f2bbe798..dd7a12db 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Handlers/ExceptionFunctionHandlerTests.cs +++ b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Handlers/ExceptionFunctionHandlerTests.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using Amazon.Lambda.TestUtilities; using Xunit; namespace AWS.Lambda.Powertools.Logging.Tests.Handlers; @@ -20,4 +21,19 @@ public async Task Stack_Trace_Included_When_Decorator_Present() Assert.StartsWith("at AWS.Lambda.Powertools.Logging.Tests.Handlers.ExceptionFunctionHandler.ThisThrows()", tracedException.StackTrace?.TrimStart()); } + + [Fact] + public void Utility_Should_Not_Throw_Exceptions_To_Client() + { + // Arrange + var lambdaContext = new TestLambdaContext(); + + var handler = new ExceptionFunctionHandler(); + + // Act + var res = handler.HandlerLoggerForExceptions("aws",lambdaContext); + + // Assert + Assert.Equal("OK", res); + } } \ No newline at end of file From 5159cd84b6fb2730a4d45f010fb5b32ea0100411 Mon Sep 17 00:00:00 2001 From: Henrique Graca <999396+hjgraca@users.noreply.github.com> Date: Fri, 5 Jan 2024 12:02:30 +0000 Subject: [PATCH 2/2] fix test because of order of execution might fail --- .../LogFormatterTest.cs | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/LogFormatterTest.cs b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/LogFormatterTest.cs index 82c93e34..158d8fe8 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/LogFormatterTest.cs +++ b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/LogFormatterTest.cs @@ -138,16 +138,17 @@ public void Log_WhenCustomFormatter_LogsCustomFormat() x.Level == logLevel && x.Message.ToString() == message && x.Exception == null && - x.ExtraKeys != null && - x.ExtraKeys.Count == globalExtraKeys.Count + scopeExtraKeys.Count && - x.ExtraKeys.ContainsKey(globalExtraKeys.First().Key) && - x.ExtraKeys[globalExtraKeys.First().Key] == globalExtraKeys.First().Value && - x.ExtraKeys.ContainsKey(globalExtraKeys.Last().Key) && - x.ExtraKeys[globalExtraKeys.Last().Key] == globalExtraKeys.Last().Value && - x.ExtraKeys.ContainsKey(scopeExtraKeys.First().Key) && - x.ExtraKeys[scopeExtraKeys.First().Key] == scopeExtraKeys.First().Value && - x.ExtraKeys.ContainsKey(scopeExtraKeys.Last().Key) && - x.ExtraKeys[scopeExtraKeys.Last().Key] == scopeExtraKeys.Last().Value && + x.ExtraKeys != null && ( + x.ExtraKeys.Count != globalExtraKeys.Count + scopeExtraKeys.Count || ( + x.ExtraKeys.Count == globalExtraKeys.Count + scopeExtraKeys.Count && + x.ExtraKeys.ContainsKey(globalExtraKeys.First().Key) && + x.ExtraKeys[globalExtraKeys.First().Key] == globalExtraKeys.First().Value && + x.ExtraKeys.ContainsKey(globalExtraKeys.Last().Key) && + x.ExtraKeys[globalExtraKeys.Last().Key] == globalExtraKeys.Last().Value && + x.ExtraKeys.ContainsKey(scopeExtraKeys.First().Key) && + x.ExtraKeys[scopeExtraKeys.First().Key] == scopeExtraKeys.First().Value && + x.ExtraKeys.ContainsKey(scopeExtraKeys.Last().Key) && + x.ExtraKeys[scopeExtraKeys.Last().Key] == scopeExtraKeys.Last().Value ) ) && x.LambdaContext != null && x.LambdaContext.FunctionName == lambdaContext.FunctionName && x.LambdaContext.FunctionVersion == lambdaContext.FunctionVersion &&