ASP.NET MVC Elmah Dashboard – 查看 Elmah 存在 SQL Server 的记录

Elmah 有提供一个基本的记录显示界面,可以让我们看到有哪些 Exception 被记录下来,但长久下来要在一大多的 Exception Record 里去找出问题或是作分析就会是一大难题,因为这个基本的显示界面是相当阳春的,如果有将这些记录存在 SQL Server 里的话,还可以在 SSMS 里去下 T-SQL 做数据查询,但是要要查个 Exception 纪录还要开启 SSMS 也是蛮累人的,尤其是有些团队的环境里是不允许开发人员直接连接正式环境的 SQL Server,所以就无法使用 SSMS 去做查询了。

如果有将 Elmah 所拦截的例外错误给存放到“SQL Server”的团队,这边向你们介绍一个简单方便的套件“ASP.NET MVC ELMAH Dashboard


无论是 ASP.NET WebFroms or MVC or WebApi,我都会在项目里安装使用 Elmah 来拦截纪录例外错误,这个博客里也有很多篇文章在说明,Elmah 这套件真的是一个历史悠久的工具,早在 2004 年就已经出现了,但是我真的很意外居然蛮多人是听都没有听过,甚至有许多人是不懂为何要来拦截记录错误(我就完全不懂这些人是如何知道网站发生了什么例外错误,而且怎么去做分析与修复?),有些团队虽然没有使用过 Elmah 而是选择自己建立错误处理机制或是使用其他的错误拦截记录机制,不管如何,例外错误的处理是不能够掉以轻心的,问题往往都能够从这些有被纪录的 Exception 里去被发现。

在正式进入介绍主题之前,先来回顾一下之前以 Elmah 为主题的文章:

ASP.NET MVC + ELMAH 监控并记录你的网站错误资讯 1 基本安装与介绍
ASP.NET MVC + ELMAH 监控并记录你的网站错误资讯 2 修改 elmah 的默认浏览路径
ASP.NET MVC + ELMAH 监控并记录你的网站错误资讯 3 elmah 的信件通知设定与 favicon.icon 404 错误过滤
ASP.NET MVC + ELMAH 监控并记录你的网站错误资讯 4 将 elmah 错误记录保存到 MS SQL Server 中
ELMAH - 自订错误通知邮件的设定(于特定Exception)
ASP.NET MVC 使用Glimpse监测网站的一举一动 3 - 结合ELMAH
ASP.NET MVC 3 使用 ELMAH 无法记录正确 Http Status Code ? (此篇已收录于 elmah 官网 Wiki - WebBase 单元中 http://code.google.com/p/elmah/wiki/WebBase)
ASP.NET MVC 使用 Elmah 但不安装 Elmah.MVC 的 location 修改
Elmah.MVC 2.0.0
ELMAH.MVC 2.0.1 - 可以自订浏览路径
ELMAH - 设定错误通知信件的主旨
ASP.NET MVC 与 Elmah.MVC 2.1.1 以及使用 Windows Azure SQL Database 的Schema 修改

另外还有在 2012-06-14 twMVC#2“攻略 ASP.NET MVC - 从无到有 与 性能剖析”这场研讨会里所另外准备“Log Reporting Dashboard”,这是将 Darren Weir 所创作的原始版本改写为 ASP.NET MVC 3,在 twMVC 的 Github Repository 有将改写后的源代码分享出来,

https://github.com/twMVC/twMVC-2-2

虽然有改写 Log Reporting Dashboard 并分享出来,但是在实际工作的项目里有用的的次数却是很少,很多无法使用的原因在于项目的 Log 不是存放在 SQL Server 里。

上面虽然这么说,但这篇要介绍的“ASP.NET MVC ELMAH Dashboard”这个套件的必要条件就是 Elmah 纪录是存放到 SQL Server 里,所以凡是存放到 Memory, XML 或其他保存设备的方式,就请不要在最后留言还问我存放到不是 SQL Server 的方式要怎么使用这个套件,只能支持 SQL Server 喔!

ASP.NET MVC Elmah Dashboard

http://www.arebis.be/MvcElmahDashboard/

https://www.nuget.org/packages/Arebis.Web.Mvc.ElmahDashboard/

http://www.arebis.be/MvcElmahDashboard/MvcElmahDashboard_Readme.html

image

直接给大家看最终完成结果

MVC Elmah Dashboard 首页

image

Logs

image

Log Details

imageimage

Log 查询

image

安装说明

Step.1

这边以一个新建立的 ASP.NET MVC 5 网站为例,然后安装基本的 Elmah 套件

SNAGHTML1f6da08a

Step.2

因为是要将 Elmah 存放在 SQL Server 里,这里是使用 LocalDB,所以在项目里新增 LocalDB 并且建立 Elmah 存放 Exception 记录的 Table,

image

[ELMAH.Error] Table Create Schema

--~Changing index [dbo].[ELMAH_Error].PK_ELMAH_Error to a clustered index.  You may    want to pick a different index to cluster on.
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].    [ELMAH_Error]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[ELMAH_Error](
[ErrorId] [uniqueidentifier] NOT NULL,
[Application] [nvarchar](60) NOT NULL,
[Host] [nvarchar](50) NOT NULL,
[Type] [nvarchar](100) NOT NULL,
[Source] [nvarchar](60) NOT NULL,
[Message] [nvarchar](500) NOT NULL,
[User] [nvarchar](50) NOT NULL,
[StatusCode] [int] NOT NULL,
[TimeUtc] [datetime] NOT NULL,
[Sequence] [int] IDENTITY(1,1) NOT NULL,
[AllXml] [nvarchar](max) NOT NULL,
CONSTRAINT [PK_ELMAH_Error] PRIMARY KEY CLUSTERED 
(
[ErrorId] ASC
)WITH (STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF)
)
END
 
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[dbo].[ELMAH_Error]') AND name = N'IX_ELMAH_Error_App_Time_Seq')
CREATE NONCLUSTERED INDEX [IX_ELMAH_Error_App_Time_Seq] ON [dbo].[ELMAH_Error] 
(
[Application] ASC,
[TimeUtc] DESC,
[Sequence] DESC
)WITH (STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE  = OFF)
GO
IF NOT EXISTS (SELECT * FROM dbo.sysobjects WHERE id =     OBJECT_ID(N'[DF_ELMAH_Error_ErrorId]') AND type = 'D')
BEGIN
ALTER TABLE [dbo].[ELMAH_Error] ADD  CONSTRAINT [DF_ELMAH_Error_ErrorId]  DEFAULT (newid()) FOR [ErrorId]
END
 
