As we all know, exception handling is critical to every application's success. It's not a matter of if something goes wrong, it's how and when. However, it's one thing to trap an exception and another to get that information into an actionable format. Anyone who's looked at a mile-long error log full of duplicate errors and with no contextual information will understand that well. So because we need not only to trap the errors but also understand them and the context they occurred in, there are many tools and libs to help. Some are open-source, like Log4Net and Elmah, and some are from Microsoft, like the Enterprise Library from Patterns and Practices. I've used all those great libraries and then some, often switching over time as my needs changed. What I ultimately landed on, though, were the plain old Trace and Debug classes provided in System.Diagnostics of the .NET framework. This allowed me to easily add both tracing and error reporting similarly while simultaneously allowing me to configure several Listeners and Filters to route and process the messaging as needed. It seems (and is) basic out of the box, but with a few modifications to a custom TraceListener, a simple Trace.TraceError.aspx) can be very powerful and packed with information. The real benefit of using the Trace and Debug classes is that you can change who is listening per app and situation while your code remains the same.
So what happens when your system isn't enough, or you need to scale across multiple platforms, even in the .NET realm? Suddenly, getting all of your exceptions in one place becomes daunting, to say the least. Then I found Raygun from the folks at Mindscape. I'm still new to the product, but from my use and implementation thus far, it's exactly what I was looking for. Put simply, its diagnostics as a service. It allows reporting exception information from nearly any code base and platform using a custom library or via their web API. It's also built for teams with support for multi-user organizations and hooks into the most popular ALM and chat software like Jira, HipChat, Campfire, and others. So centralized, searchable, alerting, and actionable diagnostic messaging across platforms that your team can access from anywhere... it's hard not to like.
Great! Found the service that I want to use, but now I'm faced with potentially refactoring quite a bit of code to take full advantage of Raygun for my server applications. It's not that The Raygun library for .NET is challenging to use; quite the contrary, it's just proprietary. So the goal was to explore allowing my current Trace and Debug code to feed into Raygun without any refactoring required. And as it turned out, after a day or so of coding and testing, I have this working well in both a large-scale web application and a critical backend windows service application.
The library I wrote is called Raygun.Diagnostics which is open source and available on Github and Nuget. I essentially built a new custom TraceListener that overrides all trace events to build the message the way Raygun wants it, which it then sends using the Raygun .NET library. The general idea is to use the Trace.TraceError method override.aspx) that accepts
(string, params object) to stuff in the extra state and tracking information we care about. So while most standard listeners expect a formatted string with args, this will use that data to generate both Raygun tags and custom data to pass along with the Exception.
In this case, I'm calling TraceError with a custom message, the Exception that occurred, an IList of tags, and either a new Dictionary with the state I want to send or simply adding that state as additional args. Now, if an out-of-the-box listener were to pick that up, like the ConsoleTraceListener.aspx), it would ignore all params beyond the message string...no harm, no foul. But to make sense of that information, the new custom trace listener picks up that message and processes it so that Raygun can make the most of it.
In this excerpt from the custom listener, the method is accepting the trace event information along with our custom
object and packaging it in a way that can then be transferred using the Raygun .NET client. Check out the full source here https://github.com/sirkirby/raygun.diagnostics/blob/master/src/Raygun.Diagnostics/RaygunTraceListener.cs
That's all there is to it. I can keep my tracing code while leveraging the cool capabilities of Raygun without any refactoring required! I will keep iterating on the library as needed or as issues arise but feel free to contribute. Issues and pull requests are welcome.