Saturday, November 10, 2012

MVC Elmah Remote Viewer

ElmahViewer Project

If you have never used Elmah, then I urge you to check it out via NuGet.  It is the quintessential .NET logging mechanism. Most people will probably use Elmah out of the box with very little configuring. This post doesn't address those implementations. If you use Elmah to log to a sql server database then this post is tailored for you.

By using SQL server as your centralized logging mechanism, you don't need direct access to a web server.  Also, some users may have their website on a farm of servers, and trying to traverse each server can be a bit of a pain.  If you are like me, then you will start using Elmah for a plethora of web projects.  I have intranet projects as well as internet projects wired up to use Elmah.  

Elmah does a good job of grabbing all of the details that comprise the error and packaging it up into a nifty little XML object.  What I needed was the ability to take all those various different applications and have one internal web page / site, where I could go through the various different errors and quickly filter through them to concentrate on a specific application.  In order to do this I had to modify the Elmah SQL script a bit and add a new column.

The only thing you should really have to do with this project is probably edit the EF object or delete it and add a new one specifying your connection string.  I would advise to keep the table name as Elmah_Error to limit the amount of work necessary to get the project running.

USE [Internal]

GO

/****** Object:  Table [dbo].[ELMAH_Error]    Script Date: 11/10/2012 14:03:23 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

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] [ntext] NOT NULL,
[AppName] [varchar](255) NULL,
 CONSTRAINT [PK_ELMAH_Error] PRIMARY KEY NONCLUSTERED 
(
[ErrorId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [INDEXDATA] TEXTIMAGE_ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

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


Create a new trigger:


CREATE trigger [dbo].[tgElmahInsert]
on [dbo].[ELMAH_Error]
for insert
as
begin
   update e
      set e.AppName = substring(i.Application,len(i.Application) - charindex('/',reverse(i.Application))+2, charindex('/',reverse(i.Application)))
     from Inserted i 
    inner join dbo.Elmah_Error e on i.ErrorId = e.ErrorId
end


Once you have the database stuff done and you are getting errors logged to the Elmah_Error table in the database of your choice, you are just about ready to start viewing them.  This is what some of the views will look like:

The Main Report Section
This comes complete with paging and jQuery UI buttons, using MVC and a WebGrid control.



This is the Cookie Section
Since Elmah took the time to package up the cookies, I took the time to display them almost the same way Elmah does out of the box, however I decided to break apart Cookie Collections if used.














Yellow Screen of Death
Error information wouldn't be complete without all the detailed error information and keeping with the original style, I show it to you right here in yellow background.



Yellow Screen of Death

Server, Form and QueryString variables
In order to properly troubleshoot your application errors having access to some of the pertinent data is invaluable.