How to access a .net 6 Scoped object from logger Singleton

Viewed 29

I have a .NET 6 application with a Scoped service that holds data from the context running, like trace id, correlation id, etc., I want to use this data to enrich my log that is a structured json using Serilog lib overriding the ILoggerFactory.

I have a custom log Provider used in the Serilog LoggerConfiguration to format the text to json and inject data from this Scoped service, the problem is that logger is a singleton and I can not access this scoped object inside it.

I can not use IHttpContextAccessor because usually the code running on it is a BackgroundService to read some Queue's not an HTTP Request, and I can not use the ServiceProvider to create a scope, because I would lose the real current scope.

internal class CustomFormatter : ITextFormatter
    {
        private readonly ILogProvider _provider;
        private readonly IServiceProvider _serviceProvider;

        static readonly JsonSerializerSettings _jsonOptions = new JsonSerializerSettings
        {
            NullValueHandling = NullValueHandling.Ignore,
            ContractResolver = new CamelCasePropertyNamesContractResolver()
        };

        public CustomFormatter(ILogProvider provider, IServiceProvider serviceProvider)
        {
            _provider = provider;
            _serviceProvider = serviceProvider;
        }

        public void Format(LogEvent logEvent, TextWriter output)
        {
            var logObj = _provider.Create(logEvent);

            // Error in this line, since ICustomContext is a scoped object
            var customContext = _serviceProvider.GetRequiredService<ICustomContext>();

            logObj.CorrelationId = customContext.correlationId;

            output.WriteLine(JsonConvert.SerializeObject(logObj, _jsonOptions));
        }
    }
0 Answers
Related