ASP.NET Core MVC 中的错误日志记录(类似于 ELMAH)针对 .Net Core 1.0






3.12/5 (7投票s)
本文介绍了如何为 .Net Core MVC 1.0 Web 项目集成简单的错误日志记录器。
引言
在 .Net Core 发布其中间件架构之前,在 Web 应用程序中记录错误的便利方法是 ELMAH 或类似工具。但由于 .Net Core 具有不同的架构,不是基于模块,而是基于中间件,因此 ELMAH 已不再使用。本文介绍如何集成一个非常类似于 ELMAH 的简单日志记录器,该日志记录器将最近的 200 个错误存储在内存中。
要查看实际效果,请按照以下步骤操作
- 下载源代码,在本地打开项目,确保您已安装 .Net Core App 1.0 和 VS2015 的最新更新。成功编译项目。
- 运行 Web 应用程序,并在浏览器中打开 https://:28157/Home/EmulateError,以模拟控制器操作中的应用程序异常。多次刷新页面。
- 打开 MVC Logger 错误历史记录页面 https://:28157/ML 以查看最近的应用程序异常信息。通过单击第一个左侧列的链接导航到详细信息页面。
背景
微软唯一提供的错误日志记录解决方案是 Application Insights,这是一个付费的 Azure 服务。它具有各种指标、仪表板,功能强大,主要目标是稳定应用程序并提高可靠性。因此,大多数基于 .Net 平台进行 Web 应用程序开发的开发人员需要一个简单、轻量级、免费的应用程序日志记录器,以便轻松访问带有详细信息的错误历史记录。通过以下方式,您可以创建自己的可自定义的 .Net Core 日志记录器,用于中间件架构。
使用代码
提出的解决方案基于 Microsoft Elm https://github.com/aspnet/Diagnostics,但进行了重大修改。下面将解释代码库。
日志记录器本身是一个中间件层。因此,它需要进行适当的配置才能将其集成到应用程序执行流程中。在应用程序的 Startup.cs 文件(位于根目录)中,需要注册日志记录器中间件服务。
public void ConfigureServices(IServiceCollection services)
{
services.AddMvcLogger(loggerOptions =>
{
loggerOptions.Filter = (loggerName, loglevel) => loglevel == LogLevel.Error;
});
........
}
下一步是在执行管道中配置日志记录页面和错误捕获。
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
........
if (env.IsDevelopment())
{
app.UseMvcLoggerPage();
app.UseMvcLoggerCapture();
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
........
}
这样就完成了配置。现在您可以在同一主机上使用“ML”路径访问日志记录屏幕 -> http(s)://...host.../ML 。此 URL 可以轻松地在 CoreMvcLogger/MLCaptureMiddleware.cs 中更改为任何其他路径 ->
public class MVCLoggerOptions
{
public PathString Path { get; set; } = new PathString("/Ml");
..........
}
此错误日志记录中间件不会替换默认的 ASP.NET Core MVC 错误详细信息页面,因此在开发环境中发生任何错误时,您仍然会看到默认的错误详细信息视图。
新集成的 MVC Logger 错误列表屏幕
单击第一个左侧列中的 URL 链接时,将显示所有作用域变量以及异常详细信息。
使用自己的简单错误日志记录器的优势是显而易见的,让我们数一数其中的一些:
- 免费,最初由微软分发给开发人员;
- MVC 日志记录器捕获系统中任何用户在所有中间件层中发生的应用程序错误,存储详细信息并方便调查问题;
- 只需两次单击即可访问有关异常和所有环境(请求)变量的详细信息;
- MVC 日志记录器错误列表视图位于应用程序的同一主机上,因此访问它既简单又快捷。
- 两个屏幕都可用:详细的默认 MVC 错误报告页面和 MVC 日志记录器历史错误快照页面。
- 由于源代码可用,因此可以根据当前需求轻松修改,例如在请求期间捕获特定于应用程序的信息,过滤掉不感兴趣的错误等。
解释日志记录器代码
最初,.Net Core 日志记录器示例已由微软在其 GitHub 账户 https://github.com/aspnet/Diagnostics/tree/dev/src 上发布,但该日志记录器存在多个问题。它需要特定版本的 .Net Core(目前有三个版本:'preview'、'release candidate'、'final')。由于使用了 razor 解析器引擎解析器/生成器,因此在错误屏幕上渲染异常详细信息存在问题。按 LogLevel 严重性过滤错误不起作用等。所有这些问题在随本文附带的稳定 MVC Logger 中都得到了修复。您可以根据自己的意愿修改自己的 MVC Logger,因为它不是编译成 dll,而是应该包含在项目中。
MVC Logger 服务实体已在 MVCLoggerServiceCollectionExtensions.cs 文件中添加。
public static IServiceCollection AddMl(this IServiceCollection services)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
services.AddOptions();
services.TryAddSingleton<MVCLoggerStore>();
services.TryAddSingleton<MVCLoggerProvider>();
return services;
}
在 MLExtensions.cs 文件中完成用于页面渲染和错误捕获的中间件注册。
public static IApplicationBuilder UseMvcLoggerCapture(this IApplicationBuilder app)
{
if (app == null)
{
throw new ArgumentNullException(nameof(app));
}
// add the mvc logger provider to the factory here so the logger can start capturing logs immediately
var factory = app.ApplicationServices.GetRequiredService<ILoggerFactory>();
var provider = app.ApplicationServices.GetRequiredService<MVCLoggerProvider>();
factory.AddProvider(provider);
return app.UseMiddleware<MLCaptureMiddleware>();
}
public static IApplicationBuilder UseMvcLoggerPage(this IApplicationBuilder app)
{
if (app == null)
{
throw new ArgumentNullException(nameof(app));
}
return app.UseMiddleware<MVCLoggerPageMiddleware>();
}
每个 HTTP 请求都由一个作用域表示。在该 HTTP 请求期间发生的所有事件都属于特定的作用域。因此,当捕获到异常时,它被保存在根作用域中,而不是简单地推送到通用列表中。启动新作用域的代码位于 MVCLogger.cs 文件中。
public IDisposable BeginScope<TState>(TState state)
实际的错误或跟踪信息捕获代码也位于 MVCLogger.cs 文件中。
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception,
Func<TState, Exception, string> formatter)
MVCLoggerPageMiddleware.cs 文件中有一个代码用于在渲染列表页面时过滤掉所有不包含任何符合过滤条件日志信息的作用域,此代码应根据您的需求进行自定义。
private bool HasAnyRelevantMessage(MVCLoggerScopeNode node, MVCLoggerOptions options)
{
var hasAnyRelevantMessage = node.Messages.Count > 0 && node.Messages.Any(ms => options.Filter("any", ms.Severity));
foreach (var nd in node.Children)
{
hasAnyRelevantMessage = hasAnyRelevantMessage | HasAnyRelevantMessage(nd, options);
}
return hasAnyRelevantMessage;
}
渲染错误列表 HTML 页面和错误详细信息 HTML 页面的代码位于 MVCLoggerPageMiddleware.cs 类中。
private void RenderMainLogPage(MVCLoggerViewOptions options, HttpContext context)
private void RenderDetailsPage(MVCLoggerViewOptions options, HttpContext context)
如果您需要更改内存中存储的错误报告数量,可以在 MVCLoggerStore.cs 文件中进行。
public class MVCLoggerStore
{
private const int Capacity = 200;
........
}
历史
由 Sem 于 2017 年 1 月 9 日星期一发布