Tuesday, February 14, 2017

Writing plugins for Exceptionless

Exceptionless is one of those tools that no developer should be without; it integrates with your application (currently .NET and NodeJS platforms are supported, with the promise of more to come), captures your unhandled exceptions, and provides you all sorts of tools to manage these exceptions.

The project itself is open source, and you can set up your own on-premise server to run the service, or you can use their cloud service if you don’t want the hassle of maintaining YADS (Yet Another D**n Server).
Their support is also very good; I’ve been working on a number of different scenarios (e.g. creating custom reports using the API to query for data, at least until they implement custom dashboards). The scenario that prompted this post was simple – when we deploy a new version of our API, we run a suite of automated regression tests to make sure we haven’t broken anything for our customers, but these regression tests include a large number of expected failure tests, which result in a large number of false positives being reported. So time to break open the coding tools and fix that…

Show me the code

The Exceptionless client provides a number of extension points, and after talking to Blake Niemyjski, who seems to be the main point of contact for enquiries, I whipped up the following plugin:
[Priority(5)]
public class SquelchExpectedExceptionsPlugin : IEventPlugin
{
    public void Run(EventPluginContext context)
    {
        var exception = context.ContextData.GetException();
        var httpContext = context.ContextData.GetHttpContext();

        if (ApiExceptionClassifier.IsAnExpectedException(exception, httpContext.Request.Headers))
        {
            context.Cancel = true;
        }
    }
}

internal static class ExceptionlessExtensions
{
    internal static HttpActionContext GetHttpContext(this IDictionary<string, object> data)
    {
        if (!data.ContainsKey("HttpActionContext")) return null;
        return data["HttpActionContext"] as HttpActionContext;
    }

    internal static Exception GetException(this IDictionary<string, object> data)
    {
        if (!data.ContainsKey("@@_Exception")) return null;
        return data["@@Exception"] as Exception;
    }

I had to add the extension methods as these are currently internal to the Exceptionless.Net library, while the ApiExceptionClassifier is a bit of business logic which checks for a specific header the the request to determine what sort of HTTP status code a given exception should result in (e.g. we want all ValidationExceptions to result in a 400 Bad Request). The plugin priority needs to be set to a low value so that it gets executed as early as possible – there’s not much point in gathering all sorts of data if we’re just going to throw it all away when the Cancel method gets called.
Once that was done, all that is left is to register the plugin in the API’s startup routine:
ExceptionlessClient.Default.Configuration.AddPlugin<SquelchExpectedExceptionsPlugin>();
And now, my regression tests don’t fill the Exceptionless reports with noise, unless an actual exception occurs during the process.

Back from hiatus

It’s been quite a while since I last posted, so it’s probably about time I got back into the habit. More to follow shortly!