You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何覆盖Microsoft.AspNetCore.Hosting.Diagnostics日志消息的格式或内容?

如何覆盖Microsoft.AspNetCore.Hosting.Diagnostics日志消息的格式或内容?

嘿,这个问题我之前踩过坑!默认的Microsoft.AspNetCore.Hosting.Diagnostics那些请求日志确实有点“固执”,要么不带上我们自定义的Correlation ID,要么格式就是改不动。不过有几个实用的办法能解决,我给你捋捋:

  • 先检查中间件顺序,别让Correlation ID迟到
    你有没有注意到,"Request Started"日志是请求刚进来就触发的?如果你的Correlation ID中间件注册得太晚——比如放在UseRouting()或者UseAuthorization()之后——那生成这条日志的时候,你的Correlation ID还没存入LogContext呢!
    赶紧把你的Correlation ID中间件往前提,最好放在app.UseHttpsRedirection()甚至最开头,这样请求一进来,Correlation ID就准备好了,默认日志自然就能带上它。

  • 用Serilog重写日志事件,强行给默认日志“加属性”
    如果只是想给默认日志补上Correlation ID或者调整格式,用Serilog的Rewrite功能就很方便。你可以过滤出Microsoft.AspNetCore.Hosting.Diagnostics的日志,然后给它们添加自定义属性,或者修改消息模板。
    举个实际代码例子:

    Log.Logger = new LoggerConfiguration()
        .Enrich.FromLogContext()
        // 过滤出目标日志,添加Correlation ID属性
        .Rewrite.ByIncluding(evt => evt.SourceContext == "Microsoft.AspNetCore.Hosting.Diagnostics", evt =>
        {
            if (LogContext.Keys.Contains("CorrelationId"))
            {
                var correlationId = LogContext.GetPropertyValue("CorrelationId");
                evt.AddOrUpdateProperty(new LogEventProperty("CorrelationId", new ScalarValue(correlationId)));
            }
        })
        // 自定义输出模板,把Correlation ID显示出来
        .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} | CorrelationId: {CorrelationId}{NewLine}{Exception}")
        .CreateLogger();
    
  • 直接禁用默认日志,自己写才最自由
    要是你完全看默认日志不顺眼,干脆禁用它,自己在Correlation ID中间件里写请求日志,格式、内容全由你说了算。
    第一步先关掉默认日志:

    // 在Program.cs里配置日志过滤
    builder.Logging.AddFilter("Microsoft.AspNetCore.Hosting.Diagnostics", LogLevel.None);
    

    然后在你的Correlation ID中间件里手动输出日志:

    public async Task InvokeAsync(HttpContext context)
    {
        // 生成或获取Correlation ID
        var correlationId = context.Request.Headers["X-Correlation-Id"].FirstOrDefault() ?? Guid.NewGuid().ToString();
        // 存入LogContext和HttpContext
        using (LogContext.PushProperty("CorrelationId", correlationId))
        {
            context.Items["CorrelationId"] = correlationId;
            // 自己写Request Started日志
            Log.Information("Request Started | {Method} {Path} | CorrelationId: {CorrelationId}", 
                context.Request.Method, context.Request.Path, correlationId);
            try
            {
                await _next(context);
            }
            finally
            {
                // 自己写Request Finished日志
                Log.Information("Request Finished | {Method} {Path} | StatusCode: {StatusCode} | CorrelationId: {CorrelationId}", 
                    context.Request.Method, context.Request.Path, context.Response.StatusCode, correlationId);
            }
        }
    }
    

    这样出来的日志完全是你想要的样子,再也不用受默认格式的限制。

  • 订阅Diagnostic事件,从源头接管日志
    其实这些默认日志是通过DiagnosticSource发布的,我们可以直接订阅对应的事件,自己处理日志输出。
    先写一个自定义的订阅者:

    public class CustomHostingDiagnosticsObserver : IObserver<KeyValuePair<string, object?>>
    {
        public void OnCompleted() { }
        public void OnError(Exception error) { }
        public void OnNext(KeyValuePair<string, object?> value)
        {
            // 捕获请求开始事件
            if (value.Key == "Microsoft.AspNetCore.Hosting.HttpRequestIn.Start")
            {
                if (value.Value is { } payload && payload.GetType().GetProperty("HttpContext")?.GetValue(payload) is HttpContext context)
                {
                    var correlationId = context.Items["CorrelationId"]?.ToString();
                    Log.Information("Request Started [CorrId: {CorrelationId}]: {Method} {Path}", 
                        correlationId, context.Request.Method, context.Request.Path);
                }
            }
            // 捕获请求结束事件
            else if (value.Key == "Microsoft.AspNetCore.Hosting.HttpRequestIn.Stop")
            {
                if (value.Value is { } payload && payload.GetType().GetProperty("HttpContext")?.GetValue(payload) is HttpContext context)
                {
                    var correlationId = context.Items["CorrelationId"]?.ToString();
                    Log.Information("Request Finished [CorrId: {CorrelationId}]: {Method} {Path} | Status: {StatusCode}", 
                        correlationId, context.Request.Method, context.Request.Path, context.Response.StatusCode);
                }
            }
        }
    }
    

    然后在Program.cs里注册这个订阅者:

    builder.Services.AddSingleton<IObserver<KeyValuePair<string, object?>>, CustomHostingDiagnosticsObserver>();
    builder.Services.AddSingleton<DiagnosticListener>(sp =>
    {
        var listener = new DiagnosticListener("Microsoft.AspNetCore");
        var observer = sp.GetRequiredService<IObserver<KeyValuePair<string, object?>>>();
        // 只订阅我们关心的请求事件
        listener.Subscribe(observer, (name, _) => name.StartsWith("Microsoft.AspNetCore.Hosting.HttpRequestIn"));
        return listener;
    });
    

    这样就能从源头接管请求日志的生成,完全按照你的需求输出。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 13:29:36