ELMAH 的日志记录错误详细信息 (C#)

作者 :Scott Mitchell

错误日志记录模块和处理程序 (ELMAH) 提供了另一种方法来记录生产环境中的运行时错误。 ELMAH 是一个免费的开放源代码错误日志记录库,其中包含错误筛选等功能,以及从网页查看错误日志、作为 RSS 源或以逗号分隔的文件下载的功能。 本教程逐步讲解如何下载和配置 ELMAH。

简介

前面的教程介绍了 ASP。NET 的运行状况监视系统,它提供一个现成的库,用于记录各种 Web 事件。 许多开发人员使用运行状况监视来记录和通过电子邮件发送未经处理的异常的详细信息。 但是,此系统有一些痛点。 首先,缺少任何类型的用户界面来查看有关记录的事件的信息。 如果想要查看最后 10 个错误的摘要,或查看上周发生的错误的详细信息,则必须浏览数据库、扫描电子邮件收件箱,或生成显示表中信息的 aspnet_WebEvent_Events 网页。

另一个痛点集中在运行状况监视的复杂性上。 由于运行状况监视可用于记录大量不同的事件,并且有多种选项用于指示记录事件的方式和时间,因此正确配置运行状况监视系统可能是一项繁重的任务。 最后,存在兼容性问题。 由于在版本 2.0 中首次将运行状况监视添加到 .NET Framework,因此它不适用于使用 ASP.NET 版本 1.x 生成的旧 Web 应用程序。 此外,SqlWebEventProvider我们在上一教程中用于将错误详细信息记录到数据库中的 类仅适用于 Microsoft SQL Server 数据库。 如果需要将错误记录到备用数据存储(如 XML 文件或 Oracle 数据库),则需要创建自定义日志提供程序类。

运行状况监视系统的替代方法是错误日志记录模块和处理程序 (ELMAH) ,这是 Atif Aziz 创建的免费开源错误日志记录系统。 这两个系统之间最明显的区别是 ELAMH 能够显示错误列表以及网页中的特定错误的详细信息,以及 RSS 源。 ELMAH 比运行状况监视更易于配置,因为它只记录错误。 此外,ELMAH 还支持 ASP.NET 1.x、ASP.NET 2.0 和 ASP.NET 3.5 应用程序,并随各种日志源提供程序一起提供。

本教程逐步讲解将 ELMAH 添加到 ASP.NET 应用程序所涉及的步骤。 让我们开始吧!

注意

健康监测系统和 ELMAH 都有各自的利弊。 我鼓励你尝试这两个系统,并确定哪种系统最适合你的需求。

将 ELMAH 添加到 ASP.NET Web 应用程序

将 ELMAH 集成到新的或现有的 ASP.NET 应用程序中是一个简单直接的过程,只需不到 5 分钟。 简言之,它涉及四个简单的步骤:

  1. 下载 ELMAH 并将程序集添加到 Elmah.dll Web 应用程序,
  2. 在 中 Web.config注册 ELMAH 的 HTTP 模块和处理程序
  3. 指定 ELMAH 的配置选项,以及
  4. 根据需要创建错误日志源基础结构。

让我们逐一演练这四个步骤中的每一个步骤。

步骤 1:下载 ELMAH 项目文件并添加到Elmah.dllWeb 应用程序

ELMAH 1.0 BETA 3 (内部版本 10617) 是撰写本文时最新版本,包含在本教程提供的下载中。 或者,你可以访问 ELMAH 网站 以获取最新版本或下载源代码。 将 ELMAH 下载解压缩到桌面上的文件夹,并找到 ELMAH 程序集文件 (Elmah.dll) 。

注意

该文件Elmah.dll位于下载的 Bin 文件夹中,该文件夹包含不同.NET Framework版本以及发布和调试版本的子文件夹。 对适当的框架版本使用发布版本。 例如,如果要生成 ASP.NET 3.5 Web 应用程序,请从 Bin\net-3.5\Release 文件夹中复制Elmah.dll文件。

接下来,打开 Visual Studio 并将程序集添加到项目,方法是右键单击解决方案资源管理器中的网站名称,然后从上下文菜单中选择“添加引用”。 此时会显示“添加引用”对话框。 导航到“浏览”选项卡并选择 Elmah.dll 文件。 此操作将 Elmah.dll 文件添加到 Web 应用程序的 Bin 文件夹中。

注意

Web 应用程序项目 (WAP) 类型不显示Bin解决方案资源管理器中的文件夹。 而是在 References 文件夹下列出这些项。

程序集 Elmah.dll 包括 ELMAH 系统使用的类。 这些类分为以下三个类别之一:

  • HTTP 模块 - HTTP 模块是一个类,用于定义 HttpApplication 事件(如 事件)的 Error 事件处理程序。 ELMAH 包括多个 HTTP 模块,其中三个最规范的模块是:

    • ErrorLogModule - 将未经处理的异常记录到日志源。
    • ErrorMailModule - 在电子邮件中发送未经处理的异常的详细信息。
    • ErrorFilterModule - 应用开发人员指定的筛选器,以确定记录哪些异常以及忽略哪些异常。
  • HTTP 处理程序 - HTTP 处理程序是一个类,负责为特定类型的请求生成标记。 ELMAH 包括 HTTP 处理程序,这些处理程序将错误详细信息呈现为网页、RSS 源或以逗号分隔的文件 (CSV) 。

  • 错误日志源 - 现成的 ELMAH 可以将错误记录到内存、Microsoft SQL Server 数据库、Microsoft Access 数据库、Oracle 数据库、XML 文件、SQLite 数据库或 Vista DB 数据库。 与运行状况监视系统一样,ELMAH 的体系结构是使用提供程序模型构建的,这意味着可以根据需要创建并无缝集成自己的自定义日志源提供程序。

步骤 2:注册 ELMAH 的 HTTP 模块和处理程序

Elmah.dll虽然该文件包含自动记录未经处理的异常以及显示网页中的错误详细信息所需的 HTTP 模块和处理程序,但这些模块和处理程序必须在 Web 应用程序的配置中显式注册。 ErrorLogModule注册后,HTTP 模块将HttpApplication订阅 的 Error 事件。 每当引发此事件时,会将 ErrorLogModule 异常的详细信息记录到指定的日志源。 我们将在下一节“配置 ELMAH”中了解如何定义日志源提供程序。HTTP ErrorLogPageFactory 处理程序工厂负责在从网页查看错误日志时生成标记。

注册 HTTP 模块和处理程序的特定语法取决于为站点提供支持的 Web 服务器。 对于 ASP.NET Development Server 和 Microsoft 的 IIS 版本 6.0 及更早版本,HTTP 模块和处理程序在 元素中显示的 <httpModules><system.web><httpHandlers> 部分中注册。 如果使用 IIS 7.0,则需要在 <system.webServer> 元素的 <modules><handlers> 部分中注册它们。 幸运的是,无论使用何种 Web 服务器,都可以在这 个位置定义 HTTP 模块和处理程序。 此选项是最可移植的选项,因为它允许在开发和生产环境中使用相同的配置,而不考虑正在使用的 Web 服务器。

首先,在 ErrorLogModule 的 和 <httpHandlers><system.web><httpModules>注册 HTTP 模块和 ErrorLogPageFactory HTTP 处理程序。 如果配置已定义这两个元素, <add> 则只需包含 ELMAH 的 HTTP 模块和处理程序的 元素。

<?xml version="1.0"?>
<configuration>
  ...
  
  <system.web>
  ...

  <httpHandlers>
  ...

  <add verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah" />
  </httpHandlers>
  
  <httpModules>
  ...
  
  <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah"/>
  </httpModules>

  ...
  </system.web>

  ...
</configuration>

接下来,在 元素中 <system.webServer> 注册 ELMAH 的 HTTP 模块和处理程序。 与之前一样,如果配置中尚不存在此元素,请添加它。

<?xml version="1.0"?>
<configuration>
  ...

  <system.webServer>
  <validation validateIntegratedModeConfiguration="false"/>
  <modules>
  ...

  <add name="Elmah.ErrorLog" type="Elmah.ErrorLogModule, Elmah" preCondition="managedHandler" />
  </modules>
  <handlers>
  ...

  <add name="Elmah" path="elmah.axd" verb="POST,GET,HEAD" type="Elmah.ErrorLogPageFactory, Elmah" preCondition="integratedMode" />
  </handlers>
  </system.webServer>
</configuration>

默认情况下,IIS 7 会抱怨是否在 节中 <system.web> 注册了 HTTP 模块和处理程序。 validateIntegratedModeConfiguration元素中的 <validation> 属性指示 IIS 7 禁止显示此类错误消息。

请注意,用于注册 HTTP 处理程序的 ErrorLogPageFactory 语法包含属性 path ,该属性设置为 elmah.axd。 此属性通知 Web 应用程序,如果请求到达名为 elmah.axd 的页面,则请求应由 HTTP 处理程序处理 ErrorLogPageFactory 。 本教程稍后将介绍 ErrorLogPageFactory HTTP 处理程序的运行情况。

步骤 3:配置 ELMAH

ELMAH 在名为 <elmah>Web.config自定义配置部分中的网站文件中查找其配置选项。 若要使用中的 Web.config 自定义节,必须先在 元素中 <configSections> 定义。 打开 文件并将 Web.config 以下标记添加到 <configSections>

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
  ...

  <sectionGroup name="elmah">
  <section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah"/>
  <section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah" />
  <section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah" />
  <section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah"/>
  </sectionGroup>
  </configSections>

  ...
</configuration>

注意

如果要为 ASP.NET 1.x 应用程序配置 ELMAH, requirePermission="false" 请从 <section> 上述元素中删除 属性。

上述语法注册自定义 <elmah> 节及其子节: <security><errorLog><errorMail><errorFilter>

接下来,将 <elmah> 节添加到 Web.config。 此部分应与 元素在同一级别 <system.web> 显示。 在 <elmah> 节内添加 和 <errorLog> 节,<security>如下所示:

<?xml version="1.0"?>
<configuration>
  ...

  <elmah>
  <security allowRemoteAccess="0" />
  
  <errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="ReviewsConnectionString" />
  </elmah>

  ...
</configuration>

<security>allowRemoteAccess 属性指示是否允许远程访问。 如果此值设置为 0,则只能在本地查看错误日志网页。 如果此属性设置为 1,则为远程和本地访问者启用错误日志网页。 现在,让我们禁用远程访问者的错误日志网页。 稍后,我们有机会讨论这样做的安全性问题后,将允许远程访问。

<errorLog> 定义错误日志源,该源指定错误详细信息的记录位置;它类似于 <providers> 运行状况监视系统中的 节。 上述语法将 类指定SqlErrorLog为错误日志源,该源将错误记录到由 connectionStringName 属性值指定的 Microsoft SQL Server 数据库。

注意

ELMAH 附带了其他错误日志提供程序,可用于将错误记录到 XML 文件、Microsoft Access 数据库、Oracle 数据库和其他数据存储。 有关如何使用这些备用错误日志提供程序的信息,请参阅 ELMAH 下载附带的示例 Web.config 文件。

步骤 4:创建错误日志源基础结构

ELMAH 的SqlErrorLog提供程序将错误详细信息记录到指定的 Microsoft SQL Server 数据库。 提供程序 SqlErrorLog 要求此数据库具有一个名为 的 ELMAH_Error 表和三个存储过程: ELMAH_GetErrorsXmlELMAH_GetErrorXmlELMAH_LogError。 ELMAH 下载包含文件夹中名为 SQLServer.sqldb 的文件,其中包含用于创建此表和这些存储过程的 T-SQL。 需要对数据库运行这些语句才能使用 SqlErrorLog 提供程序。

图 1图 2 显示了添加提供程序所需的 SqlErrorLog 数据库对象后,Visual Studio 中的数据库资源管理器。

显示 S Q L 错误日志提供程序记录写入表的错误的屏幕截图。

图 1:提供程序 SqlErrorLog 将错误记录到 ELMAH_Error

显示 S Q L 错误日志提供程序如何使用三个存储过程的屏幕截图。

图 2:提供程序 SqlErrorLog 使用三个存储过程

ELMAH 在行动

此时,我们已将 ELMAH 添加到 Web 应用程序,注册了 ErrorLogModule HTTP 模块和 ErrorLogPageFactory HTTP 处理程序,在 中 Web.config指定了 ELMAH 的配置选项,并为错误日志提供程序添加了所需的数据库对象 SqlErrorLog 。 我们现在已准备好看到 ELMAH 在行动! 访问书评网站,并访问生成运行时错误的页面,例如 Genre.aspx?ID=foo,或不存在的页面,如 NoSuchPage.aspx。 访问这些页面时看到的内容取决于 <customErrors> 配置以及是在本地访问还是远程访问。 (有关本主题的刷新,请参阅 显示自定义错误页 教程 。)

发生未经处理的异常时,ELMAH 不会影响向用户显示的内容;它只是记录其详细信息。 可以从网站的根目录中的网页 elmah.axd 访问此错误日志,例如 http://localhost/BookReviews/elmah.axd。 (此文件实际上不存在于项目中,但当运行时传入 elmah.axd 请求时,它会将其调度到 ErrorLogPageFactory HTTP 处理程序,后者生成发回到 browser 的标记。)

注意

还可以使用 elmah.axd 页面指示 ELMAH 生成测试错误。 访问 elmah.axd/test (, http://localhost/BookReviews/elmah.axd/test) 会导致 ELMAH 引发类型 Elmah.TestException为 的异常,其中包含错误消息:“这是可以安全忽略的测试异常。”

图 3 显示了从开发环境访问 elmah.axd 时的错误日志。

显示错误日志如何从网页显示的屏幕截图。

图 3Elmah.axd 显示网页中的错误日志
(单击以查看全尺寸图像)

图 3 中的错误日志包含六个错误条目。 每个条目包括 HTTP 状态代码 (404 或 500,对于这些错误) 、类型、说明、发生错误时登录用户的名称以及日期和时间。 单击“详细信息”链接将显示一个页面,其中包含错误详细信息死亡的黄色屏幕中显示的相同错误消息 (请参阅 图 4) 以及错误时服务器变量的值 (见 图 5) 。 还可以查看保存错误详细信息的原始 XML,其中包括其他信息,例如 HTTP POST 标头中的值。

显示错误详细信息 YSOD 的屏幕截图。

图 4:查看错误详细信息 YSOD
(单击以查看全尺寸图像)

显示服务器变量集合的值的屏幕截图。

图 5:在发生错误时浏览服务器变量集合的值
(单击以查看全尺寸图像)

将 ELMAH 部署到生产网站需要:

  • Elmah.dll 文件复制到生产时 Bin 的文件夹,
  • 将 ELMAH 特定的配置设置复制到 Web.config 生产中使用的文件,以及
  • 将错误日志源基础结构添加到生产数据库。

在前面的教程中,我们探索了将文件从开发复制到生产的技术。 获取生产数据库上的错误日志源基础结构的最简单方法是使用 SQL Server Management Studio 连接到生产数据库,然后执行SqlServer.sql脚本文件,这将创建所需的表和存储过程。

查看生产中的“错误详细信息”页

将站点部署到生产环境后,请访问生产网站并生成未经处理的异常。 与在开发环境中一样,ELMAH 对发生未经处理的异常时显示的错误页没有影响;相反,它只记录错误。 如果尝试从生产环境访问错误日志页 (elmah.axd) ,则会出现 图 6 中所示的“禁止”页。

显示远程访问者无法查看错误日志网页的屏幕截图。

图 6:默认情况下,远程访问者无法查看错误日志网页
(单击以查看全尺寸图像)

回想一下,在 ELMAH 配置的 <security> 部分中,我们将 属性设置为 allowRemoteAccess 0,这会禁止远程用户查看错误日志。 禁止匿名访问者查看错误日志非常重要,因为错误详细信息可能会显示安全漏洞或其他敏感信息。 如果决定将此属性设置为 1 并启用对错误日志的远程访问,则必须锁定 elmah.axd 路径,以便只有经过授权的访问者才能访问它。 这可以通过向 文件添加 <location> 元素 Web.config 来实现。

以下配置仅允许管理员角色中的用户访问错误日志网页:

<?xml version="1.0"?>
<configuration>
  ...

  <elmah>
  <security allowRemoteAccess="1" />
  
  ...
  </elmah>

  ...

  <location path="elmah.axd">
  <system.web>
  <authorization>
  <allow roles="Admin" />
  <deny users="*" />
  </authorization>
  </system.web>  
  </location>
</configuration>

注意

配置使用应用程序服务的网站教程中添加了管理员角色和系统中的三个用户-Scott、Jisun 和 Alice。 用户 Scott 和 Jisun 是管理员角色的成员。 有关身份验证和授权的详细信息,请参阅我的 网站安全教程

生产环境中的错误日志现在可以由远程用户查看;有关错误日志网页的屏幕截图,请参阅 图 34图 5 。 但是,如果匿名或非管理员用户尝试查看错误日志页,他们会自动重定向到登录页 (Login.aspx) ,如图 7 所示。

显示如何自动将未经授权的用户重定向到登录页的屏幕截图。

图 7:未经授权的用户自动重定向到登录页
(单击以查看全尺寸图像)

以编程方式记录错误

ELMAH 的 ErrorLogModule HTTP 模块自动将未经处理的异常记录到指定的日志源。 或者,可以使用 类及其 Raise 方法记录错误,而无需引发未经处理的异常ErrorSignal。 向 Raise 方法传递对象 Exception 并记录它,就像该异常已引发并到达 ASP.NET 运行时而未进行处理一样。 但区别在于,调用 方法后 Raise 请求继续正常执行,而引发的未经处理的异常会中断请求的正常执行,并导致 ASP.NET 运行时显示配置的错误页。

如果 ErrorSignal 存在一些操作可能会失败,但其故障不会对正在执行的总体操作带来灾难性影响,则类非常有用。 例如,网站可能包含接受用户输入的表单,将其存储在数据库中,然后向用户发送一封电子邮件,告知他们信息已处理。 如果成功将信息保存到数据库,但在发送电子邮件时出现错误,会发生什么情况? 一种选择是引发异常并将用户发送到错误页。 但是,这可能会使用户误以为他们输入的信息未保存。 另一种方法是记录与电子邮件相关的错误,但不要以任何方式改变用户体验。 这是 类很有用的地方 ErrorSignal

// ... Save user's information to the database ...
...

// Attempt to send the user a confirmation email
try
{
    // ... Send an email ...
}
catch (Exception e)
{
    // Error in sending email. Log it!
    ErrorSignal.FromCurrentContext().Raise(e);
}

通过Email发出错误通知

除了将错误记录到数据库之外,ELMAH 还可以配置为通过电子邮件将错误详细信息发送给指定的收件人。 此功能由 ErrorMailModule HTTP 模块提供;因此,必须注册此 HTTP 模块 Web.config 才能通过电子邮件发送错误详细信息。

<?xml version="1.0"?>
<configuration>
  ...
  
  <system.web>
  ...

  <httpModules>
  ...
  
  <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah"/>
  <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah"/>
  </httpModules>
  </system.web>

  <system.webServer>
  <validation validateIntegratedModeConfiguration="false"/>
  <modules>
  ...

  <add name="Elmah.ErrorLog" type="Elmah.ErrorLogModule, Elmah" preCondition="managedHandler" />
  <add name="Elmah.ErrorMail" type="Elmah.ErrorMailModule" preCondition="managedHandler" />
  </modules>
  
  ...
  </system.webServer>
</configuration>

接下来,在 <elmah> 元素的 <errorMail> 部分中指定有关错误电子邮件的信息,指示电子邮件的发件人和收件人、主题以及电子邮件是否以异步方式发送。

<?xml version="1.0"?>
<configuration>
  ...

  <elmah>
  ...

  <errorMail from="support@example.com"
  to="support@example.com"
  subject="Book Reviews Runtime Error"
  async="true" />
  </elmah>

  ...
</configuration>

有了上述设置,每当发生运行时错误时,ELMAH 就会向 发送电子邮件 support@example.com ,其中包含错误详细信息。 ELMAH 的错误电子邮件包含错误详细信息网页中显示的相同信息,即错误消息、堆栈跟踪和服务器变量 (请参阅 图 4图 5) 。 错误电子邮件还包括异常详细信息死亡的黄色屏幕内容作为附件 (YSOD.html) 。

图 8 显示了通过访问 Genre.aspx?ID=foo生成的 ELMAH 错误电子邮件。 虽然 图 8 仅显示了错误消息和堆栈跟踪,但服务器变量将进一步包含在电子邮件正文中。

显示可以将 ELMAH 配置为通过电子邮件发送错误详细信息的屏幕截图。

图 8:可以将 ELMAH 配置为通过Email发送错误详细信息
(单击以查看全尺寸图像)

仅记录感兴趣的错误

默认情况下,ELMAH 记录每个未处理的异常的详细信息,包括 404 和其他 HTTP 错误。 可以使用错误筛选指示 ELMAH 忽略这些或其他类型的错误。 筛选逻辑由 ELMAH 的 ErrorFilterModule HTTP 模块执行,需要 Web.config 注册该模块才能使用筛选逻辑。 用于筛选的规则在 节中 <errorFilter> 指定。

以下标记指示 ELMAH 不记录 404 错误。

<?xml version="1.0"?>
<configuration>
  ...

  <elmah>
  ...

  <errorFilter>
  <test>
  <equal binding="HttpStatusCode" value="404" type="Int32" />
  </test>
  </errorFilter>
  </elmah>

  ...
</configuration>

注意

不要忘记,若要使用错误筛选,必须注册 ErrorFilterModule HTTP 模块。

<equal> 中的 <test> 元素称为断言。 如果断言的计算结果为 true,则会从 ELMAH 的日志中筛选错误。 还有其他可用的断言,包括:<greater><greater-or-equal><not-equal><lesser><lesser-or-equal>、 等。 还可以使用 <and><or> 布尔运算符组合断言。 此外,甚至可以将简单的 JavaScript 表达式作为断言,或者用 C# 或 Visual Basic 编写自己的断言。

有关 ELMAH 的错误筛选功能的详细信息,请参阅 ELMAH 文章中的错误筛选部分

摘要

ELMAH 提供了一种简单而强大的机制,用于记录 ASP.NET Web 应用程序中的错误。 与 Microsoft 的运行状况监视系统一样,ELMAH 可以将错误记录到数据库中,并可以通过电子邮件将错误详细信息发送给开发人员。 与运行状况监视系统不同,ELMAH 包括对更广泛的错误日志数据存储的开箱即用支持,包括:Microsoft SQL Server、Microsoft Access、Oracle、XML 文件和其他几个文件。 此外,ELMAH 提供了一种内置机制,用于从网页 elmah.axd查看错误日志和有关特定错误的详细信息。 该 elmah.axd 页面还可以将错误信息呈现为 RSS 源或逗号分隔值文件, (CSV) ,你可以使用 Microsoft Excel 进行读取。 还可以指示 ELMAH 使用声明性断言或编程断言从日志中筛选错误。 ELMAH 可与 1.x 版 ASP.NET 应用程序一起使用。

每个已部署的应用程序都应具有某种机制,用于自动记录未经处理的异常,并将通知发送给开发团队。 这是使用运行状况监视还是 ELMAH 来完成。 换句话说,无论你是使用运行状况监视还是 ELMAH,这并不重要;评估这两个系统,然后选择最符合需求的系统。 至关重要的是,应建立一些机制来记录生产环境中的未经处理的异常。

编程快乐!

深入阅读

有关本教程中讨论的主题的详细信息,请参阅以下资源: