Microsoft.AspNetCore.Hosting.Internal.WebHost и log4net.LogicalThreadContext.Properties["requesttid"]

Я использую netcore2.0, и я устанавливаю свойство log4net.LogicalThreadContext "requesttid" с каждым запросом в своем классе промежуточного программного обеспечения для целей регистрации.

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

Но класс "Microsoft.AspNetCore.Hosting.Internal.WebHost" не отображает это свойство при регистрации строк.

Я не знаю, как установить log4net.LogicalThreadContext.Propery["requesttid"] для "Microsoft.AspNetCore.Hosting.Internal.WebHost".

Я хочу связать все журналы запросов от начала до конца. У кого-нибудь есть идеи, которые могут помочь?

С уважением!

ОБНОВЛЕНИЕ: вот код

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 Configure(приложение 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 | INFO | Microsoft.AspNetCore.Hosting.Internal.WebHost |(ноль)| Запросить запуск HTTP / 1.1 GET http://localhost/...
2018-04-10 14: 02: 28,956 | INFO | Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker |cfb2709e3b4f40559c365ecbb08a7746| Выполнение метода действия Controllers.HealtCheckStatusController.GetHealthCheckStatus 2018-04-10 14: 02: 29,486 | INFO | Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor |cfb2709e3b4f40559c365ecbb08a7746| Выполнение ObjectResult с записью значения Microsoft.AspNetCore.Mvc.ControllerContext.
2018-04-10 14: 02: 29,510 | INFO | Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker |cfb2709e3b4f40559c365ecbb08a7746| Выполнено действие Controllers.HealtCheckStatusController.GetHealthCheckStatus в 564.464мс
2018-04-10 14: 02: 29,520 | INFO | Microsoft.AspNetCore.Hosting.Internal.WebHost |(ноль)| Запрос завершен в 858,9575 мс 200 заявка / JSON; кодировка = UTF-8

1 ответ

Решение

Зачем WebHost регистратор не показывает свойство

WebHost регистратор регистрирует два сообщения - Запрос начального сообщения и Запрос завершенного сообщения.

Запрос стартового сообщения не видит requestid собственность, потому что WebHost запускает и регистрирует сообщение перед первым промежуточным ПО, включенным в конвейер в Startup класс где requestid свойство установлено.

Запрос завершенного сообщения не видит requestid собственность, потому что (я думаю) WebHost логгер вышел из log4net.LogicalThreadContext, Это как Log4NetRequestIdMiddleware регистратор не увидит requestid свойство, если оно будет установлено в действии контроллера.

Возможное решение

поскольку WebHost регистратор регистрирует сообщения где-то глубоко HostingApplicationDiagnostics класс от Microsoft.AspNetCore.Hosting.Internal Пространство имен нет каких-либо четких точек расширения, чтобы ввести код, который установил бы requestid имущество. Итак, я думаю, что вы можете просто зарегистрировать информацию в своем промежуточном программном обеспечении, как это делает WebHost регистратор:

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);
}

Вы можете посмотреть это https://docs.microsoft.com/en-us/aspnet/core/fundamentals/logging/?view=aspnetcore-3.1

Создайте свой собственный LogProvider, очистите поставщика журналов, как это.

            services.AddLogging(config =>
            {
                config.ClearProviders();
            });

            loggerFactory.AddLog4Net();

В этой статье рассказывается, как создать регистратор log4net. https://dotnetthoughts.net/how-to-use-log4net-with-aspnetcore-for-logging/

Другие вопросы по тегам