MVC使用 Elmah 日志记录组件

简介

ELMAH(Error Logging Modules and Handlers)错误日志记录模块和处理程序,是一种应用广泛的错误日志工具是完全可插拔。它可以动态添加到一个正在运行的ASP.NET Web应用程序,甚至是一台机器上的所有ASP.NET Web应用程序,而无需重新编译或重新部署。

ELMAH既支持ASP.NET Web Forms 又支持 ASP.NET MVC。你可以对ELMAH进行配置来存储各种不同的错误(XML文件,事件日志,Access数据库,SQL数据库,Oracle数据库,或者计算机 RAM。)你还可以让ELMAH在错误发生的时候,把错误信息email给你。

在默认情况下,在一个已经安装ELMAH的网站中,你可以通过请求的elmah.axd页面的方式来访问ELMAH。

使用方法

本篇来尝试Elmah在Asp.net MVC 5使用.

第一步:安装布署

首先Build 空的Asp.net MVC 5 Project:

添加Elmah引用:

Elmah组建已经配置成功.其实这个过程做了两件事:

  • A:将Elmah.dll复制到程序的根目录的Bin文件夹下.并当前项目的引用.
  • B:向项目根目录下Web.Config文件添加如下内容

在webConfig文件中添加如下内容:

  <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>

<elmah>
    <!--
        See http://code.google.com/p/elmah/wiki/SecuringErrorLogPages for
        more information on remote access and securing ELMAH.
    -->
    <security allowRemoteAccess="false" />
  </elmah>
  <location path="elmah.axd" inheritInChildApplications="false">
    <system.web>
      <httpHandlers>
        <add verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah" />
      </httpHandlers>
      <!--
        See http://code.google.com/p/elmah/wiki/SecuringErrorLogPages for
        more information on using ASP.NET authorization securing ELMAH.

      <authorization>
        <allow roles="admin" />
        <deny users="*" />
      </authorization>
      -->
    </system.web>
    <system.webServer>
      <handlers>
        <add name="ELMAH" verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah" preCondition="integratedMode" />
      </handlers>
    </system.webServer>
  </location>

第二步:测试使用

HomeController.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace Elmah.Demo.Controllers
{
    public class HomeController : Controller
    {
        //
        // GET: /Home/
        public ActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public ActionResult GenerateError(string error)
        {
            throw new ApplicationException(error);
        }

    }
}

index.cshtml

@{
    Layout = null;
    ViewBag.Title = "Index";
}

<div>
    <input type="text" id="ErrorMsg" />
    <button id="GenerateError">生成错误日志</button>
    <a href="/elmah.axd" target="_blank">在elmah中查看错误日志</a>
</div>

<script src="~/Scripts/jquery-1.10.2.js"></script>
<script type="text/javascript">
    $("#GenerateError").click(function () {
        $.post("/Home/GenerateError?error=" + $("#ErrorMsg").val());
    });
</script>

运行效果如下:

如果不是Post方式,会报黄页,如:

来看看Elmah是否记录本次执行过程中出现的异常:

可以看到Elmah已经如期的扑捉到当前应用程序的异常.ELMAH在后台记录了错误信息,并为我们提供了查询错误日志信息的界面,只需要简单的操作,就完成了基本的需求.

存储方式

有人可能会问,上面的自动配置中,并没有指定存储日志的方式啊(当然这里还没介绍如何配置,但是从上面配置中,似乎也看不到有哪里指定了存储方 式),那这些数据存储在哪里了呢?答案是,NuGet安装ELMAH后,它是没有指定任何存储方式。而ELMAH认为,如果没有指定存储方式,那么就采用 默认的内存存储方式(也可以显式的指定)。但是这种存储方式只能作为调试阶段使用,生产环境下不应使用此方式,具体的缺点请看下面对内存存储方式的介绍。

接下来就具体介绍各种存储方式,分别以数据库存储、文件存储和内存存储为例,需要强调一点,ELMAH目前只支持一下三种方式中的任意一种,不支持同时采用多种记录方式。(想必也没这个必要)

1.内存存储方式

内存存储,顾名思义,将日志记录于操作系统分配给应用程序的内存中。应用程序的内存是与应用程序域相关的,这可以保证每个应用程序只能获取和记录属于自己 的日志信息。但是,一旦应用程序重启,之前记录的信息将会消失。最简单的例子,如果你用这种方式调试呢,默认是用ASP.NET Development Server作为web服务器,如果这时停止此服务器,则就满足上述条件了(如下图)。另外,断电,发布后IIS的重启等问题,都会导致记录的信息丢失。 因此,这种方式只能用于测试用。

