Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 7713521

Browse files
Merge pull request #269 from nblumhardt/nested-scope-ordering
Correct the order of property additions from external scopes
2 parents 8575f90 + 68374e5 commit 7713521

File tree

5 files changed

+69
-21
lines changed

5 files changed

+69
-21
lines changed

‎src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerProvider.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,12 @@ public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
102102
}
103103
}
104104

105+
scopeItems?.Reverse();
106+
105107
_externalScopeProvider?.ForEachScope((state, accumulatingLogEvent) =>
106108
{
107-
SerilogLoggerScope.EnrichWithStateAndCreateScopeItem(accumulatingLogEvent, propertyFactory, state, out var scopeItem);
109+
SerilogLoggerScope.EnrichWithStateAndCreateScopeItem(
110+
accumulatingLogEvent, propertyFactory, state, update: true, out var scopeItem);
108111

109112
if (scopeItem != null)
110113
{
@@ -115,7 +118,6 @@ public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
115118

116119
if (scopeItems != null)
117120
{
118-
scopeItems.Reverse();
119121
logEvent.AddPropertyIfAbsent(new LogEventProperty(ScopePropertyName, new SequenceValue(scopeItems)));
120122
}
121123
}

‎src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerScope.cs

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ public void Dispose()
4747
}
4848
}
4949

50-
public void EnrichAndCreateScopeItem(LogEvent logEvent, ILogEventPropertyFactory propertyFactory, out LogEventPropertyValue? scopeItem) => EnrichWithStateAndCreateScopeItem(logEvent, propertyFactory, _state, out scopeItem);
50+
public void EnrichAndCreateScopeItem(LogEvent logEvent, ILogEventPropertyFactory propertyFactory, out LogEventPropertyValue? scopeItem) => EnrichWithStateAndCreateScopeItem(logEvent, propertyFactory, _state, update:false,out scopeItem);
5151

52-
public static void EnrichWithStateAndCreateScopeItem(LogEvent logEvent, ILogEventPropertyFactory propertyFactory, object? state, out LogEventPropertyValue? scopeItem)
52+
public static void EnrichWithStateAndCreateScopeItem(LogEvent logEvent, ILogEventPropertyFactory propertyFactory, object? state, boolupdate,out LogEventPropertyValue? scopeItem)
5353
{
5454
if (state == null)
5555
{
@@ -63,8 +63,8 @@ public static void EnrichWithStateAndCreateScopeItem(LogEvent logEvent, ILogEven
6363
// Separate handling of this case eliminates boxing of Dictionary<TKey, TValue>.Enumerator.
6464
scopeItem = null;
6565
foreach (var stateProperty in dictionary)
66-
{
67-
AddProperty(logEvent, propertyFactory, stateProperty.Key, stateProperty.Value);
66+
{
67+
AddProperty(logEvent, propertyFactory, stateProperty.Key, stateProperty.Value,update);
6868
}
6969
}
7070
else if (state is IEnumerable<KeyValuePair<string, object>> stateProperties)
@@ -79,21 +79,21 @@ public static void EnrichWithStateAndCreateScopeItem(LogEvent logEvent, ILogEven
7979
}
8080
else
8181
{
82-
AddProperty(logEvent, propertyFactory, stateProperty.Key, stateProperty.Value);
82+
AddProperty(logEvent, propertyFactory, stateProperty.Key, stateProperty.Value,update);
8383
}
8484
}
8585
}
8686
#if FEATURE_ITUPLE
8787
else if (state is System.Runtime.CompilerServices.ITuple tuple && tuple.Length == 2 && tuple[0] is string s)
8888
{
8989
scopeItem = null; // Unless it's `FormattedLogValues`, these are treated as property bags rather than scope items.
90-
AddProperty(logEvent, propertyFactory, s, tuple[1]);
90+
AddProperty(logEvent, propertyFactory, s, tuple[1],update);
9191
}
9292
#else
9393
else if (state is ValueTuple<string, object?> tuple)
9494
{
9595
scopeItem = null;
96-
AddProperty(logEvent, propertyFactory, tuple.Item1, tuple.Item2);
96+
AddProperty(logEvent, propertyFactory, tuple.Item1, tuple.Item2,update);
9797
}
9898
#endif
9999
else
@@ -102,22 +102,29 @@ public static void EnrichWithStateAndCreateScopeItem(LogEvent logEvent, ILogEven
102102
}
103103
}
104104

105-
static void AddProperty(LogEvent logEvent, ILogEventPropertyFactory propertyFactory, string key, object? value)
105+
static void AddProperty(LogEvent logEvent, ILogEventPropertyFactory propertyFactory, string key, object? value,boolupdate)
106106
{
107-
var destructureObject = false;
107+
var destructureObjects = false;
108108

109109
if (key.StartsWith('@'))
110110
{
111111
key = SerilogLogger.GetKeyWithoutFirstSymbol(SerilogLogger.DestructureDictionary, key);
112-
destructureObject = true;
112+
destructureObjects = true;
113113
}
114114
else if (key.StartsWith('$'))
115115
{
116116
key = SerilogLogger.GetKeyWithoutFirstSymbol(SerilogLogger.StringifyDictionary, key);
117117
value = value?.ToString();
118118
}
119119

120-
var property = propertyFactory.CreateProperty(key, value, destructureObject);
121-
logEvent.AddPropertyIfAbsent(property);
120+
var property = propertyFactory.CreateProperty(key, value, destructureObjects);
121+
if (update)
122+
{
123+
logEvent.AddOrUpdateProperty(property);
124+
}
125+
else
126+
{
127+
logEvent.AddPropertyIfAbsent(property);
128+
}
122129
}
123130
}

