Raygun is a super easy to use monitoring tool. If you’ve ever used New Relic, it’s not too dissimilar, but focuses a bit more on crash reporting and error logging. They currently have a 14 day trial to sign up, and best of all, they have an awesome Nuget package for integrating your ASP.NET Core app. Super easy!
The Basics
To get up and running will only take a few lines of code!
First install the following Nuget package in your package manager console :
Install-Package Mindscape.Raygun4Net.AspNetCore
Next, go into your appsettings.json and add in a setting called “RaygunSettings” and inside that put “ApiKey”. This should all be at the root level so for example my complete appsettings looks like the following :
{ "Logging": { "IncludeScopes": false, "LogLevel": { "Default": "Warning" } }, "RaygunSettings": { "ApiKey": "GbuxW3gkv&^HFGbntt5VGKg==" } }
After this, head over to your startup.cs. In your ConfigureServices method, add a call to “AddRaygun” and pass in your Configuration object.
public void ConfigureServices(IServiceCollection services) { services.AddRaygun(Configuration); services.AddMvc(); }
Then in the Configure method, add in the Raygun middleware. Note that this should be early on in the pipeline (If not the very first thing in your pipeline). Remember that Middleware is run in order! If you place the Raygun middleware after the call to UseMvc for example, you will not log anything should an error be thrown inside the Mvc Middleware. It should end up looking a bit like this :
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { app.UseRaygun(); app.UseMvc(); }
Next we head over to our controller and just throw a test exception inside an action to see how we get on.
[HttpGet] public string Get() { throw new Exception("This is a test exception!"); }
When we load this in our browser and head over to the Raygun dashboard, wallah!
Manually Logging Exceptions
Now the above is great when you are just trying to catch any old unhandled exception, but there may be cases where you want to log an exception in code that you have caught and you don’t want to crash your entire application. For that, Raygun allows you to manually log exceptions.
Firstly, to log any exception you can do the following basic line of code anywhere you want :
new RaygunClient("MyAppKey").SendInBackground(e);
So if you are in a pinch and just want to get things going, there we go! Done!
One important thing to note is the “SendInBackground”, this should not be done if your code looks something like this :
try { throw new Exception("This is a test exception!"); } catch (Exception e) { new RaygunClient("MyAppKey").SendInBackground(e); throw; }
Because the throw will cause the application to crash and possible close threads before the message is sent. For that you can use the Sync version which is just “Send”. On top of that, if you are using the Raygun middleware anyway, then you shouldn’t be rethrowing as you will once again log the exception further down the middleware. In simple terms, this should only be used for “handled” exceptions.
In any case, the fact we are “new-ing” up things makes things a little hard to unit test in our code. So let’s create a nice wrapper for ourselves. First, let’s create a “Settings” object that can hold any configuration we might need for the logger. While this is only going to hold an API key at first, it’s an awesome pattern to use as it allows you to easily add new configuration options further down the line without having to mangle the constructor of our logger.
public interface IRaygunLoggerSettings { string ApiKey { get; } } public class RaygunLoggerSettings : IRaygunLoggerSettings { public string ApiKey { get; set; } }
Next create an interface called “IRaygunLogger”. This will be pretty simple at first and will only need to expose a “LogException” method.
public interface IRaygunLogger { void LogException(Exception e); }
Now let’s create an implementation of this interface called RaygunLogger. Inside this we will actually new up everything to send the exception to Raygun.
public class RaygunLogger : IRaygunLogger { private readonly IRaygunLoggerSettings _raygunLoggerSettings; public RaygunLogger(IRaygunLoggerSettings raygunLoggerSettings) { _raygunLoggerSettings = raygunLoggerSettings; } public void LogException(Exception e) { new RaygunClient(_raygunLoggerSettings.ApiKey).SendInBackground(e); } }
Now the final piece of the puzzle in setting this up is to to register all these classes in our DI container. The RaygunLoggerSettings should be registered as a singleton (As the settings will never change) and we can pull the API key direct from the configuration for this. Our RaygunLogger should be a transient instance. It would look something like this :
services.AddSingleton<IRaygunLoggerSettings>( new RaygunLoggerSettings { ApiKey = Configuration.GetSection("RaygunSettings").GetValue<string>("ApiKey") }); services.AddTransient<IRaygunLogger, RaygunLogger>();
Now it’s just about injecting our logger where we need it and logging an exception. Below is a controller that has been setup to log a simple caught exception. Now we can actually run tests through this code testing how we handle exceptions etc. Awesome!
public class ValuesController : Controller { private readonly IRaygunLogger _raygunLogger; public ValuesController(IRaygunLogger raygunLogger) { _raygunLogger = raygunLogger; } [HttpGet] public string Get() { try { throw new Exception("This is a caught exception!"); } catch (Exception e) { _raygunLogger.LogException(e); } return "All good sir!"; } }
And when we give it a whirl?!