BLOG Global IIS logging 30 August 2015 Previous post button Up to TOC button Next post button

Up until several years ago Visual Studio included a C++ sample project which was a wrapper around the C API that could intercept IIS Logging events. The internal plumbing of IIS has changed many times since then and the sample vanished, which was a nuisance, as I was using it to track hits on my web sites in real-time and show them in a grid which sat at the bottom corner of my server's screen.

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:

  1. Create a class library targeting Framework 3.5 (not higher).
  2. Set the project to sign the assembly with a strong name (using a SNK file).
  3. Write a class of whatever name you like that implements IHttpModule.
  4. In the Init method add a listener to the PostLogRequest event.
  5. 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.
  6. Add the assembly to the GAC by either dropping it into C:\windows\assembly or using the gacutil utility.
  7. 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).

There are many events that you can listen to, including a pair called LogRequest and PostLogRequest. Using guesswork and instinct I decided to use the latter event, and when I ran a web search I found someone who was also using it, but they had this statement inside:

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.