Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4b7587a

Browse files
authored
Fix NullReferenceException with structured logging (#2132)
1 parent 57f93d2 commit 4b7587a

File tree

7 files changed

+109
-10
lines changed

7 files changed

+109
-10
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"Projects": [
3+
{
4+
"Name": "Amazon.Lambda.RuntimeSupport",
5+
"Type": "Patch",
6+
"ChangelogMessages": [
7+
"Fix NullReferenceException when logging a null logging message with structured logging enabled."
8+
]
9+
},
10+
{
11+
"Name": "Amazon.Lambda.Logging.AspNetCore",
12+
"Type": "Patch",
13+
"ChangelogMessages": [
14+
"Fix NullReferenceException when logging a null logging message with structured logging enabled."
15+
]
16+
}
17+
]
18+
}

Libraries/src/Amazon.Lambda.Logging.AspNetCore/LambdaILogger.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Except
7070
}
7171
}
7272

73+
if (messageTemplate == null)
74+
{
75+
messageTemplate = formatter.Invoke(state, exception);
76+
}
77+
7378
Amazon.Lambda.Core.LambdaLogger.Log(lambdaLogLevel, exception, messageTemplate, parameters.ToArray());
7479
}
7580
else

Libraries/src/Amazon.Lambda.RuntimeSupport/Helpers/ConsoleLoggerWriter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ internal void FormattedWriteLine(string level, Exception exeception, string mess
401401

402402
var messageState = new MessageState();
403403

404-
messageState.MessageTemplate = messageTemplate;
404+
messageState.MessageTemplate = messageTemplate ?? string.Empty;
405405
messageState.MessageArguments = args;
406406
messageState.TimeStamp = DateTime.UtcNow;
407407
messageState.AwsRequestId = CurrentAwsRequestId;

Libraries/src/Amazon.Lambda.RuntimeSupport/Helpers/Logging/AbstractLogMessageFormatter.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#if NET6_0_OR_GREATER
1+
#if NET6_0_OR_GREATER
22
using System;
33
using System.Collections.Concurrent;
44
using System.Collections.Generic;
@@ -285,4 +285,4 @@ public bool UsingPositionalArguments(IReadOnlyList<MessageProperty> messagePrope
285285
}
286286
}
287287
}
288-
#endif
288+
#endif

Libraries/src/Amazon.Lambda.RuntimeSupport/Helpers/Logging/JsonLogMessageFormatter.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#if NET6_0_OR_GREATER
1+
#if NET6_0_OR_GREATER
22
using System;
33
using System.Buffers;
44
using System.Collections;
@@ -48,15 +48,15 @@ public override string FormatMessage(MessageState state)
4848
if (state.MessageArguments?.Length == 0)
4949
{
5050
messageProperties = _emptyMessageProperties;
51-
message = state.MessageTemplate;
51+
message = state.MessageTemplate ?? string.Empty;
5252
}
5353
else
5454
{
5555
// Parse the message template for any message properties like "{count}".
56-
messageProperties = ParseProperties(state.MessageTemplate);
56+
messageProperties = ParseProperties(state.MessageTemplate ?? string.Empty);
5757

5858
// Replace any message properties in the message template with the provided argument values.
59-
message = ApplyMessageProperties(state.MessageTemplate, messageProperties, state.MessageArguments);
59+
message = ApplyMessageProperties(state.MessageTemplate ?? string.Empty, messageProperties, state.MessageArguments);
6060
}
6161

6262

@@ -310,4 +310,4 @@ private void FormatJsonValue(Utf8JsonWriter writer, object value, string formatA
310310
private static string ToInvariantString(object obj) => Convert.ToString(obj, CultureInfo.InvariantCulture);
311311
}
312312
}
313-
#endif
313+
#endif

Libraries/test/Amazon.Lambda.Logging.AspNetCore.Tests/LoggingTests.cs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.IO;
77
using System.Linq;
88
using System.Reflection;
9+
using System.Text;
910
using Xunit;
1011

1112
namespace Amazon.Lambda.Tests
@@ -581,6 +582,46 @@ public void TestJSONParameterLogging()
581582

582583
}
583584

