If you have an ASP.Net project mapped to an Azure worker role, then Elmah is a great exception handling framework for providing near code-less, world class exception handling for your project. Read on for a step-by-step guide.
- Create an Azure web role
- Reference the Elmah dll in your project
- In its web.config file, in the configSections node under the configuration node, add the following section:
<sectionGroup name="elmah"> <!-- NOTE! If you are using ASP.NET 1.x then remove the requirePermission="false" attribute from the section elements below as those are only needed for partially trusted applications in ASP.NET 2.0 --> <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"/> <section name="errorTweet" requirePermission="false" type="Elmah.ErrorTweetSectionHandler, Elmah"/> </sectionGroup>
- Add the elmah node right after configSections
<elmah> <security allowRemoteAccess="1" /> <errorLog type="Elmah.SqlErrorLog, Elmah" connectionString="data source=server;initial catalog=databaseuser id=user;password=password;multipleactiveresultsets=True;" /> <!--<errorFilter> <test> <jscript> <expression> <![CDATA[ // @assembly mscorlib // @assembly System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a // @import System.IO // @import System.Web HttpStatusCode == 404 || BaseException instanceof FileNotFoundException || BaseException instanceof HttpRequestValidationException /* Using RegExp below (see http://msdn.microsoft.com/en-us/library/h6e2eb7w.aspx) */ || Context.Request.UserAgent.match(/crawler/i) || Context.Request.ServerVariables['REMOTE_ADDR'] == '127.0.0.1' // IPv4 only ]]> </expression> </jscript> </test> </errorFilter>--> </elmah>
- Under the system.web section add the following modules and handlers
<httpHandlers> <add verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah"/> </httpHandlers> <httpModules> <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah"/> <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah"/> <add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah"/> </httpModules>
- Under the system.webServer section, add the following modules and handlers
<handlers> <add name="Elmah" verb="POST,GET,HEAD" path="elmah.axd" preCondition="integratedMode" type="Elmah.ErrorLogPageFactory, Elmah"/> </handlers> <modules runAllManagedModulesForAllRequests="true"> <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah"/> <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah"/> <add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah"/> </modules>
- Create the logging table in your database by running the following SQL
--~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
- To test it, go to http://yoursite/elmah.axd
Keywords: Windows Azure Exception Handling Logging
0 comments:
Post a Comment
I always welcome feedback from my readers.