我使用netcore2.0,并在中间件类中为每个请求设置log4net.LogicalThreadContext属性“ requestid”,以进行记录。

log4net.LogicalThreadContext.Properties["requestid"] = Guid.NewGuid().ToString("N");


但是“ Microsoft.AspNetCore.Hosting.Internal.WebHost”类在记录行时不显示此属性。

我不知道如何为“ Microsoft.AspNetCore.Hosting.Internal.WebHost”设置log4net.LogicalThreadContext.Propery [“ requestid”]。

我希望将所有请求日志从头到尾都捆绑在一起。
有没有人有什么见识可以帮助您?

问候!

更新:这是代码

using Microsoft.Extensions.Logging;
...

public static ILoggerProvider Log4NetProvider;

public static void Main(string[] args)
    {

#if DEBUG
        Log4NetProvider = new Log4NetProvider("log4net.Debug.config", ((o,
exception) => exception.Message));
#else
        Log4NetProvider = new Log4NetProvider("log4net.Release.config", ((o,
exception) => exception.Message));
#endif
        var host = new WebHostBuilder()
            .UseKestrel()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .ConfigureLogging((hostingContext, logging) =>
            {
                logging.AddProvider(Log4NetProvider);
            })
            .ConfigureServices(services =>
            {
                services.AddAutofac();
            })
            .UseIISIntegration()
            .UseStartup<Startup>()
            .Build();
        host.Run();


在Startup.cs中
配置(IApplicationBuilder应用程序,IHostingEnvironment env)我已经设置为第一件事。

app.UseMiddleware<Log4NetRequestIdMiddleware>();

public class Log4NetRequestIdMiddleware
{
    private readonly RequestDelegate _next;

    public Log4NetRequestIdMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task Invoke(HttpContext context)
    {
        log4net.LogicalThreadContext.Properties["requestid"] = Guid.NewGuid().ToString("N");
        await _next(context);
    }
}


Log4net配置文件>

<?xml version="1.0" encoding="utf-8" ?>
<log4net>
  <appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
    <file value="C:\log\applog.log" />
    <rollingStyle value="Size"/>
    <maxSizeRollBackups value="500"/>
    <maximumFileSize value="5MB"/>
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%utcdate|%-5level|%logger|%property{requestid}| %message %exception%newline" />
    </layout>
  </appender>
  <root>
    <level value="ALL" />
    <appender-ref ref="RollingFile" />
  </root>
</log4net>


Fileappender.log中的其他示例(加粗标记RequestId)


  2018-04-10 14:02:28,664 |信息| Microsoft.AspNetCore.Hosting.Internal.WebHost |(null)|请求启动HTTP / 1.1 GET http://localhost ...
  2018-04-10 14:02:28,956 |信息| Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker | cfb2709e3b4f40559c365ecbb08a7746 |执行动作方法Controllers.HealtCheckStatusController.GetHealthCheckStatus
  2018-04-10 14:02:29,486 |信息| Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor | cfb2709e3b4f40559c365ecbb08a7746 |执行ObjectResult,写入值Microsoft.AspNetCore.Mvc.ControllerContext。
  2018-04-10 14:02:29,510 |信息| Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker | cfb2709e3b4f40559c365ecbb08a7746 |在564.464毫秒内执行了动作Controllers.HealtCheckStatusController.GetHealthCheckStatus
  2018-04-10 14:02:29,520 |信息| Microsoft.AspNetCore.Hosting.Internal.WebHost |(null)|请求完成于858.9575ms 200 application / json;字符集= utf-8

最佳答案

为什么WebHost记录器不显示该属性

WebHost记录器记录两条消息-请求开始消息和请求完成消息。

请求启动消息没有看到requestid属性,因为WebHost运行并在设置了Startup属性的requestid类的管道中包含的第一个中间件之前记录该消息。

请求完成的消息看不到requestid属性,因为(我想)WebHost记录器不在log4net.LogicalThreadContext内。就像Log4NetRequestIdMiddleware记录器将不会看到requestid属性,如果在控制器操作中进行设置。

可能的解决方案

由于WebHost记录器从HostingApplicationDiagnostics命名空间将消息记录在Microsoft.AspNetCore.Hosting.Internal类的较深位置,因此没有任何明确的扩展点来注入将设置requestid属性的代码。
因此,我认为您可以像WebHost logger一样在中间件中记录信息:

public async Task Invoke(HttpContext context)
{
    var logger = httpContext.RequestServices.GetRequiredService<ILogger<Log4NetRequestIdMiddleware>>();
    log4net.LogicalThreadContext.Properties["requestid"] = Guid.NewGuid().ToString("N");

    var request = context.Request;
    string logMsg = string.Format(
            CultureInfo.InvariantCulture,
            "Request starting {0} {1} {2}://{3}{4}{5}{6} {7} {8}",
            request.Protocol,
            request.Method,
            request.Scheme,
            request.Host.Value,
            request.PathBase.Value,
            request.Path.Value,
            request.QueryString.Value,
            request.ContentType,
            request.ContentLength);

    logger.LogDebug(logMsg);

    await _next(context);
}

10-05 19:23