diff --git a/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerProvider.cs b/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerProvider.cs index 2ad7738..9f66537 100644 --- a/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerProvider.cs +++ b/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerProvider.cs @@ -105,13 +105,13 @@ public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) scopeCollector.ReverseItems(); - _externalScopeProvider?.ForEachScope(static (state, parameters) => + _externalScopeProvider?.ForEachScopeReversed(static (state, parameters) => { SerilogLoggerScope.EnrichWithStateAndCreateScopeItem( parameters.LogEvent, parameters.PropertyFactory, state, - update: true, + update: false, out var scopeItem); if (scopeItem != null) @@ -177,3 +177,30 @@ public void AddItem(LogEventPropertyValue scopeItem) } } } + + +file static class Extensions +{ + public static void TryClear(this List list) + { + if (list.Count > 0) + list.Clear(); + } + + private static readonly ThreadLocal> _list = new(() => []); + + public static void ForEachScopeReversed(this IExternalScopeProvider provider, Action callback, TState state) + { + var list = _list.Value!; + list.TryClear(); + + provider.ForEachScope((m, _) => list.Add(m), state); + + for (var i = list.Count - 1; i >= 0; i--) + { + callback(list[i], state); + } + + list.TryClear(); + } +} diff --git a/test/Serilog.Extensions.Logging.Tests/SerilogLoggerTests.cs b/test/Serilog.Extensions.Logging.Tests/SerilogLoggerTests.cs index bbbfb14..3ef97e5 100644 --- a/test/Serilog.Extensions.Logging.Tests/SerilogLoggerTests.cs +++ b/test/Serilog.Extensions.Logging.Tests/SerilogLoggerTests.cs @@ -634,4 +634,33 @@ public void ConflictingEventIdTemplatePropertyIsIgnored() var recordedEventId = Assert.IsType(recordedEventIdPropertyValue.Value); Assert.Equal(loggedEventId, recordedEventId); } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void LoggingScopeShouldNotReplacePropertyInLogEvent(bool withExternalScopeProvider) + { + var sink = new CollectingSink(); + using var logger = new LoggerConfiguration().WriteTo.Sink(sink).CreateLogger(); + var serilogLoggerProvider = new SerilogLoggerProvider(logger); + + var services = new ServiceCollection(); + services.AddLogging(l => l.AddSerilog(logger)); + + using var serviceProvider = services.BuildServiceProvider(); + var msLogger = withExternalScopeProvider + ? serviceProvider.GetRequiredService>() + : serilogLoggerProvider.CreateLogger(Name); + + using (msLogger.BeginScope(new Dictionary { { "Value", 1 } })) + using (msLogger.BeginScope(new Dictionary { { "Value", 2 } })) + { + msLogger.LogInformation("Value: {Value}", 3); + } + + var logEvent = sink.Writes.First(); + var value = (logEvent.Properties["Value"] as ScalarValue)?.Value; + + Assert.Equal(3, value); + } }