585+
[Fact]
586+
public void JsonLoggingWithNoOriginalFormat()
587+
{
588+
Environment.SetEnvironmentVariable("AWS_LAMBDA_LOG_FORMAT", "JSON");
589+
try
590+
{
591+
using (var writer = new StringWriter())
592+
{
593+
ConnectLoggingActionToLogger(message => writer.Write(message));
594+
595+
var configuration = new ConfigurationBuilder()
596+
.AddJsonFile(GetAppSettingsPath("appsettings.json"))
597+
.Build();
598+
599+
var loggerOptions = new LambdaLoggerOptions(configuration);
600+
var loggerFactory = new TestLoggerFactory()
601+
.AddLambdaLogger(loggerOptions);
602+
603+
var logger = loggerFactory.CreateLogger("JSONLogging");
604+
605+
logger.Log(LogLevel.Error, new EventId(1), new Dictionary<string, object>() { { "Param1", "Value1" } }, null, (state, e) =>
606+
{
607+
var sb = new StringBuilder();
608+
foreach(var kvp in state)
609+
{
610+
sb.AppendFormat("{0}:{1}\n", kvp.Key, kvp.Value);
611+
}
612+
return sb.ToString();
613+
});
614+
615+
var text = writer.ToString();
616+
Assert.Contains("Param1:Value1", text);
617+
}
618+
}
619+
finally
620+
{
621+
Environment.SetEnvironmentVariable("AWS_LAMBDA_LOG_FORMAT", null);
622+
}
623+
}
624+
584625
private static string GetAppSettingsPath(string fileName)
585626
{
586627
return Path.Combine(APPSETTINGS_DIR, fileName);
@@ -609,7 +650,7 @@ private static void ConnectLoggingActionToLogger(Action<string> loggingAction)
609650
loggingWithLevelActionField.SetValue(null, loggingWithLevelAction);
610651

611652
Action<string, Exception, string, object[]> loggingWithExceptionLevelAction = (level, exception, message, parameters) => {
612-
var formattedMessage = $"{level}: {message}: parameter count: {parameters?.Length}\n{exception.Message}";
653+
var formattedMessage = $"{level}: {message}: parameter count: {parameters?.Length}\n{exception?.Message}";
613654
loggingAction(formattedMessage);
614655
};
615656

Libraries/test/Amazon.Lambda.RuntimeSupport.Tests/Amazon.Lambda.RuntimeSupport.UnitTests/LogMessageFormatterTests.cs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using Amazon.Lambda.RuntimeSupport.Helpers;
1+
using Amazon.Lambda.RuntimeSupport.Helpers;
22
using Amazon.Lambda.RuntimeSupport.Helpers.Logging;
33
using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities;
44
using System;
@@ -103,6 +103,41 @@ public void FormatJsonWithStringMessageProperties()
103103
Assert.Equal("Hello AWS", doc.RootElement.GetProperty("message").GetString());
104104
}
105105

106+
[Fact]
107+
public void FormatJsonNullMessageTemplate()
108+
{
109+
var timestamp = DateTime.UtcNow;
110+
var formatter = new JsonLogMessageFormatter();
111+
var state = new MessageState()
112+
{
113+
MessageTemplate = null,
114+
AwsRequestId = "1234",
115+
Level = Helpers.LogLevelLoggerWriter.LogLevel.Warning,
116+
TimeStamp = timestamp
117+
};
118+
119+
var json = formatter.FormatMessage(state);
120+
var doc = JsonDocument.Parse(json);
121+
Assert.Equal(string.Empty, doc.RootElement.GetProperty("message").GetString());
122+
Assert.Equal("1234", doc.RootElement.GetProperty("requestId").GetString());
123+
124+
// Currently the arguments are ignored because they don't exist in the message template but
125+
// having arguments uses a different code path so we need to make sure a NPE doesn't happen.
126+
state = new MessageState()
127+
{
128+
MessageTemplate = null,
129+
MessageArguments = new object[] { true },
130+
AwsRequestId = "1234",
131+
Level = Helpers.LogLevelLoggerWriter.LogLevel.Warning,
132+
TimeStamp = timestamp
133+
};
134+
135+
json = formatter.FormatMessage(state);
136+
doc = JsonDocument.Parse(json);
137+
Assert.Equal(string.Empty, doc.RootElement.GetProperty("message").GetString());
138+
Assert.Equal("1234", doc.RootElement.GetProperty("requestId").GetString());
139+
}
140+
106141
[Fact]
107142
public void FormatJsonWithAllPossibleTypes()
108143
{

0 commit comments

Comments
 (0)