GO
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[ELMAH_GetErrorsXml]') AND type in (N'P', N'PC'))
BEGIN
EXEC dbo.sp_executesql @statement = N'
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
 
SELECT 
    @TotalCount = COUNT(1) 
FROM 
    [ELMAH_Error]
WHERE 
    [Application] = @Application
 
-- Get the ID of the first error for the requested page
 
SET @StartRowIndex = @PageIndex * @PageSize + 1
 
IF @StartRowIndex <= @TotalCount
BEGIN
 
    SET ROWCOUNT @StartRowIndex
 
    SELECT  
        @FirstTimeUTC = [TimeUtc],
        @FirstSequence = [Sequence]
    FROM 
        [ELMAH_Error]
    WHERE   
        [Application] = @Application
    ORDER BY 
        [TimeUtc] DESC, 
        [Sequence] DESC
 
END
ELSE
BEGIN
 
    SET @PageSize = 0
 
END
 
-- Now set the row count to the requested page size and get
-- all records below it for the pertaining application.
 
SET ROWCOUNT @PageSize
 
SELECT 
    errorId     = [ErrorId], 
    application = [Application],
    host        = [Host], 
    type        = [Type],
    source      = [Source],
    message     = [Message],
    [user]      = [User],
    statusCode  = [StatusCode], 
    time        = CONVERT(VARCHAR(50), [TimeUtc], 126) + ''Z''
FROM 
    [ELMAH_Error] error
WHERE
    [Application] = @Application
AND
    [TimeUtc] <= @FirstTimeUTC
AND 
    [Sequence] <= @FirstSequence
ORDER BY
    [TimeUtc] DESC, 
    [Sequence] DESC
FOR
    XML AUTO
 
' 
END
GO
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[ELMAH_GetErrorXml]') AND type in (N'P', N'PC'))
BEGIN
EXEC dbo.sp_executesql @statement = N'
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
 
' 
END
GO
SET ANSI_NULLS ON
SET QUOTED_IDENTIFIER ON
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].    [ELMAH_LogError]') AND type in (N'P', N'PC'))
BEGIN
EXEC dbo.sp_executesql @statement = N'
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 NVARCHAR(MAX),
@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
    )
 
' 
END
GO

如果要增加 Dashboard 搜寻的速度,建议增加 ELMAH.Error 几个字段的索引

