Introduction
Always monitoring a web application has been a common requirement for professional developers and site administrators. For ASP.NET 1.x there were some solutions that were written by community such as famous ELMAH (Error Logging Modules and Handlers) but now ASP.NET 2.0 has its own mechanism to let developers monitor their applications. There are some default providers to let you get events via email, log them into SQL Server database or server's Log Events or map them to WMI.
There is also another available option for you to write your own provider. In this article I show you how to do this by creating an XML provider step by step.
How to Write a Custom Provider
Writing a custom Health Monitoring web event provider is as easy as creating a Class Library project, a class in it and write a class that is inherited from System.Web.Management.BufferedWebEventProvider abstract base class and overriding its methods.
There are four methods in BufferedWebEventProvider abstract base class that you should override:
- Initialize(string, NameValueCollection): Occurs when your web event provider is being initialized.
- ProcessEvent(WebBaseEvent): Occurs when an event occurs in your application. If provider is configured to buffer events, they will be added to buffer otherwise you need to save them.
- ProcessEventFlush(WebEventBufferFlushInfo): Occurs when provider is being flushed and you need to implement your logic to save all buffered events.
- Shutdown(): Occurs when provider is being shut down.
User can configure this provider to buffer events so you need to consider this case in your code and try to save buffered events.
Write an XML Provider
Now I show you how to override those methods to write a custom web event provider. Before anything you need to know that I used a DataSet to save my event data into an XML file.
First I create a class, add necessary references and inherit it from BufferedWebEventProvider abstract base class.
using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.Management;
using System.Collections.Specialized;
using System.Xml;
using System.IO;
using System.Data;
namespace CustomHealthMonitorProvider
{
public class XmlProvider : BufferedWebEventProvider
{
I add some private variables to keep my data such as my XML file path, my provider name and my DataSet to save event data.
#region "Private members"
private string providerName = null;
private string filePath = null;
private DataSet data = new DataSet();
#endregion
My implementation for Initialize() method tries to set some values for my private members then creates an initial empty XML file with correct structure and saves it by calling CreateInitialFile() private method.
public override void Initialize(string name, NameValueCollection configuration)
{
base.Initialize(name, configuration);
this.providerName = name;
this.filePath = @"C:\MyFile.xml";
if (!File.Exists(this.filePath))
CreateInitialFile();
this.data.ReadXml(this.filePath);
}
private void CreateInitialFile()
{
DataSet ds = new DataSet(this.providerName);
DataTable table = new DataTable("Events");
table.Columns.Add("EventID");
table.Columns.Add("EventTime");
table.Columns.Add("EventOccurrence");
table.Columns.Add("Message");
table.Columns.Add("Details");
ds.Tables.Add(table);
this.data = ds;
SaveData();
}
Now I override ProcessEvent() and ProcessEventFlush() methods to add events to my DataSet based on user configuration for buffering events then save them into the XML file.
public override void ProcessEvent(WebBaseEvent eventRaised)
{
if (base.UseBuffering)
{
base.ProcessEvent(eventRaised);
}
else
{
DataRow row = GetRow(eventRaised);
this.data.Tables[0].Rows.Add(row);
SaveData();
}
}
public override void ProcessEventFlush(WebEventBufferFlushInfo flushInfo)
{
foreach (WebBaseEvent anEvent in flushInfo.Events)
{
DataRow row = GetRow(anEvent);
this.data.Tables[0].Rows.Add(row);
}
SaveData();
}
GetRow() and SaveData() private methods are very simple. First one creates a DataRow object from the properties of a WebBaseEvent object and second one saves the content of my DataSet into XML file.
private DataRow GetRow(WebBaseEvent eventRaised)
{
DataRow row = this.data.Tables[0].NewRow();
row["EventID"] = eventRaised.EventID;
row["EventTime"] = eventRaised.EventTime;
row["EventOccurrence"] = eventRaised.EventOccurrence;
row["Message"] = eventRaised.Message;
row["Details"] = eventRaised.ToString();
return row;
}
private void SaveData()
{
this.data.AcceptChanges();
this.data.WriteXml(this.filePath);
}
Finally I don't need to override anything for ShutDown() method so simply call it from base class.
public override void Shutdown()
{
base.Flush();
}
Test
Now that I have an XML web event provider, which can save my ASP.NET 2.0 application events into an XML file. First I create a simple ASP.NET 2.0 website that has only one page which contains nothing except raising an exception:
protected void Page_Load(object sender, EventArgs e)
{
throw new ApplicationException
("This is an error thrown to be logged in XML file.");
}
Now it's time to configure my application to use my XML web event provider.
<healthMonitoring enabled="true">
<providers>
<add
name="MyXMLWebEventProvider"
buffer="false"
bufferMode="Notification"
type="CustomHealthMonitorProvider.XmlProvider,
CustomHealthMonitorProvider" />
</providers>
<rules>
<add name="LogAllEvents"
eventName="All Events"
provider="MyXMLWebEventProvider"/>
</rules>
</healthMonitoring>
By hitting my page I get an error. After this I can check my XML file to see the events logged there:
<?xml version="1.0" standalone="yes"?>
<MyXMLWebEventProvider>
<!-- Other events are removed to save space -->
<Events>
<EventID>dcbdf3c6-6208-48f3-93e7-c261e4ef86eb</EventID>
<EventTime>9/18/2006 11:06:55 AM</EventTime>
<EventOccurrence>1</EventOccurrence>
<Message>An unhandled exception has occurred.</Message>
<Details>Event code: 3005
Event message: An unhandled exception has occurred.
Event time: 9/18/2006 11:06:55 AM
Event time (UTC): 9/18/2006 4:06:55 PM
Event ID: dcbdf3c6620848f393e7c261e4ef86eb
Event sequence: 4
Event occurrence: 1
Event detail code: 0
Application information:
Application domain: a34130de-1-128030692127031250
Trust level: Full
Application Virtual Path: /HealthMonitoring
Application Path: C:\Documents and Settings\Keyvan Nayyeri\My Documents\Visual Studio 2005\WebSites\HealthMonitoring\
Machine name: KEYVANNAYYERI
Process information:
Process ID: 8800
Process name: WebDev.WebServer.EXE
Account name: KEYVANNAYYERI\Keyvan Nayyeri
Exception information:
Exception type: System.ApplicationException
Exception message: This is an error thrown to be logged in XML file.
Request information:
Request URL: http://localhost:3705/HealthMonitoring/Default.aspx
Request path: /HealthMonitoring/Default.aspx
User host address: 127.0.0.1
User: KEYVANNAYYERI\Keyvan Nayyeri
Is authenticated: True
Authentication Type: NTLM
Thread account name: KEYVANNAYYERI\Keyvan Nayyeri
Thread information:
Thread ID: 4
Thread account name: KEYVANNAYYERI\Keyvan Nayyeri
Is impersonating: False
Stack trace: at _Default.Page_Load(Object sender, EventArgs e)
at System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e)
at System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e)
at System.Web.UI.Control.OnLoad(EventArgs e)
at System.Web.UI.Control.LoadRecursive()
at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
</Details>
</Events>
</MyXMLWebEventProvider>
You can extend my provider to save more properties for events and write a reporting application to show this data.
Summary
In this article I talked about the process you need to follow to create a custom web event provider for ASP.NET 2.0 Health Monitoring feature. I showed this by implementing an XML web event provider and describing the process step by step.
Download
You can download the source code of my XML web event provider.
About Keyvan Nayyeri
 |
Keyvan is a software architect and developer who has a bachelor of science degree in applied mathematics. He was born in Kermanshah, Kurdistan, in 1984.
Keyvan’s main focus is on Microsoft development technologies and their related technologies such as mark-up languages. He’s also experie...
View complete profile
|
Please login to rate or to leave a comment.