In the spirit of “here’s something I couldn’t find an easy answer for so I’m writing it myself”, let me very briefly run you through how to have Raygun ignore specific exception types raised by Web API.
Firstly, Web API support came a couple of months ago which is rather important given how much stuff is transitioning to APIs these days. I use Web API fairly extensively in Have I been pwned? (HIBP), partly to enable nice light async requests once pages have already loaded and partly as a dedicated API that others can consume at will.
Setting up Raygun was dead simple and it looks like this in the WebApiConfig class which is invoked on Application_Start:
public static void Register(HttpConfiguration config) { RaygunWebApiClient.Attach(config); }
Job done, except there’s a problem: The theory is that APIs should be all nice and HTTP semantic which means, for example, that if you were to request a resource via the API and that resource didn’t exist, the API should return a 404. Now I’ve got Raygun logging 404s by default because I want to know if I’ve broken a link or someone has linked to a non-existent resource or (and this happens a lot) someone is running a security scanning tool over the site and looking for things that don’t exist. However, I don’t want to log 404s that I’m intentionally throwing during the organic execution of the app.
The fix is easy enough but the solution is a little verbose code wise. Let’s extend the previous line of code like so:
private static RaygunWebApiClient _client; public static void Register(HttpConfiguration config) { RaygunWebApiClient.Attach(config, () => { if (_client == null) { _client = new RaygunWebApiClient(); _client.SendingMessage += client_SendingMessage; }</span><span style="background: white; color: blue">return </span><span style="background: white; color: black">_client;
});
private static void client_SendingMessage(object sender, RaygunSendingMessageEventArgs e)
}
{
if (e.Message.Details.Request == null || e.Message.Details.Request.Url == null || e.Message.Details.Response == null)
{
return;
} var url = e.Message.Details.Request.Url;
var code = e.Message.Details.Response.StatusCode; if (url.StartsWith("/api/v2/breachedaccount/", StringComparison.InvariantCultureIgnoreCase) && code == 404)
{
e.Cancel = true;
}
}
Ok, there’s a bit going on here but it’s (mostly) pretty intuitive:
- Call the overloaded Attach method on the RaygunWebApiClient class which takes a Func<RaygunWebApiClient> delegate
- If the RaygunWebApiClient hasn’t already been initialised, set that guy up and attach a SendingMessage event that calls client_SendingMessage (this is where the real work happens as this event is fired every time an exception is raised via Web API)
- Within client_SendingMessage, we’ll first make sure that the request, the URL on it and the response all have values (apparently there are circumstances where they may not)
- If the URL matches the one I want my custom logic on and the HTTP response code is a 404, cancel the event
Admittedly my final code is somewhat more verbose than that as I have multiple paths and status code combinations that might lead to the event being cancelled. It’d be neat to be able to do this via configuration rather than code, but certainly this is functional and achieves the behaviour I was after.