ELMAH and Windows Azure go together like peanut butter and jelly. If you’ve been using both, you’re probably familiar with a Nuget package that hooks ELMAH up to Table Storage. But, you may hit a snag with large exceptions. In this post, I’ll take you through how to get ELMAH and Table Storage settle some of their differences.
My apologies to readers finding this article since I previously wrote it as I have incidentally deleted the gists that were inserted.
If you’ve been building asp.net apps for Windows Azure, you may recognize ELMAH. It’s a fantastic logging add-on to any application. If you’ve never heard of it, check it out - it makes catching unhandled (and handled) exceptions a breeze.
This is especially helpful when you start deploying applications to Windows Azure, where having easy access to exceptions makes your life much less stressful when something inevitably goes wrong. Thankfully, Wade Wegner (@wadewegner) has made it super easy to get this working in Azure with his package that uses Table Storage to store exceptions. Wade gives a great write up on it in more detail.
A Little Problem
Logging the exceptions works great however, you may encounter the following exception at some point:
The property value is larger than allowed by the Table Service.
This is because the Table Storage Service limits the size of any string value property to 64KB. When you further examine the ErrorEntity class, you will find that this is actually quite easy to accomplish with exceptions that have large stack traces. A little examination reveals that the error caught by ELMAH is encoded to an XML string and saved to the SerializedError property.
Have No Fear
My solution to this is to store the serialized error in Blob Storage, and add a key (pointer) to it on the ErrorEntity. So, lets get right to the code…
I’ve added two new properties. BlobId - which will be our pointer to our blob record. OriginalError - which is needed, but we will use later. One thing you will notice is that SerializedError is gone, I will get to this a little later.
The other important things to capture is that we assign our Error that we constructed the ErrorEntity with to our new property and we also created a function to obtain it later on. The key here is that we mark the OriginalError property private. This is to prevent the property from being persisted as part of the Table Storage entity.
The Dirty Work
Now comes the fun part; getting the error into blob storage. Lets start with where we save the entity to Table Storage.
What we are doing here is simply making a call to a function (which we will define in a second) that will persist our error to blob storage and give us back and ID we can use to obtain it later.
Pretty simple eh? Now that we know how we are saving to blob storage, we can simply extract it via the reverse process.
The rest is pretty self-explanatory. You can now throw exceptions with full (large) stack traces and and ELMAH should be able to handle them all day long.