‎test/Serilog.Extensions.Logging.Tests/SerilogLoggerTests.cs

Lines changed: 43 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33

44
using System.Collections;
55
using System.Diagnostics;
6+
using Microsoft.Extensions.DependencyInjection;
67
using Serilog.Events;
78
using Microsoft.Extensions.Logging;
89
using Serilog.Debugging;
910
using Serilog.Extensions.Logging.Tests.Support;
1011
using Xunit;
1112
using Serilog.Core;
13+
// ReSharper disable AccessToDisposedClosure
1214

1315
namespace Serilog.Extensions.Logging.Tests;
1416

@@ -17,9 +19,9 @@ public class SerilogLoggerTest
1719
const string Name = "test";
1820
const string TestMessage = "This is a test";
1921

20-
static Tuple<SerilogLogger, SerilogSink> SetUp(LogLevel logLevel, IExternalScopeProvider? externalScopeProvider = null)
22+
static Tuple<SerilogLogger, CollectingSink> SetUp(LogLevel logLevel, IExternalScopeProvider? externalScopeProvider = null)
2123
{
22-
var sink = new SerilogSink();
24+
var sink = new CollectingSink();
2325

2426
var serilogLogger = new LoggerConfiguration()
2527
.WriteTo.Sink(sink)
@@ -34,7 +36,7 @@ static Tuple<SerilogLogger, SerilogSink> SetUp(LogLevel logLevel, IExternalScope
3436
provider.SetScopeProvider(externalScopeProvider);
3537
}
3638

37-
return new Tuple<SerilogLogger, SerilogSink>(logger, sink);
39+
return new Tuple<SerilogLogger, CollectingSink>(logger, sink);
3840
}
3941

4042
[Fact]
@@ -516,7 +518,7 @@ public void Dispose()
516518
}
517519
}
518520
}
519-
521+
520522
[Fact]
521523
public void MismatchedMessageTemplateParameterCountIsHandled()
522524
{
@@ -579,4 +581,41 @@ public void TraceAndSpanIdsAreCaptured()
579581
Assert.Equal(Activity.Current.TraceId, evt.TraceId);
580582
Assert.Equal(Activity.Current.SpanId, evt.SpanId);
581583
}
584+
585+
[Fact]
586+
public void LoggingScopeReplacesPropertyInNestedScope()
587+
{
588+
var sink = new CollectingSink();
589+
using var logger = new LoggerConfiguration().WriteTo.Sink(sink).CreateLogger();
590+
591+
var services = new ServiceCollection();
592+
services.AddLogging(l => l.AddSerilog(logger));
593+
594+
using var serviceProvider = services.BuildServiceProvider();
595+
var msLogger = serviceProvider.GetRequiredService<ILogger<SerilogLoggerTest>>();
596+
597+
using (msLogger.BeginScope(new Dictionary<string, object> { { "EXECUTION_TAGS", "[TAG1]" } }))
598+
{
599+
msLogger.LogInformation("Message1");
600+
using (msLogger.BeginScope(new Dictionary<string, object> { { "EXECUTION_TAGS", "[TAG2]" } }))
601+
{
602+
msLogger.LogInformation("Message2");
603+
}
604+
}
605+
606+
var logEvent = sink.Writes.FirstOrDefault(e => e.MessageTemplate.Text == "Message1");
607+
Assert.NotNull(logEvent);
608+
AssertHasScalarProperty(logEvent, "EXECUTION_TAGS", "[TAG1]");
609+
610+
logEvent = sink.Writes.FirstOrDefault(e => e.MessageTemplate.Text == "Message2");
611+
Assert.NotNull(logEvent);
612+
AssertHasScalarProperty(logEvent, "EXECUTION_TAGS", "[TAG2]");
613+
}
614+
615+
static void AssertHasScalarProperty(LogEvent logEvent, string name, object? expectedValue)
616+
{
617+
Assert.True(logEvent.Properties.TryGetValue(name, out var result));
618+
var scalar = Assert.IsType<ScalarValue>(result);
619+
Assert.Equal(expectedValue, scalar.Value);
620+
}
582621
}

‎test/Serilog.Extensions.Logging.Tests/SerilogLoggingBuilderExtensionsTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public void AddSerilogMustRegisterAnILoggerProvider()
2121
[Fact]
2222
public void AddSerilogMustRegisterAnILoggerProviderThatForwardsLogsToStaticSerilogLogger()
2323
{
24-
var sink = new SerilogSink();
24+
var sink = new CollectingSink();
2525
Log.Logger = new LoggerConfiguration()
2626
.WriteTo.Sink(sink)
2727
.CreateLogger();
@@ -39,7 +39,7 @@ public void AddSerilogMustRegisterAnILoggerProviderThatForwardsLogsToStaticSeril
3939
[Fact]
4040
public void AddSerilogMustRegisterAnILoggerProviderThatForwardsLogsToProvidedLogger()
4141
{
42-
var sink = new SerilogSink();
42+
var sink = new CollectingSink();
4343
var serilogLogger = new LoggerConfiguration()
4444
.WriteTo.Sink(sink)
4545
.CreateLogger();

‎test/Serilog.Extensions.Logging.Tests/Support/SerilogSink.cs renamed to ‎test/Serilog.Extensions.Logging.Tests/Support/CollectingSink.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
namespace Serilog.Extensions.Logging.Tests.Support;
88

9-
public class SerilogSink : ILogEventSink
9+
public class CollectingSink : ILogEventSink
1010
{
1111
public List<LogEvent> Writes { get; set; } = new();
1212

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /