A few years ago I looked for way of implementing my old logging feature again, but due to confusing documentation and lack of clear guidance on how to do this in managed code I gave up.
This weekend I decided to have another bash with a clear mind on how to intercept global IIS logging using C# instead of C/C++. I eventually stumbled over these steps, which I want to document for myself and anyone else who might be interested:
- Create a class library targeting Framework 3.5 (not higher).
- Set the project to sign the assembly with a strong name (using a SNK file).
- Write a class of whatever name you like that implements IHttpModule.
- In the Init method add a listener to the PostLogRequest event.
- In the event handler you can cast the sender to a HttpApplication which then gives you properties for the Request and Response, and from there you can get lots of useful information to log.
- Add the assembly to the GAC by either dropping it into C:\windows\assembly or using the gacutil utility.
- In IIS Manager at the machine level node open IIS Modules, click Add managed Modules and you should see your assembly listed in the pick list. Give it a display name and uncheck the option for "only managed requests" (mine was unchecked by default).
var app = (HttpApplication)sender;
if (app.Context.IsPostNotification)
{
// Log here
}
Why they were doing this wasn't clear, but I decided to do the same due to lack of time. So in the logging code I get useful properties like the RawUrl, StatusCode, UserAgent, UserHostAddress and more, put them into an XML element string and broadcast the string as utf-8 bytes using UdpClient. I like this idea because the logging code is quite short and fast, and all it does is spew broadcasts out to any other apps who might like to listen and display what's happening.
I did in fact write a small WPF desktop app to listen to the broadcasts and show them in a nice grid. Because events can arrive in rapid bursts, be sure to use UdpClient BeginReceive to asynchronously process the events. Look for some samples on how to do this thread safely and efficiently without blocking.