From f9802e2cadf22f70cbe9ddc3b5fffc584710f316 Mon Sep 17 00:00:00 2001 From: Rolf Kristensen Date: Wed, 22 Mar 2023 23:47:47 +0100 Subject: [PATCH] NLogBeginScopeParser - Skip capture of nested state when List + Array + Dictionary --- .../Logging/NLogBeginScopeParser.cs | 15 +++++++++++- .../CustomBeginScopeTest.cs | 23 +++++++++++++++++++ .../Extensions/ConfigureExtensionsTests.cs | 2 +- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/NLog.Extensions.Logging/Logging/NLogBeginScopeParser.cs b/src/NLog.Extensions.Logging/Logging/NLogBeginScopeParser.cs index 72c6972b..ce6607b7 100644 --- a/src/NLog.Extensions.Logging/Logging/NLogBeginScopeParser.cs +++ b/src/NLog.Extensions.Logging/Logging/NLogBeginScopeParser.cs @@ -31,10 +31,20 @@ public IDisposable ParseBeginScope(T state) { if (state is IReadOnlyList> scopePropertyList) { + if (scopePropertyList is IList) + return ScopeContext.PushNestedStateProperties(null, scopePropertyList); // Probably List/Array without nested state + object scopeObject = scopePropertyList; scopePropertyList = ParseScopeProperties(scopePropertyList); return ScopeContext.PushNestedStateProperties(scopeObject, scopePropertyList); } + else if (state is IReadOnlyCollection> scopeProperties) + { + if (scopeProperties is IDictionary) + return ScopeContext.PushNestedStateProperties(null, scopeProperties); // Probably Dictionary without nested state + else + return ScopeContext.PushNestedStateProperties(scopeProperties, scopeProperties); + } if (!(state is string)) { @@ -181,7 +191,10 @@ public static IDisposable CaptureScopeProperties(IEnumerable scopePropertyCollec propertyList.Add(propertyValue.Value); } - return ScopeContext.PushNestedStateProperties(scopePropertyCollection, propertyList); + if (scopePropertyCollection is IList || scopePropertyCollection is IDictionary) + return ScopeContext.PushNestedStateProperties(null, propertyList); // Probably List/Array/Dictionary without nested state + else + return ScopeContext.PushNestedStateProperties(scopePropertyCollection, propertyList); } public static IDisposable CaptureScopeProperty(TState scopeProperty, ExtractorDictionary stateExtractor) diff --git a/test/NLog.Extensions.Logging.Tests/CustomBeginScopeTest.cs b/test/NLog.Extensions.Logging.Tests/CustomBeginScopeTest.cs index ae98df8d..6a4e900e 100644 --- a/test/NLog.Extensions.Logging.Tests/CustomBeginScopeTest.cs +++ b/test/NLog.Extensions.Logging.Tests/CustomBeginScopeTest.cs @@ -65,6 +65,17 @@ public void TestNonSerializableSayNothing() Assert.Equal("Nothing", target.Logs[0]); } + [Fact] + public void TestNonSerializableSaySomething() + { + var runner = GetRunner(); + var target = new Targets.MemoryTarget { Layout = "${message}${scopeproperty:Say}" }; + ConfigureNLog(target); + runner.SaySomething().Wait(); + Assert.Single(target.Logs); + Assert.Equal("SaySomething", target.Logs[0]); + } + public class CustomBeginScopeTestRunner { private readonly ILogger _logger; @@ -111,6 +122,18 @@ public async Task SayNothing() _logger.LogInformation("Nothing"); } } + + public async Task SaySomething() + { + using (var scopeState = _logger.BeginScope(new Dictionary() + { + { "Say", "Something" }, + })) + { + await Task.Yield(); + _logger.LogInformation("Say"); + } + } } private class ActionLogScope : IReadOnlyList> diff --git a/test/NLog.Extensions.Logging.Tests/Extensions/ConfigureExtensionsTests.cs b/test/NLog.Extensions.Logging.Tests/Extensions/ConfigureExtensionsTests.cs index 0a481588..4f024f5d 100644 --- a/test/NLog.Extensions.Logging.Tests/Extensions/ConfigureExtensionsTests.cs +++ b/test/NLog.Extensions.Logging.Tests/Extensions/ConfigureExtensionsTests.cs @@ -70,7 +70,7 @@ public void AddNLog_LoggerFactory_IncludeActivityIdsWithBeginScope() var logger = loggerFactory.CreateLogger(nameof(AddNLog_LoggerFactory_IncludeActivityIdsWithBeginScope)); var activity = new System.Diagnostics.Activity("TestActivity").SetParentId("42").Start(); var scopeProperties = new Dictionary { { "RequestId", "123" }, { "RequestPath", "Unknown" } }; - using (logger.BeginScope(scopeProperties.ToList())) + using (logger.BeginScope(new ArraySegment>(scopeProperties.ToArray()))) { logger.LogInformation(default(EventId), "test message with {0} arg", 1); }