You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Since version 9.0.1 of Serilog.Extensions.Logging, there has been a change in how values in a scope override each other in LogEvents. Previously, the value passed directly to the log method would take precedence over values defined in scopes. Now, the innermost scope value takes precedence instead.
Reproduction Code
[Fact]publicasyncTaskPropertyOverride_Scope(){varlistener=newLogEventListener();Log.Logger=newLoggerConfiguration().Enrich.FromLogContext().WriteTo.Sink(listener).CreateLogger();varprovider=newServiceCollection().AddLogging(m =>m.AddSerilog(Log.Logger,dispose:true)).BuildServiceProvider();varlogger=provider.GetRequiredService<ILogger<ScopeTests>>();using(logger.BeginScope(newDictionary<string,object?>{{"Value",1}}))using(logger.BeginScope(newDictionary<string,object?>{{"Value",2}})){logger.LogInformation("Value: {Value}",3);}Assert.True(awaitlistener.WaitAsync(1,TimeSpan.FromSeconds(3)));varlogEvent=listener.Events.First();varvalue=(logEvent.Properties["Value"]asScalarValue)?.Value;// Expected behavior before Serilog.Extensions.Logging 9.0.1// Assert.Equal(3, value);// Actual behavior since Serilog.Extensions.Logging 9.0.1Assert.Equal(2,value);}publicclassLogEventListener:ILogEventSink{privatereadonlySemaphoreSlim_semaphore=new(0);publicList<LogEvent>Events{get;}=[];publicvirtualvoidEmit(LogEventlogEvent){Events.Add(logEvent);_semaphore.Release();}publicasyncTask<bool>WaitAsync(intcount,TimeSpantimeout,CancellationTokencancellationToken=default){for(vari=0;i<count;++i){varflag=await_semaphore.WaitAsync(timeout,cancellationToken);if(flag==false)returnfalse;// timeout}returntrue;}}
Comparing to LogContext
When using Serilog's native LogContext directly (instead of through Microsoft.Extensions.Logging), the behavior is different and matches the previous behavior:
using(LogContext.PushProperty("Value",1))using(LogContext.PushProperty("Value",2)){logger.Information("Value: {Value}",3);}// the "Value" will be 3.
Expected Behavior
Before version 9.0.1, when logging with a parameter that shares the same name as a property in a scope, the directly passed value (3 in this case) would take precedence over any scope values, which is consistent with how Serilog's native LogContext API works.
Actual Behavior
Since version 9.0.1, the innermost scope value (2 in this case) takes precedence over the value passed directly to the log method (3), creating inconsistency with Serilog's native behavior.
Questions
Is this a deliberate change in behavior or an unintended side effect?
If unintended, can the previous behavior be restored?
The text was updated successfully, but these errors were encountered:
Thanks for the note! I think this is an unintended consequence of the external scope provider support added in v9, which would have been masked by another issue in the 9.0.0 build, but revealed by the 9.0.1 fix.
I am not sure whether Microsoft.Extensions.Logging sets any expectations around how conflicts between event and scope properties should be resolved, and thus whether this is a bug or just unspecified behavior. A proposal/PR that reverts to the earlier behavior would be welcome, but I'm not sure it's possible without significant performance costs - needs some investigation.
Description
Since version 9.0.1 of Serilog.Extensions.Logging, there has been a change in how values in a scope override each other in LogEvents. Previously, the value passed directly to the log method would take precedence over values defined in scopes. Now, the innermost scope value takes precedence instead.
Reproduction Code
Comparing to LogContext
When using Serilog's native LogContext directly (instead of through Microsoft.Extensions.Logging), the behavior is different and matches the previous behavior:
Expected Behavior
Before version 9.0.1, when logging with a parameter that shares the same name as a property in a scope, the directly passed value (3 in this case) would take precedence over any scope values, which is consistent with how Serilog's native
LogContext
API works.Actual Behavior
Since version 9.0.1, the innermost scope value (2 in this case) takes precedence over the value passed directly to the log method (3), creating inconsistency with Serilog's native behavior.
Questions
The text was updated successfully, but these errors were encountered: