Zero Touch Application Logger
Exception handling is an important art and the truth is that it is tricky to make consistant and full-proof. There are lot of classic articles on exceptional handling of exceptions, cost of stack un-winding, global vs. local handling etc. and the manifestation of the its importance is evident from the inclusion in the Microsoft Enterprise Application Block. It's bizzare and stupid to think hardly any piece of professional quality software comes without robust exception handling policy. But still there will be time when code reviewer mistakenly skips a part which demands a SEH or Structured Exception Handling or something like that. Especially it would be excellent for an ASP.NET web application that already deployed to production server to show the logged dump of those "rare" unhandled exceptions.
This relationship is not entirely correct :
HTTP Module : .NET Fx :: ISAPI Filter : IIS
HTTP modules are more advanced filters in comparison with ISAPI one. Once registered they are dynamically picked up and injected into the ASP.NET runtime pipeline that happens within the context of a HttpApplication. More importantly they can took part in the global events' invocations as someone used to do in Global.aspx file. To handle any unhandled exception you simply have to hook the Error event of the contextual HttpApplication object
public class WebLoggerModule : IHttpModule
{
public WebLoggerModule()
{
}
public virtual void Init(HttpApplication WebApplication)
{
WebApplication.Error += new EventHandler(OnError);
}
public virtual void Dispose()
{
//Clean-up resources
return;
}
private void OnError(object sender, EventArgs e)
{
//
}
It's not recommended to maintain any state in the HTTP module implementation class for obvious reasons(AppDomain recycling...etc). Once you are inside the invocation handler its easy to get contextual application
HttpApplication WebApplication = (HttpApplication) sender;
Also note that any this will fire before any invocation handler registered by the application. Because HTTP modules are processed at much earlier stage in entire HttpRuntime's application call stack(Incoming mode or Reqest mode). The logger simply tries to get the last error and the innermost exception to unlock actual exception source. The actual logging policy could vary widely depending on the companies. In this eaxmple I have used a simple file based logger. Sometimes simple loggers are nicer compared to full-blown logging application block(Be aware of recursive call while getting exception in logging the exception !!!).
try
{
//Get the web application instance
HttpApplication WebApplication = (HttpApplication) sender;
//Get the last exception which causes this event to be fired
Exception lastException = WebApplication.Server.GetLastError();
if (lastException != null)
{
//Try to get the innermost exception from the wrapped-up
Exception deepestException = lastException;
while(deepestException.InnerException != null)
{
deepestException = deepestException.InnerException;
}
if (deepestException != null)
{
//Get the method's name which has caused this exception
sMethodName = GetMethodWhereExceptionOccurred(deepestException.StackTrace);
//Get the class's name which has caused the exception
sClassName = GetClassWhereExceptionOccurred(deepestException.StackTrace);
//Log using common logger
FileLogger oLogger =
Logger.GetLogger(sClassName,sMethodName,LoggerType.File);
oLogger.LogError("SYSTEM ERROR : " + deepestException.Message);
}
}
}
catch(Exception localException)
{
Trace.WriteLine(localException.Message);
}
Only thing left is to register the HTTP module so that ASP.NET runtime can pick it up. It is done through web.config's section. Detail description of registering a module is available in any ASP.NET book or MSDN Documentation. Just copy the assembly to bin folder of the application you want to monitor. From the next requests and onward the ZTWL(Zero Touch Web Logger...wow) will be right there at HttpApplication's call chain.