为祖国健康工作50年

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

    最近在研究几个ASP.NET的开源项目时,发现都在使用ELMAH来作为记录整个应用程序的错误日志,于是拿来小研究了一下,在这里和各位分享一下,如果有使用过的,请多指教。

    对于ELMAH,将用三篇系列文章来介绍:

   概念篇

    ELMAH(The Error Logging Modules And Handlers),直译过来就是“错误日志模块和处理”,它提供了一个用于集中记录和通知错误日志的机制。它是专用于ASP.NET的完全可热插拔的错误日志记录工具。其特点就是无需ASP.NET程序重新编译,即可通过配置web.config(或machine.config)来实现整个应用程序甚至是IIS中所有ASP.NET应用程序的错误日志记录工作。它支持日志的多种存储方式(各种数据库、XML、内存存储),除了提供一个界面用于查询日志详细信息外,还可以通过E-MAIL、RSS订阅或Twitter发布方式通知错误信息给相关人员。

  error0

    对于一个已经运行于生产环境的ASP.NET程序,如果想用ELMAH为程序增加错误日志记录的功能,只需要将ELMAH的dll文件复制到程序的bin目录下,然后修改此ASP.NET程序的web.config文件,就完成了所有的配置工作。以后,想查看系统发生了哪些错误信息,直接输入在web.config中事先指定的页面地址,即可看到日志信息。具体操作请看下一篇:应用篇。本文将简单介绍其基本概念和运行机制。

1.ELMAH是一个可热插拔的解决方案。也就是说可以动态的加入到ASP.NET应用程序,而不需要对项目进行重新编译和部署,因为仅需要在web.config中配置,并将一些程序集复制到bin目录下即可,而不需要更改项目中其他任何内容(如果你项目中的代码有可能导致ELMAH无法记录一些异常信息,则需要修改相关代码,具体请看下面第4条)。

2.ELMAH仅仅是后台记录未处理的异常,在异常发生时,它并不会改变用户体验,也就是说根据软件自身设置情况,用户依然可能看到黄颜色的报错界面或者被定位到一个错误提示页面。实际上,从用户体验角度,应该制定一个友好的错误页面, 可以参考文章2

3.ELMAH是通过HTTP modules与HTTP handlers来记录和展示软件中未捕获的异常(如果异常通过catch被捕获了就无法记录了,除非捕获后又throw。也就是在异常链上,最终的异常必须抛给了ASP.NET运行时,才可以被捕获)。另外,如果那个未处理的异常是ASP.NET Web service的,因为这种异常不发给HTTP modules,ELMAH也是无法记录到的.这种异常被ASP.NET运行时截获并返回一个SOAP falut(SOAP消息中传输错误及状态信息),因此,如果想记录这种异常,可以创建一个SOAP扩展来监听SOAP faults。

这里简单介绍一下HTTP modules与HTTP handlers:

当一个请求到达IIS,如果这个请求资源被配置为由ASP.NET ISAPI来处理,那么IIS将把这一请求分发给aspnet_isapi.dll,而这个dll将请求又交给了ASP.NET引擎来处理。在这一引擎里,有多个HTTP modules(可以在web.config中配置),每个请求都要依次通过这些HTTP modules,这就使得各个HTTP modules可以根据自己需要处理这些请求,当经过所有的HTTP modules后,将由一个(只能是一个)HTTP handler来处理这一请求(可以在web.config中配置由哪个HTTP handler来处理,它是根据被请求资源的路径名称或者后缀名来决定,比如可以指定如果请求error.axd这个资源文件,则由名称为ErrorLog的HTTP handler来处理。)。处理后这个HTTP handler将结果返回给用户,其过程是上述的相反过程,通过各个HTTP modules,最终到达用户端,示意图如下:

IC121205 

下面来看看ELMAH是如果根据如上的机制,来配置httpModules和handlers的。
//ELAMH添加了一个HTTP module,从而让每个请求和回应都通过它。当用户请求一个资源而报错后,返回给这个错误信息时,
//当通过了ErrorLog这个HTTP module,ELMAH获取到回应中的错误信息,并记录下来。
<httpModules>  
   <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" /> 
</httpModules>   

//当用户想查看记录下来的错误日志时,他将请求叫做elmah.axd的资源文件,这个请求最终被叫做Elmah的这个handler来
//处理,他查询错误日志的信息后,将结果返回给用户,从而实现了查询功能。
<handlers> 
  <add name="Elmah" verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah"/>
</handlers>

4.ELMAH捕获异常是基于HttpApplication对象的Error事件。如果软件项目中的一些处理导致了HttpApplication事件无法被触发(比如在发生异常后,还没来得及执行Application_Error,就执行了Server.ClearError()方法,他会阻止Error事件的触发,再比如,如果一个异常被try-catch捕获到,并且没有再次throw,那么异常也是不会最终触发Error事件),那ELMAH也就无能为力了。因此要确保这一点。

5.既然可以通过配置某一项目的web.config文件并将DLL文件Copy到项目的bin目录下即可实现对某一项目的错误日志记录,那么同样可以通过配置machine.config以及将dll文件置于GAC中,从而实现对IIS中所有ASP.NET项目实现错误日志记录。

6.还有一个常用的用于.NET异常处理的解决方案:Exception Management Application Block (EMAB)。他是Enterprise Library的一个模块。这里并不主要讨论它与ELMAH谁更好,只有哪个更适合某一应用,以下简单对比:

(1):ELMAH的机制决定他只用于ASP.NET,而EMAB同时适用于.NET的WinForm和ASP.NET,但是更适合用于WinForm,因为默认它将日志记录于操作系统的事件查看器,事件查看器适用于记录精简的日志信息,而这对于ASP.NET,如果是运行于共享主机等空间,还需要分配给ASP.NET读写事件查看器的权限,这显然有时候并不可行。当然,EMAB也可定制其他记录日志的方式,但这一切都需要开发人员去实现。

(2):EMAB不是热插拔的解决方案,需要在Global.asax的Application_Error中(或其它位置)编写相应代码。而ELMAH是热插拔的,不需要编写代码,不需要重新编译软件。

7.其实.NET下的日志记录工具还是不少的,比如著名的Log4net以及Enterprise Library中的Logging Application Block。可以说,这些工具相对ELMAH来说,太重量级了,他们可以记录各种日志信息,比如监视代码中变量的变化情况,周期性的记录到文件中供其他应用进行统计分析工作;跟踪代码运行时轨迹,作为日后审计的依据;担当集成开发环境中的调试器的作用,向文件或控制台打印代码的调试信息。因此,如果仅仅是记录ASP.NET的错误日志,ELMAH应该是首选,而其他功能,ELMAH就无能力为了,也就是说,没有所谓好坏,只有哪个更适合之说吧。

基本概念就这样吧,要想深入理解其运行机制,可以参考下面的参考文章1,讲的很详细。

备注:感谢周公帮我指出了一个笔误,不知道你会不会解梦啊:)

参考文章:
1.《Using HTTP Modules and Handlers to Create Pluggable ASP.NET Components》

2.《customErrors Element (ASP.NET Settings Schema)》

3.《ASP.NET中的HTTP模块和处理程序》

4. ELMAH主页

5.《ELMAH的web.config详细配置(v1.1)》

posted on 2011-03-29 09:09  lerit  阅读(3966)  评论(23编辑  收藏  举报