Skip to content

Commit efec6fb

Browse files
authored
Merge pull request #538 from hjgraca/hendle-exception-logger
fix: Handle Exceptions and Prevent application from crashing when using Logger
2 parents 741bff4 + 5159cd8 commit efec6fb

File tree

5 files changed

+94
-29
lines changed

5 files changed

+94
-29
lines changed

libraries/src/AWS.Lambda.Powertools.Logging/LoggerExtensions.cs

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
/*
22
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3-
*
3+
*
44
* Licensed under the Apache License, Version 2.0 (the "License").
55
* You may not use this file except in compliance with the License.
66
* A copy of the License is located at
7-
*
7+
*
88
* http://aws.amazon.com/apache2.0
9-
*
9+
*
1010
* or in the "license" file accompanying this file. This file is distributed
1111
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
1212
* 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
187187
#region ExtraKeys Logger Extentions
188188

189189
#region Debug
190-
190+
191191
/// <summary>
192192
/// Formats and writes a debug log message.
193193
/// </summary>
@@ -242,15 +242,16 @@ public static void LogDebug<T>(this ILogger logger, T extraKeys, Exception excep
242242
/// <param name="message">Format string of the log message in message template format. Example: <c>"User {User} logged in from {Address}"</c></param>
243243
/// <param name="args">An object array that contains zero or more objects to format.</param>
244244
/// <example>logger.LogDebug(extraKeys, "Processing request from {Address}", address)</example>
245-
public static void LogDebug<T>(this ILogger logger, T extraKeys, string message, params object[] args) where T : class
245+
public static void LogDebug<T>(this ILogger logger, T extraKeys, string message, params object[] args)
246+
where T : class
246247
{
247248
Log(logger, LogLevel.Debug, extraKeys, message, args);
248249
}
249-
250+
250251
#endregion
251252

252253
#region Trace
253-
254+
254255
/// <summary>
255256
/// Formats and writes a trace log message.
256257
/// </summary>
@@ -305,15 +306,16 @@ public static void LogTrace<T>(this ILogger logger, T extraKeys, Exception excep
305306
/// <param name="message">Format string of the log message in message template format. Example: <c>"User {User} logged in from {Address}"</c></param>
306307
/// <param name="args">An object array that contains zero or more objects to format.</param>
307308
/// <example>logger.LogTrace(extraKeys, "Processing request from {Address}", address)</example>
308-
public static void LogTrace<T>(this ILogger logger, T extraKeys, string message, params object[] args) where T : class
309+
public static void LogTrace<T>(this ILogger logger, T extraKeys, string message, params object[] args)
310+
where T : class
309311
{
310312
Log(logger, LogLevel.Trace, extraKeys, message, args);
311313
}
312314

313315
#endregion
314316

315317
#region Information
316-
318+
317319
/// <summary>
318320
/// Formats and writes an informational log message.
319321
/// </summary>
@@ -368,11 +370,12 @@ public static void LogInformation<T>(this ILogger logger, T extraKeys, Exception
368370
/// <param name="message">Format string of the log message in message template format. Example: <c>"User {User} logged in from {Address}"</c></param>
369371
/// <param name="args">An object array that contains zero or more objects to format.</param>
370372
/// <example>logger.LogInformation(extraKeys, "Processing request from {Address}", address)</example>
371-
public static void LogInformation<T>(this ILogger logger, T extraKeys, string message, params object[] args) where T : class
373+
public static void LogInformation<T>(this ILogger logger, T extraKeys, string message, params object[] args)
374+
where T : class
372375
{
373376
Log(logger, LogLevel.Information, extraKeys, message, args);
374377
}
375-
378+
376379
#endregion
377380

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

441445
#region Error
@@ -494,7 +498,8 @@ public static void LogError<T>(this ILogger logger, T extraKeys, Exception excep
494498
/// <param name="message">Format string of the log message in message template format. Example: <c>"User {User} logged in from {Address}"</c></param>
495499
/// <param name="args">An object array that contains zero or more objects to format.</param>
496500
/// <example>logger.LogError(extraKeys, "Processing request from {Address}", address)</example>
497-
public static void LogError<T>(this ILogger logger, T extraKeys, string message, params object[] args) where T : class
501+
public static void LogError<T>(this ILogger logger, T extraKeys, string message, params object[] args)
502+
where T : class
498503
{
499504
Log(logger, LogLevel.Error, extraKeys, message, args);
500505
}
@@ -557,15 +562,16 @@ public static void LogCritical<T>(this ILogger logger, T extraKeys, Exception ex
557562
/// <param name="message">Format string of the log message in message template format. Example: <c>"User {User} logged in from {Address}"</c></param>
558563
/// <param name="args">An object array that contains zero or more objects to format.</param>
559564
/// <example>logger.LogCritical(extraKeys, "Processing request from {Address}", address)</example>
560-
public static void LogCritical<T>(this ILogger logger, T extraKeys, string message, params object[] args) where T : class
565+
public static void LogCritical<T>(this ILogger logger, T extraKeys, string message, params object[] args)
566+
where T : class
561567
{
562568
Log(logger, LogLevel.Critical, extraKeys, message, args);
563569
}
564570

565571
#endregion
566572

567573
#region Log
568-
574+
569575
/// <summary>
570576
/// Formats and writes a log message at the specified log level.
571577
/// </summary>
@@ -630,11 +636,19 @@ public static void Log<T>(this ILogger logger, LogLevel logLevel, T extraKeys, E
630636
/// <param name="message">Format string of the log message in message template format. Example: <c>"User {User} logged in from {Address}"</c></param>
631637
/// <param name="args">An object array that contains zero or more objects to format.</param>
632638
/// <example>logger.Log(LogLevel.Information, extraKeys, "Processing request from {Address}", address)</example>
633-
public static void Log<T>(this ILogger logger, LogLevel logLevel, T extraKeys, string message, params object[] args) where T : class
639+
public static void Log<T>(this ILogger logger, LogLevel logLevel, T extraKeys, string message, params object[] args)
640+
where T : class
634641
{
635-
Log(logger, logLevel, extraKeys, 0, null, message, args);
642+
try
643+
{
644+
Log(logger, logLevel, extraKeys, 0, null, message, args);
645+
}
646+
catch (Exception e)
647+
{
648+
logger.Log(LogLevel.Error, 0, e, "Powertools internal error");
649+
}
636650
}
637-
651+
638652
#endregion
639653

640654
#endregion

libraries/tests/AWS.Lambda.Powertools.Logging.Tests/AWS.Lambda.Powertools.Logging.Tests.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
<!-- More info https://learn.microsoft.com/en-us/nuget/consume-packages/central-package-management -->
1212
<PackageReference Include="Amazon.Lambda.ApplicationLoadBalancerEvents" />
1313
<PackageReference Include="Amazon.Lambda.APIGatewayEvents" />
14+
<PackageReference Include="Amazon.Lambda.Core" />
15+
<PackageReference Include="Amazon.Lambda.TestUtilities" />
1416
<PackageReference Include="coverlet.collector" >
1517
<PrivateAssets>all</PrivateAssets>
1618
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>

libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Handlers/ExceptionFunctionHandler.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Globalization;
34
using System.Threading.Tasks;
5+
using Amazon.Lambda.Core;
46

57
namespace AWS.Lambda.Powertools.Logging.Tests.Handlers;
68

@@ -20,4 +22,34 @@ private void ThisThrows()
2022
{
2123
throw new NullReferenceException();
2224
}
25+
26+
[Logging(CorrelationIdPath = "/1//", LogEvent = true, Service = null, SamplingRate = 10000d)]
27+
public string HandlerLoggerForExceptions(string input, ILambdaContext context)
28+
{
29+
// Edge cases and bad code to force exceptions
30+
31+
Logger.LogInformation("Hello {input}", input);
32+
Logger.LogError("Hello {input}", input);
33+
Logger.LogCritical("Hello {input}", input);
34+
Logger.LogDebug("Hello {input}", input);
35+
Logger.LogTrace("Hello {input}", input);
36+
37+
Logger.LogInformation("Testing with parameter Log Information Method {company}", new[] { "AWS" });
38+
39+
var customKeys = new Dictionary<string, string>
40+
{
41+
{"test1", "value1"},
42+
{"test2", "value2"}
43+
};
44+
Logger.LogInformation(customKeys, "Retrieved data for city {cityName} with count {company}", "AWS");
45+
46+
Logger.AppendKey("aws",1);
47+
Logger.AppendKey("aws",3);
48+
49+
Logger.RemoveKeys("test");
50+
51+
Logger.AppendKeys(new[]{ new KeyValuePair<string, object>("aws",1), new KeyValuePair<string, object>("aws",2)});
52+
53+
return "OK";
54+
}
2355
}

libraries/tests/AWS.Lambda.Powertools.Logging.Tests/Handlers/ExceptionFunctionHandlerTests.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Threading.Tasks;
3+
using Amazon.Lambda.TestUtilities;
34
using Xunit;
45

56
namespace AWS.Lambda.Powertools.Logging.Tests.Handlers;
@@ -20,4 +21,19 @@ public async Task Stack_Trace_Included_When_Decorator_Present()
2021
Assert.StartsWith("at AWS.Lambda.Powertools.Logging.Tests.Handlers.ExceptionFunctionHandler.ThisThrows()", tracedException.StackTrace?.TrimStart());
2122

2223
}
24+
25+
[Fact]
26+
public void Utility_Should_Not_Throw_Exceptions_To_Client()
27+
{
28+
// Arrange
29+
var lambdaContext = new TestLambdaContext();
30+
31+
var handler = new ExceptionFunctionHandler();
32+
33+
// Act
34+
var res = handler.HandlerLoggerForExceptions("aws",lambdaContext);
35+
36+
// Assert
37+
Assert.Equal("OK", res);
38+
}
2339
}

libraries/tests/AWS.Lambda.Powertools.Logging.Tests/LogFormatterTest.cs

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -138,16 +138,17 @@ public void Log_WhenCustomFormatter_LogsCustomFormat()
138138
x.Level == logLevel &&
139139
x.Message.ToString() == message &&
140140
x.Exception == null &&
141-
x.ExtraKeys != null &&
142-
x.ExtraKeys.Count == globalExtraKeys.Count + scopeExtraKeys.Count &&
143-
x.ExtraKeys.ContainsKey(globalExtraKeys.First().Key) &&
144-
x.ExtraKeys[globalExtraKeys.First().Key] == globalExtraKeys.First().Value &&
145-
x.ExtraKeys.ContainsKey(globalExtraKeys.Last().Key) &&
146-
x.ExtraKeys[globalExtraKeys.Last().Key] == globalExtraKeys.Last().Value &&
147-
x.ExtraKeys.ContainsKey(scopeExtraKeys.First().Key) &&
148-
x.ExtraKeys[scopeExtraKeys.First().Key] == scopeExtraKeys.First().Value &&
149-
x.ExtraKeys.ContainsKey(scopeExtraKeys.Last().Key) &&
150-
x.ExtraKeys[scopeExtraKeys.Last().Key] == scopeExtraKeys.Last().Value &&
141+
x.ExtraKeys != null && (
142+
x.ExtraKeys.Count != globalExtraKeys.Count + scopeExtraKeys.Count || (
143+
x.ExtraKeys.Count == globalExtraKeys.Count + scopeExtraKeys.Count &&
144+
x.ExtraKeys.ContainsKey(globalExtraKeys.First().Key) &&
145+
x.ExtraKeys[globalExtraKeys.First().Key] == globalExtraKeys.First().Value &&
146+
x.ExtraKeys.ContainsKey(globalExtraKeys.Last().Key) &&
147+
x.ExtraKeys[globalExtraKeys.Last().Key] == globalExtraKeys.Last().Value &&
148+
x.ExtraKeys.ContainsKey(scopeExtraKeys.First().Key) &&
149+
x.ExtraKeys[scopeExtraKeys.First().Key] == scopeExtraKeys.First().Value &&
150+
x.ExtraKeys.ContainsKey(scopeExtraKeys.Last().Key) &&
151+
x.ExtraKeys[scopeExtraKeys.Last().Key] == scopeExtraKeys.Last().Value ) ) &&
151152
x.LambdaContext != null &&
152153
x.LambdaContext.FunctionName == lambdaContext.FunctionName &&
153154
x.LambdaContext.FunctionVersion == lambdaContext.FunctionVersion &&

0 commit comments

Comments
 (0)