Today we'll be talking about exception handling.
So, what is exception handling?
First, let's talk about what an exception is and why we'd want to handle one.
An exception is an event that disrupts the normal flow of an application. Since an exception, by definition, is something that isn't accounted for, there are lots of risks: system failure, data integrity issues, performance concerns, and more.
Now that we know what exceptions are, we need to figure out how to handle them.
There are many ways to handle exceptions; one of the least beneficial methods is to allow our application logs to accumulate on a server and then manually log in to the server to check them.
There are several reasons that this is a bad idea. First and foremost, you're not going to check them. Using this method is much like keeping a backup of your database; you're never going to look at them unless there's catastrophic failure that takes your system down or users start complaining. We don't even need to discuss any other reasons.
Another option is to use something like syslog. With syslog, you can have a syslog server setup that each of your servers can send logs to. I've used this approach many times and it works well, but there is still some useful functionality that is missing or requires additional work.
This is where using an exception service, such as Airbrake, Sentry, or HoneyBadger is handy.
Setting up HoneyBadger
The first thing we need to do is head over to HoneyBadger and set up an account. I've chosen the micro plan with a free 15 day trial. But any will work.
Once you've established your account, you should be redirected to the setup process, which is painless. First, you need to name your application and select the language you'll be using.
After completing that step, you'll be sent to another page that will show you how to get your application configured to send exceptions to honeybadger.io.
Now we'll need to switch over to our produciton app and configure it.
First, we'll add this to our gemfile:
gem 'honeybadger', '~> 3.1'
Next, we'll need to install the gem:
➜ produciton.com git:(bprice/setup-honeybadger) ✗ bundle
Then, we'll run the HoneyBadger install:
➜ produciton.com git:(bprice/setup-honeybadger) ✗ bundle exec honeybadger install 8fdef1aa
Installing Honeybadger 3.2.0
You're already on Honeybadger, so you're all set.
Detected Rails 5.1.4
Raising 'HoneybadgerTestingException' to simulate application failure.
At this point, we can flip back over to HoneyBadger, where we should see that our app has been successfully set up.
Now, we can click on the
Success! View Your Project button to take a look at our exceptions.
Right off the bat, we can see a lot of useful information. Let's just start at the top and work our way down. At the top of the page, we can see we're in the Errors screen, but we also see that there are Uptime, Check-ins, Deployments, and Reports sections as well.
If we go down a bit further, we can see a search bar with some default filters in there. You’ll notice
-is:ignored, which means we have a way to filter out the exceptions we actually care about seeing.
Now, if we look further down, we can see that I have 2 errors. (You will probably only have one, but this actually caught an exception where I didn't have my database running locally.)
We can see the last time the error was reported, the total number of times the exception has happened in the last hour, the environment it occurred in; from here, we have the ability to assign it to someone, or the ability to resolve it.
You can also see that HoneyBadger keeps track of deployments. This is a nifty feature that, if you remember from our previous video, Scout also supported. This is a great feature to identify when an exception first appeared, which gives you just a bit more information and context to help resolve the issue. This is also a very convenient feature to have for reporting purposes. It can visually bring to your attention the fact that the QA workflow change you made 3 weeks ago has resulted in a 20% increase in exceptions.
Now, let's take a look at an exception:
Here, we can see that we have more in-depth information about an exception.
We have access to the backtrace, url, location, occurence metrics, context (where you can pass additional information from the application), environment information, history, and more.
Next, we need to get a new image built and pushed to AWS.
➜ docker build -t production .
➜ docker tag production:latest 154477107666.dkr.ecr.us-east-1.amazonaws.com/dailydrip/produciton
➜ $(aws ecr get-login --no-include-email)
➜ docker push 154477107666.dkr.ecr.us-east-1.amazonaws.com/dailydrip/produciton:latest
Now, we just need to restart our service. If you've followed along with the previous videos, we've always done this via the AWS Console; however, today we're going to use the AWS cli to do this.
➜ aws ecs update-service --service production-load-balanced --cluster Produciton --force-new-deployment
If we flip over to our AWS Dashboard and look at our service, we should see the new tasks being provisioned.
We can also see this using the AWS cli:
➜ aws ecs list-tasks --service production-load-balanced --cluster Produciton
Now, we need to test that our exception handling is working correctly. Since we don't have much code and, by default, HoneyBadger is ignoring a lot of errors you could easily reproduce (routing errors), I'm going to take another approach to easily verify that this works.
I'm going to temporarily turn off my database. This can be done by selecting the database and choosing
Stop from the
Instance Actions button.
This will take a few minutes, but once the database is down, we should be able to try to reload the app and get an exception in HoneyBadger.
In this video, we went over configuring our application to send exceptions to HoneyBadger and some of the base features they offer.