Microsoft.AspNetCore.Hosting.Internal.WebHost 和 log4net.LogicalThreadContext.Properties["requestid"]
Microsoft.AspNetCore.Hosting.Internal.WebHost and log4net.LogicalThreadContext.Properties["requestid"]
我使用 netcore2.0 并在我的中间件 class 中为每个请求设置 log4net.LogicalThreadContext 属性 "requestid" 用于记录目的。
log4net.LogicalThreadContext.Properties["requestid"] = Guid.NewGuid().ToString("N");
但是 "Microsoft.AspNetCore.Hosting.Internal.WebHost" class 在记录行时不显示此 属性。
我不知道如何为 "Microsoft.AspNetCore.Hosting.Internal.WebHost" 设置 log4net.LogicalThreadContext。属性["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
Configure(IApplicationBuilder app, 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|(null)| Request starting HTTP/1.1 GET http://localhost...
2018-04-10 14:02:28,956|INFO| Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker|cfb2709e3b4f40559c365ecbb08a7746| Executing action method Controllers.HealtCheckStatusController.GetHealthCheckStatus
2018-04-10 14:02:29,486|INFO| Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor|cfb2709e3b4f40559c365ecbb08a7746| Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
2018-04-10 14:02:29,510|INFO| Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker|cfb2709e3b4f40559c365ecbb08a7746| Executed action Controllers.HealtCheckStatusController.GetHealthCheckStatus in 564.464ms
2018-04-10 14:02:29,520|INFO|Microsoft.AspNetCore.Hosting.Internal.WebHost|(null)| Request finished in 858.9575ms 200 application/json; charset=utf-8
为什么 WebHost
记录器不显示 属性
WebHost
记录器记录两条消息 - 请求开始消息和请求完成消息。
请求开始消息没有看到 requestid
属性 因为 WebHost
在 Startup
[=40= 的第一个中间件包含到管道之前运行并记录消息] 其中设置了 requestid
属性。
请求完成消息没有看到 requestid
属性 因为(我猜)WebHost
记录器不在 log4net.LogicalThreadContext
。就像 Log4NetRequestIdMiddleware
记录器不会看到 requestid
属性 如果它在控制器操作中设置。
可能的解决方案
由于 WebHost
记录器从 Microsoft.AspNetCore.Hosting.Internal
命名空间的 HostingApplicationDiagnostics
class 某处深处记录消息,因此没有任何明确的扩展点来注入将设置 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);
}
创建自己的LogProvider,像这样清除日志提供程序。
services.AddLogging(config =>
{
config.ClearProviders();
});
loggerFactory.AddLog4Net();
本文介绍了如何创建 log4net 记录器。
https://dotnetthoughts.net/how-to-use-log4net-with-aspnetcore-for-logging/
我使用 netcore2.0 并在我的中间件 class 中为每个请求设置 log4net.LogicalThreadContext 属性 "requestid" 用于记录目的。
log4net.LogicalThreadContext.Properties["requestid"] = Guid.NewGuid().ToString("N");
但是 "Microsoft.AspNetCore.Hosting.Internal.WebHost" class 在记录行时不显示此 属性。
我不知道如何为 "Microsoft.AspNetCore.Hosting.Internal.WebHost" 设置 log4net.LogicalThreadContext。属性["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 Configure(IApplicationBuilder app, 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|(null)| Request starting HTTP/1.1 GET http://localhost...
2018-04-10 14:02:28,956|INFO| Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker|cfb2709e3b4f40559c365ecbb08a7746| Executing action method Controllers.HealtCheckStatusController.GetHealthCheckStatus 2018-04-10 14:02:29,486|INFO| Microsoft.AspNetCore.Mvc.Internal.ObjectResultExecutor|cfb2709e3b4f40559c365ecbb08a7746| Executing ObjectResult, writing value Microsoft.AspNetCore.Mvc.ControllerContext.
2018-04-10 14:02:29,510|INFO| Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker|cfb2709e3b4f40559c365ecbb08a7746| Executed action Controllers.HealtCheckStatusController.GetHealthCheckStatus in 564.464ms
2018-04-10 14:02:29,520|INFO|Microsoft.AspNetCore.Hosting.Internal.WebHost|(null)| Request finished in 858.9575ms 200 application/json; charset=utf-8
为什么 WebHost
记录器不显示 属性
WebHost
记录器记录两条消息 - 请求开始消息和请求完成消息。
请求开始消息没有看到 requestid
属性 因为 WebHost
在 Startup
[=40= 的第一个中间件包含到管道之前运行并记录消息] 其中设置了 requestid
属性。
请求完成消息没有看到 requestid
属性 因为(我猜)WebHost
记录器不在 log4net.LogicalThreadContext
。就像 Log4NetRequestIdMiddleware
记录器不会看到 requestid
属性 如果它在控制器操作中设置。
可能的解决方案
由于 WebHost
记录器从 Microsoft.AspNetCore.Hosting.Internal
命名空间的 HostingApplicationDiagnostics
class 某处深处记录消息,因此没有任何明确的扩展点来注入将设置 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);
}
创建自己的LogProvider,像这样清除日志提供程序。
services.AddLogging(config =>
{
config.ClearProviders();
});
loggerFactory.AddLog4Net();
本文介绍了如何创建 log4net 记录器。 https://dotnetthoughts.net/how-to-use-log4net-with-aspnetcore-for-logging/