Skip to content

Commit

Permalink
Merge pull request #538 from hjgraca/hendle-exception-logger
Browse files Browse the repository at this point in the history
fix: Handle Exceptions and Prevent application from crashing when using Logger
  • Loading branch information
hjgraca authored Feb 16, 2024
2 parents 741bff4 + 5159cd8 commit efec6fb
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 29 deletions.
52 changes: 33 additions & 19 deletions libraries/src/AWS.Lambda.Powertools.Logging/LoggerExtensions.cs
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 Down Expand Up @@ -187,7 +187,7 @@ public static void Log(this ILogger logger, LogLevel logLevel, Exception excepti
#region ExtraKeys Logger Extentions

#region Debug

/// <summary>
/// Formats and writes a debug log message.
/// </summary>
Expand Down Expand Up @@ -242,15 +242,16 @@ public static void LogDebug<T>(this ILogger logger, T extraKeys, Exception excep
/// <param name="message">Format string of the log message in message template format. Example: <c>"User {User} logged in from {Address}"</c></param>
/// <param name="args">An object array that contains zero or more objects to format.</param>
/// <example>logger.LogDebug(extraKeys, "Processing request from {Address}", address)</example>
public static void LogDebug<T>(this ILogger logger, T extraKeys, string message, params object[] args) where T : class
public static void LogDebug<T>(this ILogger logger, T extraKeys, string message, params object[] args)
where T : class
{
Log(logger, LogLevel.Debug, extraKeys, message, args);
}

#endregion

#region Trace

/// <summary>
/// Formats and writes a trace log message.
/// </summary>
Expand Down Expand Up @@ -305,15 +306,16 @@ public static void LogTrace<T>(this ILogger logger, T extraKeys, Exception excep
/// <param name="message">Format string of the log message in message template format. Example: <c>"User {User} logged in from {Address}"</c></param>
/// <param name="args">An object array that contains zero or more objects to format.</param>
/// <example>logger.LogTrace(extraKeys, "Processing request from {Address}", address)</example>
public static void LogTrace<T>(this ILogger logger, T extraKeys, string message, params object[] args) where T : class
public static void LogTrace<T>(this ILogger logger, T extraKeys, string message, params object[] args)
where T : class
{
Log(logger, LogLevel.Trace, extraKeys, message, args);
}

#endregion

#region Information

/// <summary>
/// Formats and writes an informational log message.
/// </summary>
Expand Down Expand Up @@ -368,11 +370,12 @@ public static void LogInformation<T>(this ILogger logger, T extraKeys, Exception
/// <param name="message">Format string of the log message in message template format. Example: <c>"User {User} logged in from {Address}"</c></param>
/// <param name="args">An object array that contains zero or more objects to format.</param>
/// <example>logger.LogInformation(extraKeys, "Processing request from {Address}", address)</example>
public static void LogInformation<T>(this ILogger logger, T extraKeys, string message, params object[] args) where T : class
public static void LogInformation<T>(this ILogger logger, T extraKeys, string message, params object[] args)
where T : class
{
Log(logger, LogLevel.Information, extraKeys, message, args);
}

#endregion

#region Warning
Expand Down Expand Up @@ -431,11 +434,12 @@ public static void LogWarning<T>(this ILogger logger, T extraKeys, Exception exc
/// <param name="message">Format string of the log message in message template format. Example: <c>"User {User} logged in from {Address}"</c></param>
/// <param name="args">An object array that contains zero or more objects to format.</param>
/// <example>logger.LogWarning(extraKeys, "Processing request from {Address}", address)</example>
public static void LogWarning<T>(this ILogger logger, T extraKeys, string message, params object[] args) where T : class
public static void LogWarning<T>(this ILogger logger, T extraKeys, string message, params object[] args)
where T : class
{
Log(logger, LogLevel.Warning, extraKeys, message, args);
}

#endregion

#region Error
Expand Down Expand Up @@ -494,7 +498,8 @@ public static void LogError<T>(this ILogger logger, T extraKeys, Exception excep
/// <param name="message">Format string of the log message in message template format. Example: <c>"User {User} logged in from {Address}"</c></param>
/// <param name="args">An object array that contains zero or more objects to format.</param>
/// <example>logger.LogError(extraKeys, "Processing request from {Address}", address)</example>
public static void LogError<T>(this ILogger logger, T extraKeys, string message, params object[] args) where T : class
public static void LogError<T>(this ILogger logger, T extraKeys, string message, params object[] args)
where T : class
{
Log(logger, LogLevel.Error, extraKeys, message, args);
}
Expand Down Expand Up @@ -557,15 +562,16 @@ public static void LogCritical<T>(this ILogger logger, T extraKeys, Exception ex
/// <param name="message">Format string of the log message in message template format. Example: <c>"User {User} logged in from {Address}"</c></param>
/// <param name="args">An object array that contains zero or more objects to format.</param>
/// <example>logger.LogCritical(extraKeys, "Processing request from {Address}", address)</example>
public static void LogCritical<T>(this ILogger logger, T extraKeys, string message, params object[] args) where T : class
public static void LogCritical<T>(this ILogger logger, T extraKeys, string message, params object[] args)
where T : class
{
Log(logger, LogLevel.Critical, extraKeys, message, args);
}

#endregion

#region Log

/// <summary>
/// Formats and writes a log message at the specified log level.
/// </summary>
Expand Down Expand Up @@ -630,11 +636,19 @@ public static void Log<T>(this ILogger logger, LogLevel logLevel, T extraKeys, E
/// <param name="message">Format string of the log message in message template format. Example: <c>"User {User} logged in from {Address}"</c></param>
/// <param name="args">An object array that contains zero or more objects to format.</param>
/// <example>logger.Log(LogLevel.Information, extraKeys, "Processing request from {Address}", address)</example>
public static void Log<T>(this ILogger logger, LogLevel logLevel, T extraKeys, string message, params object[] args) where T : class
public static void Log<T>(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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
<!-- More info https://learn.microsoft.com/en-us/nuget/consume-packages/central-package-management -->
<PackageReference Include="Amazon.Lambda.ApplicationLoadBalancerEvents" />
<PackageReference Include="Amazon.Lambda.APIGatewayEvents" />
<PackageReference Include="Amazon.Lambda.Core" />
<PackageReference Include="Amazon.Lambda.TestUtilities" />
<PackageReference Include="coverlet.collector" >
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down
Original file line number Diff line number Diff line change
@@ -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;

Expand All @@ -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<string, string>
{
{"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<string, object>("aws",1), new KeyValuePair<string, object>("aws",2)});

return "OK";
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Threading.Tasks;
using Amazon.Lambda.TestUtilities;
using Xunit;

namespace AWS.Lambda.Powertools.Logging.Tests.Handlers;
Expand All @@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 &&
Expand Down

0 comments on commit efec6fb

Please sign in to comment.