diff --git a/src/Serilog/Configuration/LoggerSettingsConfiguration.cs b/src/Serilog/Configuration/LoggerSettingsConfiguration.cs
index ce279f0eb..6acbf70ac 100644
--- a/src/Serilog/Configuration/LoggerSettingsConfiguration.cs
+++ b/src/Serilog/Configuration/LoggerSettingsConfiguration.cs
@@ -50,11 +50,21 @@ public LoggerConfiguration Settings(ILoggerSettings settings)
///
/// A list of key-value pairs describing logger settings.
/// Configuration object allowing method chaining.
+ /// In case of duplicate keys, the last value for the key is kept and the previous ones are ignored.
public LoggerConfiguration KeyValuePairs(IEnumerable> settings)
{
if (settings == null) throw new ArgumentNullException(nameof(settings));
+ var uniqueSettings = new Dictionary();
+ foreach (var kvp in settings)
+ {
+ uniqueSettings[kvp.Key] = kvp.Value;
+ }
+ return KeyValuePairs(uniqueSettings);
+ }
- return Settings(new KeyValuePairSettings(settings.ToDictionary(x => x.Key, x => x.Value)));
+ LoggerConfiguration KeyValuePairs(IReadOnlyDictionary settings)
+ {
+ return Settings(new KeyValuePairSettings(settings));
}
}
}
diff --git a/test/Serilog.Tests/Settings/KeyValuePairSettingsTests.cs b/test/Serilog.Tests/Settings/KeyValuePairSettingsTests.cs
index d20f57889..275f82b82 100644
--- a/test/Serilog.Tests/Settings/KeyValuePairSettingsTests.cs
+++ b/test/Serilog.Tests/Settings/KeyValuePairSettingsTests.cs
@@ -16,19 +16,24 @@ namespace Serilog.Tests.Settings
public class KeyValuePairSettingsTests
{
[Fact]
- public void DuplicateKeysCauseArgumentException()
+ public void LastValueIsTakenWhenKeysAreDuplicate()
{
- Action action = () => new LoggerConfiguration()
+ LogEvent evt = null;
+ var log = new LoggerConfiguration()
.ReadFrom.KeyValuePairs(new List>
{
- new KeyValuePair("setting", "Value"),
- new KeyValuePair("setting", "SameSettingOtherValue"),
- });
+ new KeyValuePair("enrich:with-property:App", "InitialValue"),
+ new KeyValuePair("enrich:with-property:App", "OverridenValue"),
+ new KeyValuePair("enrich:with-property:App", "FinalValue")
+ })
+ .WriteTo.Sink(new DelegatingSink(e => evt = e))
+ .CreateLogger();
- var ex = Assert.ThrowsAny(action);
- Assert.NotNull(ex);
- Assert.Contains("An item with the same key has already been added.", ex.Message);
- }
+ log.Information("Has a test property");
+
+ Assert.NotNull(evt);
+ Assert.Equal("FinalValue", evt.Properties["App"].LiteralValue());
+ }
[Fact]
public void FindsConfigurationAssemblies()
@@ -328,7 +333,7 @@ public void LoggingLevelSwitchCanBeUsedForMinimumLevelOverrides()
systemLogger.Write(Some.WarningEvent());
Assert.False(evt is null, "LoggingLevelSwitch initial level was Warning for logger System.*. It should log Warning messages for SourceContext System.Bar");
-
+
evt = null;
var controlSwitch = DummyWithLevelSwitchSink.ControlLevelSwitch;