I have the need to add information to the log scopes in .NET and they need to survive longer than a single method call...
Usualy the samples always tell us to use log scopes like this
public void DoSomething()
{
using(Logger.BeginScope("Instance id {Guid}", strGuid)
{
Logger.LogInformation("did something");
}
}
This would need to wrap every public accessible with the begin scope call....
public class SampleServivce : IDisposable
{
public readonly ILogger<SampleService> Logger;
private IDisposable _logScope;
public SampleService(ILogger<SampleService> logger)
{
Logger = logger;
_logScope = Logger.BeginScope("Instance id {Guid}", Guid.NewGuid().ToString();
}
public void DoSomething()
{
Logger.LogInformation("did something");
}
public void Dispose()
{
logScope?.Dispose();
}
}
The second idea would be to create the scope in the constructor and dispose it in the dispose method. And this is where the
This post gives greater explanation why this would not work and yes, I can confirm this won't work because I am currently troubleshooting "wrong log scope info".
What our setup extends is the layer we have multiple instances of background services waiting for and doing tasks up on demand. Unfortunatly some scoped services required us to create dedicated service scopes per instance of background workers and requesting the services on demand...
So we do ...
public class BackgroundWorker1 : BackgroundService
{
private string _workerInstance = Guid.NewGuid().ToString();
private IDisposable _logScope;
private IServiceScope _serviceScope;
public readonly IServiceScopeFactory ServiceScopeFactory;
public readonly ILogger<BackgroundWorker1> Logger;
private IServiceProvider _serviceProvider;
public BackgroundWorker1(IServiceScopeFactory serviceScopeFactory)
{
ServiceScopeFactory = serviceScopeFactory;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_serviceScope = ServiceScopeFactory.CreateScope();
_serviceProvider = _serviceScope.ServiceProvider;
Logger = _serviceProvider.GetRequiredService<ILogger<BackgroundWorker1>>();
_logScope = Logger.BeginScope("worker instance id {WorkerId}", _workerInstance);
}
public void OneOfManyExternallyCalledMethods()
{
var service = _serviceProvider.GetRequiredService<Some3rdPartyService>();
service.DoSomething();
// all logs of all (incl. 3rd party/Microsoft) libs should contain the guid of the worker instance
}
public void Dispose()
{
_serviceScope?.Dispose();
_logScope?.Dispose();
}
}
The ultimate goal is to have each worker instance id in each log .... and in some services the services (we can rewrite) the serivce instance id from the second sample ....