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/