其实Elmah处理原理.当我们请求页面报错时.在返回黄页错误时首先被 httpModules中名为ErrorLog模块进行拦截. 该模块将本次请求出错的信息保存起来.-默认是放置在内存中.便于即时调试.但用户输入elmah.axd要查看日志信息时. 首先httpHandlers捕获到该请求.并交给专门处理elmah.axd的处理程序.该模块把错误日志View返回给用户.可见Elmah核心技术 还是基于HttpModules和HttpHandlers来实现的.

2.文件存储方式

文件存储实际上ELMAH提供了xml文件的存储方式,每一个报错日志信息生成一个xml文件。配置相当简单:

  <elmah>
    <!--
        See http://code.google.com/p/elmah/wiki/SecuringErrorLogPages for
        more information on remote access and securing ELMAH.
    -->
    <security allowRemoteAccess="false" />
    <!--只有这一句就行了,其中logPath用于指定记录日志的文件夹位置-->
    <errorLog type="Elmah.XmlFileErrorLog, Elmah" logPath="~/Static/Log/" />
  </elmah>

该配置必需确认LogPath路径目录是完整存在的.测试会发现在本地文件中(\Elmah.Demo\Static\Log)会出现一个XML文件:

3. 数据库存储方式

在数据可视化和管理上数据库依然是最理想的选择.这里采用SQlServer2008 版本测试.在构建Elmah支持SQLServer数据支持需要如下三个操作:

  • a) 告诉ELMAH使用哪种数据库作为存储数据库;
  • b) 告诉ELMAH如何连接到数据库;
  • c) 指定的数据库里,要包含ELMAH需要的表、视图和存储过程等(嵌入式数据库不需要此过程)。

其中a和b步骤需要在web.config中指定,c则需要在数据库中添加相关对象。

web.config配置如下(httpModules以及httpHandlers就不贴了,这里只给出ELMAH记录日志于sqlserver数据库的配置):

  <connectionStrings>
    <add name="elmah-sqlserver" connectionString="server=.;database=MvcTest;user id=sa;[email protected]" providerName="System.Data.SqlClient" />
  </connectionStrings>

  <elmah>
    <!--
        See http://code.google.com/p/elmah/wiki/SecuringErrorLogPages for
        more information on remote access and securing ELMAH.
    -->
    <security allowRemoteAccess="false" />
    <!--只有这一句就行了,其中logPath用于指定记录日志的文件夹位置-->
    <!--<errorLog type="Elmah.XmlFileErrorLog, Elmah" logPath="~/Static/Log/" />-->
    <!-- 告诉elmah,我要采用sqlserver来记录我的日志,连接那个数据库的字符串名为myconnectionString。-->
    <errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="elmah-sqlserver" />
  </elmah>

创建数据库,在该数据执行如下SQL语句.请参考官方的连接.

Elmah SQL Server Script File:http://code.google.com/p/elmah/source/browse/src/Elmah/SQLServer.sql

脚本:

