Description
Hi, I'm raising this initially just as an issue, to check my thinking and see if there would be interest in this feature. If so, then I can potentially have a go at fully implementing this and raising a PR.
Is your feature request related to a problem? Please describe.
The Microsoft.Extensions.Logging
library supports automatically enriching your logs with tags and/or baggage from the associated System.Diagnostics
Activity
at the time of logging. This is enabled by setting the ActivityTrackingOptions
setting to either Tags
or Baggage
(or both). This is as introduced in this PR dotnet/runtime#48722 which comes off the back of this issue dotnet/runtime#46571.
I've found that setting this property doesn't seem to work when I'm using Serilog behind the Microsoft.Extensions.Logging
API. Looking into it, I believe the reason is this line here in the Microsoft.Extensions.Logging
library:
private void AddProviderRegistration(ILoggerProvider provider, bool dispose)
{
_providerRegistrations.Add(new ProviderRegistration
{
Provider = provider,
ShouldDispose = dispose
});
if (provider is ISupportExternalScope supportsExternalScope)
{
_scopeProvider ??= new LoggerFactoryScopeProvider(_factoryOptions.ActivityTrackingOptions);
supportsExternalScope.SetScopeProvider(_scopeProvider);
}
}
Here, the LoggerFactoryScopeProvider
is what does the work of pulling out the tags and baggage defined on the Activity
and making available for logging scopes. If the ILoggerProvider
supports external scopes, by implementing ISupportExternalScope
, then it can receive this LoggerFactoryScopeProvider
to use later to enrich its logs.
Unfortunately, it seems that the SerilogLoggerProvider
doesn't implement that ISupportExternalScope
interface (https://github.com/serilog/serilog-extensions-logging/blob/main/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLoggerProvider.cs), and hence misses out on this feature.
Describe the solution you'd like
Ideally, Serilog could support these Tags
and Baggage
switches on the ActivityTrackingOptions
setting, so that logs can be enriched with tags and baggage from the ongoing Activity
.
I don't have much deep experience with Serilog, so I might be a bit naïve here, but I think this might be a relatively straightforward addition to implement the ISupportExternalScope
interface.
I think we can modify the Enrich
method in SerilogLoggerProvider
, with something like (this is a quick sketch of a solution):
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
+ _externalScopeProvider?.ForEachScope((scope, state) =>
+ {
+ if (scope is IEnumerable<KeyValuePair<string, object?>> dict)
+ {
+ foreach (var kvp in dict)
+ {
+ state.AddPropertyIfAbsent(propertyFactory.CreateProperty(kvp.Key, kvp.Value));
+ }
+ }
+ }, logEvent);
List<LogEventPropertyValue>? scopeItems = null;
for (var scope = CurrentScope; scope != null; scope = scope.Parent)
{
scope.EnrichAndCreateScopeItem(logEvent, propertyFactory, out var scopeItem);
if (scopeItem != null)
{
scopeItems ??= new List<LogEventPropertyValue>();
scopeItems.Add(scopeItem);
}
}
if (scopeItems != null)
{
scopeItems.Reverse();
logEvent.AddPropertyIfAbsent(new LogEventProperty(ScopePropertyName, new SequenceValue(scopeItems)));
}
}
where we implement the ISupportExternalScope.SetScopeProvider(IExternalScopeProvider scopeProvider)
method by just storing the IExternalScopeProvider
as the field _externalScopeProvider
like:
public void SetScopeProvider(IExternalScopeProvider scopeProvider)
{
_externalScopeProvider = scopeProvider;
}
Describe alternatives you've considered
An alternative is to manually define a Serilog enricher, to do the same thing, pulling out tags and baggage and enriching the logs. This is the approach taken by in this blog post: https://www.jimmybogard.com/increasing-trace-cardinality-with-tags-and-baggage/.
However, it would be great if Serilog could support all the available options on the ActivityTrackingOptions
setting, and then allow us to rely on Microsoft's implementation for doing this.