diff --git a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs index e5664ec2..525a26cb 100644 --- a/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs +++ b/libraries/src/AWS.Lambda.Powertools.Logging/Internal/PowertoolsLogger.cs @@ -396,14 +396,26 @@ private static bool CustomFormatter(TState state, Exception exception, o return false; #if NET8_0_OR_GREATER - var stateKeys = (state as IEnumerable>)? - .ToDictionary(i => i.Key, i => PowertoolsLoggerHelpers.ObjectToDictionary(i.Value)); + var stateKeys = new Dictionary(); + if (state is IEnumerable> keyValuePairs) + { + foreach (var kvp in keyValuePairs) + { + stateKeys[kvp.Key] = PowertoolsLoggerHelpers.ObjectToDictionary(kvp.Value); + } + } #else - var stateKeys = (state as IEnumerable>)? - .ToDictionary(i => i.Key, i => i.Value); +var stateKeys = new Dictionary(); +if (state is IEnumerable> keyValuePairs) +{ + foreach (var kvp in keyValuePairs) + { + stateKeys[kvp.Key] = kvp.Value; + } +} #endif - if (stateKeys is null || stateKeys.Count != 2) + if (stateKeys.Count != 2) return false; if (!stateKeys.TryGetValue(_originalformat, out var originalFormat)) diff --git a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs index 81546c3d..1aff9187 100644 --- a/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs +++ b/libraries/tests/AWS.Lambda.Powertools.Logging.Tests/PowertoolsLoggerTest.cs @@ -1750,6 +1750,48 @@ public void Log_Cold_Start(bool willLog, string awsInitType) // Assert Assert.Contains($"\"coldStart\":{willLog.ToString().ToLower()}", outPut); } + + [Fact] + public void Log_WhenDuplicateKeysInState_LastValueWins() + { + // Arrange + var loggerName = Guid.NewGuid().ToString(); + var service = Guid.NewGuid().ToString(); + var logLevel = LogLevel.Information; + + var configurations = Substitute.For(); + configurations.Service.Returns(service); + configurations.LogLevel.Returns(logLevel.ToString()); + configurations.LoggerOutputCase.Returns(LoggerOutputCase.PascalCase.ToString()); + + var systemWrapper = Substitute.For(); + + var loggerConfiguration = new PowertoolsLoggerConfiguration + { + Service = service, + MinimumLogLevel = logLevel, + LoggerOutputCase = LoggerOutputCase.PascalCase, + LogOutput = systemWrapper + }; + + var provider = new PowertoolsLoggerProvider(loggerConfiguration, configurations); + var logger = provider.CreateLogger(loggerName); + + // Create state with duplicate keys (simulating duplicate HTTP headers) + var stateWithDuplicates = new List> + { + new("Content-Type", "application/json"), + new("Content-Type", "application/x-www-form-urlencoded"), // This should win + new("Accept", "text/html"), + new("Accept", "*/*") // This should win + }; + + // Act - This should not throw an exception + logger.Log(logLevel, new EventId(), stateWithDuplicates, null, (state, ex) => "Test message"); + + // Assert + systemWrapper.Received(1).WriteLine(Arg.Any()); + } public void Dispose() {