CREATE TABLE dbo.ELMAH_Error
(
    ErrorId     UNIQUEIDENTIFIER NOT NULL,
    Application NVARCHAR(60) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
    Host        NVARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
    Type        NVARCHAR(100) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
    Source      NVARCHAR(60) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
    Message     NVARCHAR(500) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
    [User]      NVARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL,
    StatusCode  INT NOT NULL,
    TimeUtc     DATETIME NOT NULL,
    Sequence    INT IDENTITY (1, 1) NOT NULL,
    AllXml      NTEXT COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

ALTER TABLE dbo.ELMAH_Error WITH NOCHECK ADD
    CONSTRAINT PK_ELMAH_Error PRIMARY KEY NONCLUSTERED
    (
        ErrorId
    )  ON [PRIMARY]
GO

ALTER TABLE dbo.ELMAH_Error ADD
    CONSTRAINT DF_ELMAH_Error_ErrorId DEFAULT (newid()) FOR [ErrorId]
GO

CREATE NONCLUSTERED INDEX IX_ELMAH_Error_App_Time_Seq ON dbo.ELMAH_Error
(
    [Application] ASC,
    [TimeUtc] DESC,
    [Sequence] DESC
) ON [PRIMARY]
GO

SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO

CREATE PROCEDURE dbo.ELMAH_GetErrorXml
(
    @Application NVARCHAR(60),
    @ErrorId UNIQUEIDENTIFIER
)
AS

SET NOCOUNT ON

SELECT
    AllXml
FROM
    ELMAH_Error
WHERE
    ErrorId = @ErrorId
AND
    Application = @Application

GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO

CREATE PROCEDURE dbo.ELMAH_GetErrorsXml
(
    @Application NVARCHAR(60),
    @PageIndex INT = 0,
    @PageSize INT = 15,
    @TotalCount INT OUTPUT
)
AS 

SET NOCOUNT ON

DECLARE @FirstTimeUTC DateTime
DECLARE @FirstSequence int
DECLARE @StartRow int
DECLARE @StartRowIndex int

-- Get the ID of the first error for the requested page

SET @StartRowIndex = @PageIndex * @PageSize + 1
SET ROWCOUNT @StartRowIndex

SELECT
    @FirstTimeUTC = TimeUTC,
    @FirstSequence = Sequence
FROM
    ELMAH_Error
WHERE
    Application = @Application
ORDER BY
    TimeUTC DESC,
    Sequence DESC

-- Now set the row count to the requested page size and get
-- all records below it for the pertaining application.

SET ROWCOUNT @PageSize

SELECT
    @TotalCount = COUNT(1)
FROM
    ELMAH_Error
WHERE
    Application = @Application

SELECT
    errorId,
    application,
    host,
    type,
    source,
    message,
    [user],
    statusCode,
    CONVERT(VARCHAR(50), TimeUtc, 126) + ‘Z‘ time
FROM
    ELMAH_Error error
WHERE
    Application = @Application
AND
    TimeUTC <= @FirstTimeUTC
AND
    Sequence <= @FirstSequence
ORDER BY
    TimeUTC DESC,
    Sequence DESC
FOR
    XML AUTO

GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO

CREATE PROCEDURE dbo.ELMAH_LogError
(
    @ErrorId UNIQUEIDENTIFIER,
    @Application NVARCHAR(60),
    @Host NVARCHAR(30),
    @Type NVARCHAR(100),
    @Source NVARCHAR(60),
    @Message NVARCHAR(500),
    @User NVARCHAR(50),
    @AllXml NTEXT,
    @StatusCode INT,
    @TimeUtc DATETIME
)
AS

SET NOCOUNT ON

INSERT
INTO
    ELMAH_Error
    (
        ErrorId,
        Application,
        Host,
        Type,
        Source,
        Message,
        [User],
        AllXml,
        StatusCode,
        TimeUtc
    )
VALUES
    (
        @ErrorId,
        @Application,
        @Host,
        @Type,
        @Source,
        @Message,
        @User,
        @AllXml,
        @StatusCode,
        @TimeUtc
    )

GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO

执行sQL语句完成后会在当前数据库看到表:

当再次运行应用程序.在Throw ArgumentNullException时查询数据库:

简单总结一下各种方式:

  • 数据库存储方式,配置相对麻烦,但对于大规模日志的记录,效率最好;
  • 文件存储方式,配置相对简单,每日志一个文件,当数据量很大后,可能会导致巨量文件带来的效率问题;
  • 内存存储,配置最简单,但是鉴于以上原因,不应使用于生产环境。

补充

在使用Elmah过程发一下一些特点.这里需要说明一下.

Elmah是通过Http Modules 和Http Handler来记录和展示程序捕获的异常. 但是如果你在应用程序中添加异常处理模块.Try-Catch Elmah是无法记录到的.或是在Catch后在Throw出来. 在整个应用程序异常链上. 只有最终的异常抛给了Asp.net运行时Elmah组件才能捕获到并记录.

有很多人认为加入Elmah组件后能够处理应用异常.其实本质上Elmah本质上是一个日志记录工具.并没有处理异常的能力.所以如果异常发生.不会改变原来应用程序给用户体验.依然还会出现黄色页面.

在官方Note明确提到一个例外:

ELMAH捕获异常是基于HttpApplication对象的Error事件。

如果软件项目中的一些处理导致了HttpApplication事件无法被触发(比如在发生异常后,还没来得及执行Application_Error,就执行了Server.ClearError()方法,

会阻止Error事件的触发,再比如,如果一个异常被try-catch捕获到,并且没有再次throw,那么异常也是不会最终触发Error事件)

日志记录工具还是不少的,比如著名的Log4net。Log4Net包含了主要有四种重要的组件,分别是Logge, Repository, Appender以及 Layout.功能强大.可以自定义日志输出级别.具体操作可以参考我的另一遍文章:

Log4net配置与使用

提供源码,源码默认是内存存储方式,需要改为文件或者数据库,请更改<elmah> 节点下已经注释掉的相应配置即可。点击去下载

时间: 2024-10-13 10:27:53

MVC使用 Elmah 日志记录组件的相关文章

Elmah 日志记录组件

[http://www.cnblogs.com/chenkai/archive/2013/01/26/2877855.html] 常在服务器端处理用户请求时.特别是针对Web应用程序.当出现异常是可以根据日志操作记录还原异常出现时操作步骤.而记录异常堆栈信息判断问题出现问题位置. 为了跟踪和记录服务器行为.特别是针对出现异常时构建简单.统一的异常处理模式就显得尤为重要. 如果有一个基础的架构用来记录服务器端中日志和事件.那么对于调试和在问题的解决就变得更加简单直接.针对日志记录.可能针对大部分开

C#Log4net日志记录组件的使用

一.Log4Net介绍 Log4net是基于.NET开发的一款非常著名的记录日志开源组件.它通过一套XML配置的日志引擎,将日志分不同的等级,分别是:FATAL . ERROR. WARN. INFO . DEBUG.ALL(允许所有的日志请求)和OFF(拒绝所有的日志请求),缺省为DEBUG,前五个可以看到和我们平常在调试应用程序的出错有点类似,在编译器中也会留下如错误.警告之类的提示信息,它们的错误级别不断的降低. 我们接着看Log4net的核心组成部分,Log4net主要由五个部分组成,分

以HTML为表现的日志记录组件

关于日志记录,如果你不想随用随写,又不想用log4net的话,也许你可以了解一下这个! 我也是个很懒的人,程序上的东西,只要别人写好了,而且自己用着爽,绝不做重复的coding.这个组件的起源是因为感觉log4net太强大太复杂(对我来说真是这样),当我想用log4net的时候,看到配置我都吓尿n次了,而这个时候心中又突发奇想,用HTML来做日志的表现!理由有二,一是HTML和CSS大家都会,二是可以实现很好的可读可视性. 一.配置文件说明 <?xml version="1.0"

.NET Core 下 ASP.NET MVC 使用 Elmah 日志组件

.NET Core 下项目Elmah的配置和Framework下有所区别,总结一下简单使用 1.添加ElmahCore的NuGet包 2.注册Elmah服务 services.AddElmah(); //默认配置 默认配置下:日志在/Elmah路径,如      http://localhost:1996/elmah services.AddElmah(option => { option.Path = "/elm"; //设置路径 }); Elmah的记录方式有三种: Memo

ASP.Net日志记录组件XCLNetLogger发布啦

下载地址:https://github.com/xucongli1989/XCLNetLogger/releases 项目地址:https://github.com/xucongli1989/XCLNetLogger 该程序主要是向数据库中记录代码中的日志信息,配置相当简单,当然,功能也简单,献给合适的人. By:XCL @2015 mail:[email protected] http://blog.csdn.net/luoyeyu1989 使用环境 SQL SERVER Windows As

log4net日志记录

这里是接着上一篇来优化的,上篇:ASP.NET MVC中错误日志信息记录 log4Net是用来记录日志的,可以将程序运行过程中的信息输出到一些地方(文件,数据库,EventLog等),日志就是程序的黑匣子,可以通过日志查看系统的运行过程,从而发现系统的问题. 1.引用log4net.dll bin\net\2.0\release,不要引用debug版本 2.在Web.Config添加配置 把下面配置信息加到web.config中 Log4Net配置 <configuration> <co

Log4Net异常日志记录在asp.net mvc3.0的应用

前言 log4net是.Net下一个非常优秀的开源日志记录组件.log4net记录日志的功能非常强大.它可以将日志分不同的等级,以不同的格式,输出到不同的媒介.本文主要是简单的介绍如何在Visual Studio2010(Asp.Net Mvc3.0)中使用log4net快速创建系统日志,如何扩展以输出自定义字段. 用户可以从http://logging.apache.org/log4net/下载log4net的源代码.解压软件包后,在解压的src目录下将log4net.sln载入Visual

也用 Log4Net 之将日志记录到数据库的配置 (一)

也用 Log4Net  之将日志记录到数据库的配置 (一) 前段时间我一直想做一个通用一点的日志记录系统,可以便于不同的业务组调用进行日志记录及分析.本来打算着自己下手写一个,后面发现各业务组可能会需要不同的记录方式,比如利用数据库来记录,用txt的文件形式来记录,当然,这些都是最常用的记录方式.而且不同的业务组都希望有自己的记录数据表,不希望和其他业务组的数据混在一起.于是我先前设想的架构方式也就付之一炬了,因为不够灵活,而且实现难度大.周期长.恰在此时想起了之前做项目的时候用的 Log4Ne

[.Net MVC] 使用 log4net 日志框架

项目:后台管理平台 意义:项目开发中提出增加日志功能,对关键的操作.程序运行中的错误信息进行记录,这对程序部署后的调试有很大意义. 注:本文非原创,只是对网上搜集的信息进行了整合,以备今后查询. 一.最快速的上手步骤 1.用 NuGet来添加log4net 2.在项目根目录下的Web.config中添加节点.在 <configSections> 节点下添加对log4net的引用, <configSections> <section name="log4net&quo