Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting logging scope globally in ASP.Net Core

I want to get certain key bits of information (service-name, service-version, host-name, etc) logged on every log message in an ASP.Net Core service.

I have the following code:

public class Program
{
    public static void Main(string[] args)
    {
        var host = CreateHostBuilder(args).Build();

        using (host.Services.GetRequiredService<ILogger<Program>>().BeginScope("ServiceName: {0}", "bob-service"))
        {
            host.Run();
        }
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureLogging(builder =>
            {
                builder.AddConsole(o => o.IncludeScopes = true);
            })
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

From this I get the following logging:

info: Microsoft.Hosting.Lifetime[0]
      => ServiceName: bob-service
      Now listening on: http://localhost:5002

info: Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure.PageActionInvoker[102]
      => ConnectionId:0HLSO8706NGBN => RequestPath:/ RequestId:0HLSO8706NGBN:00000001, SpanId:|aa5794ba-408ad22a63064421., TraceId:aa5794ba-408ad22a63064421, ParentId: => Middleware_Scope => /Index
      Executed handler method OnGet, returned result .

Note how the ServiceName only appears on the host-level logging. The request-level logging does not include it.

Is there a mechanism for setting scope on every log-message that comes out of ASP.Net Core.

I've tried adding a piece of middleware to do this, and it mostly works, but the logging doesn't appear on the "Microsoft.AspNetCore.Hosting.Diagnostics" log messages (although it appears on everything else as far as I can tell).

app
    .Use(async (context, next) =>
    {
        // Middleware to add scoped values to log messages.
        var logger = context.RequestServices.GetRequiredService<ILogger<Startup>>();
        using (logger.BeginScope("ServiceName: {0}", "bob-service")))
        {
            await next();
        }
    });

EDIT

Even when using the middleware described above, log messages from the Microsoft.AspNetCore.Hosting.Diagnostics logger do not contain the scoped fields. For example, note how in the second log message, the Middleware_Scope scoped message does not appear.

info: Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware[6]
      => ConnectionId:0HLSOTDVELPJA => RequestPath:/css/site.css RequestId:0HLSOTDVELPJA:00000001, SpanId:|2fbd556d-44cc7c919266ccaf., TraceId:2fbd556d-44cc7c919266ccaf, ParentId: => Middleware_Scope
      The file /css/site.css was not modified

info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
      => ConnectionId:0HLSOTDVELPJD => RequestPath:/js/site.js RequestId:0HLSOTDVELPJD:00000001, SpanId:|2fbd5570-44cc7c919266ccaf., TraceId:2fbd5570-44cc7c919266ccaf, ParentId:
      Request finished in 29.8413ms 304 application/javascript
like image 534
RB. Avatar asked Feb 14 '26 05:02

RB.


1 Answers

I don't know if it is right, but I came to set scopes globally using ILoggerProvider instead of ILogger<T>, and setting my own scope provider for it, something like this:

    public static void Main(string[] args)
    {
        var host = CreateHostBuilder(args).Build();
        
        // ... other logging configurations, like ClearProviders() and AddJsonConsole(o => o.IncludeScopes = true);

        var provider = host.Services.GetService<ILoggerProvider>()
        if (provider is ISupportExternalScope scopedProvider)
        {
            var scopes = new LoggerExternalScopeProvider();
            scopes.Push("ServiceName: bob-service");
            scopedProvider.SetScopeProvider(scopes);
        }

        host.Run();
    }

You may have to use GetServices<ILoggerProvider> and take care of a list if you have more than one provider.

like image 164
alexbrina Avatar answered Feb 17 '26 00:02

alexbrina



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!