OWIN middleware for Raygun.io
Raygun.Owin is based around the official library from Mindscape but does not reference System.Web
. Because of this, and the lack of HttpContext
, the more generic IDictionary<string, object>
environment is used making it compatible with any OWIN implementation.
Install-Package Raygun.Owin
Install-Package Raygun.Owin.AppBuilder
- IAppBuilder supportThe primary use of this library is to log unhandled exceptions but it may also be used to log unhandled requests or as a starting point for your own logging framework.
The API key and endpoint override can be set in the middleware settings, or they can be set in your config's appSettings
like so:
<appSettings>
<add key="raygun:apiEndpoint" value="https://api.raygun.io/entries" />
<add key="raygun:apiKey" value="abc123" />
<add key="raygun:tags" value="tag1, tag2, tag3" /> <!-- supported delimiters: , ; | -->
<add key="raygun:applicationVersion" value="1.2.3.4-beta2" />
<add key="raygun:throwOnError" value="false" />
<add key="raygun:excludeErrorsFromLocal" value="true" />
</appSettings>
To log unhandled exceptions you will need to register the RaygunUnhandledExceptionMiddleware
before the middleware you would like to log errors for. Typically this would be before all other middleware is registered.
To log unhandled requests you will need to register the RaygunUnhandledRequestMiddleware
before the middleware you would like to log unhandled requests for. Since requests will pass through you may also choose to register a catch all error page. You may also exclude this altogether and log the unhandled requests from inside your application or another piece of middleware.
See the Raygun.Owin.Samples.NancyFX project for a more complete example.
public class Startup
{
public static void Configuration(IAppBuilder app)
{
var settings = new RaygunSettings();
#if DEBUG
settings.Tags.Add("debug");
#endif
app.UseRaygun(options => {
options.LogUnhandledExceptions = true;
options.LogUnhandledRequests = true;
options.Settings = settings;
});
app.UseCassette();
app.UseNancy();
app.UseStageMarker(PipelineStage.MapHandler);
}
}
Since Raygun.Owin is middleware exceptions thrown during application setup will not be caught. To log these you will need to wrap your setup code in a try/catch block and then log the exceptions manually like so:
public class Startup
{
public static void Configuration(IAppBuilder app)
{
try
{
var container = LoadIoCContainer();
RunDbMigrations(container);
SetupMiddleware(app, container);
}
catch (Exception ex)
{
new RaygunClient().SendInBackground(null, ex);
throw;
}
}
}
If you update your Startup
class to inherit from RaygunStartup
then this will be handled for you.
By default Nancy is a terminating middleware which means requests will not be passed on if they can't be handled. Because of this unhandled exceptions won't be passed on for the RaygunUnhandledExceptionMiddleware
to log. One way to get around this is like so:
public class Startup
{
public static void Configuration(IAppBuilder app)
{
var settings = new RaygunSettings();
app.UseRaygun(options => {
options.LogUnhandledExceptions = true;
options.LogUnhandledRequests = true;
options.Settings = settings;
});
app.UseNancy(options =>
{
options.PerformPassThrough = context =>
{
if (context.Response.StatusCode == HttpStatusCode.InternalServerError)
{
Exception exception;
if (context.TryGetException(out exception))
{
if (exception is RequestExecutionException)
{
exception = exception.InnerException;
}
new RaygunClient(settings).SendInBackground(context.GetOwinEnvironment(), exception);
}
}
return false;
};
});
}
}
Web API swallows exceptions in order to gracefully return their details in the call result. Because of this you will need to add an extra filter to your Web API setup, or individual controllers, which will store the exception in the current OWIN request using the key webapi.exception
.
The following is an example of this:
public class Startup
{
public static void Configuration(IAppBuilder app)
{
var config = new HttpConfiguration();
config.Filters.Add(new OwinRequestExceptionLoggerAttribute());
app.UseWebApi(config);
}
}
public class OwinRequestExceptionLoggerAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
var owinContext = actionExecutedContext.ActionContext.Request.GetOwinContext();
owinContext.Set("webapi.exception", actionExecutedContext.Exception);
}
}
Copyright (c) 2016 Brian Surowiec under the MIT License.