Skip to content

fix: Handle Exceptions and Prevent application from crashing when using Logger #538

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 2 commits into from
Feb 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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 @@ -12,6 +12,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