CREATE NONCLUSTERED INDEX [IX_ELMAH_Error_Application] ON [dbo].[ELMAH_Error] ([Application] ASC)
GO
CREATE NONCLUSTERED INDEX [IX_ELMAH_Error_Host] ON [dbo].[ELMAH_Error] ([Host] ASC)
GO
CREATE NONCLUSTERED INDEX [IX_ELMAH_Error_Type] ON [dbo].[ELMAH_Error] ([Type] ASC)
GO
CREATE NONCLUSTERED INDEX [IX_ELMAH_Error_Source] ON [dbo].[ELMAH_Error] ([Source] ASC)
GO
CREATE NONCLUSTERED INDEX [IX_ELMAH_Error_User] ON [dbo].[ELMAH_Error] ([User] ASC)
GO
CREATE NONCLUSTERED INDEX [IX_ELMAH_Error_TimeUtc] ON [dbo].[ELMAH_Error] ([TimeUtc] ASC)
GO
CREATE NONCLUSTERED INDEX [IX_ELMAH_Error_Sequence] ON [dbo].[ELMAH_Error] ([Sequence] ASC)
GO

Step.3

再来就是修改 Web.Config 里面的 Elmah 设定,让 Elmah 的记录能够保存到 LocalDB 里,


    <;add name="Elmah.Sql"
         connectionString="Data Source=(LocalDB)MSSQLLocalDB;AttachDbFileName=|DataDirectory|Sample.mdf;Integrated Security=True"
         providerName="System.Data.SqlClient" />;
    

Step.4

https://www.nuget.org/packages/Arebis.Web.Mvc.ElmahDashboard/

安装“ASP.NET MVC Elmah Dashboard”套件

PM > Install-Package Arebis.Web.Mvc.ElmahDashboard

or

SNAGHTML1f8f03c8

安装完毕后,会在 Visual Studio 开启 ASP.NET MVC Elmah Dashboard 的 Readme 说明文档

image

因为这一篇文章只是做个简单的介绍,并不会讲到比较细的设定,例如 Security, 修改默认 Dashboard 路径名称等,一定要详细把 Readme 给看仔细。

Step.5

安装好套件之后,MVC Elmah Dashboard 会在 Web.Config 里的 AppSettings 增加了一些设定,还需要做一些调整,

image

MvcElmahDashboardConnectionName,这个要改为 Elmah 存放到数据库的连线名称

MvcElmahDashboardCulture,这个看各地区的语言文化来决定,例如可以填入 en-us or zh-tw,会影响日期时间的显示格式

MvcElmahDashboardLogCount,这个是设定在 Dashboard 首页里要显示多少则最新的纪录

以下是我修改后的设定内容

image

Step.6

到这边还没结束喔,因为 MVC Elmah Dashboard 是在 ASP.NET MVC 项目里增加 Areas,而且在 MvcElmahDashboard 里同样也有一个 HomeController,如果在不修改 Route 设定的情况下执行网站,那么就会遇到错误,

image

修改 ~App_Start/RouteConfig.cs,增加 namespaces 的条件约束

image

而 ~Areas/MvcElmahDashboard/MvcElmahDashboardAreaRegistration.cs 里就已经有处理了

image

修改后再重新执行网站就可以正常了,而默认的情况下只要在网址根目录后输入 MvcElmahDashboard 就可以进入 MVC Elmah Dashbaord 的页面,

image

到这边为止就算是完成了,如果有些真的不是很清楚的话,可以仔细看看 Readme,例如读取 MVC Elmah Dashboard 的权限设定

image

修改读取 MVC Elmah Dashboard 的路径设定

image

对了,在范例的说明过程中我并没有另外再安装 Elmah.MVC 喔,另外原本 Web.Config 的 Elmah 默认设定,我只有保留 elmah 区段的部分,其余的都删除。

image


以上就是给各位介绍的 ASP.NET MVC Elmah Dashboard,如果是把 Elmah 记录存放在 SQL Server 的话,不妨就考虑使用。

参考连结

MVC ELMAH Dashboard
http://www.arebis.be/MvcElmahDashboard/

MVC ELMAH Dashboard Readme
http://www.arebis.be/MvcElmahDashboard/MvcElmahDashboard_Readme.html

NuGet Gallery| ASP.NET MVC ELMAH Dashboard 1.0.0
https://www.nuget.org/packages/Arebis.Web.Mvc.ElmahDashboard/

Configuring ELMAH to use SQL Server ~ andyfrench.info
http://www.andyfrench.info/2014/07/configuring-elmah-to-use-sql-server.html

延伸阅读

mrkt 的程序学习笔记: 系统记录与性能监测
http://kevintsengtw.blogspot.tw/p/blog-page_12.html

以上

分享