Ruby is a popular open source programming language that is highly flexible, and used for everything from basic "hello world" apps to sophisticated, dynamic programs. Whether you've been programming in Ruby for years or you're a complete beginner, tracking down errors in your Ruby app is simple and easy. Let's go through some basic Ruby error handling, and discover how easy it can be to integrate Rollbar into your Ruby app to automatically log and report your exceptions.
Raise and Rescue Exceptions
Ruby's default exception handling is to terminate the program in the event of an exception. That's not really useful when you're trying to build a complex web application for multiple users. Luckily there's a way around this - declaring exception handlers. Exception handlers are blocks of code that are called if an exception occurs in the execution of another block of code in your program. For the most basic Ruby exception handling, you need to know how to Raise and Rescue an exception.
When you Raise an exception, you stop the normal flow of the program, and execute the code that deals with handling an error. This code can either deal with the error in some way, or terminate the program. If you provide a Rescue clause in your error handler, you can choose how to deal with the exception; without it, the program will simply terminate.
Ruby Exception Hierarchy
Ruby has a predefined Exception class, with quite a few subclasses that can be used for basic error handling. The hierarchy of these subclasses is as follows (with commentary):
Fatal
: used internally by Ruby when it must exit due to a fatal error. Errors of this class can't be rescued.NoMemoryError
: raised when memory allocation fails.ScriptError
: used when a script is unable to be executed. This can be due to errors in any of the subclasses ofScriptError
.LoadError
: raised if a required file doesn't load.NotImplementedError
: raised when a feature isn't implemented on the current platform (i.e., trying to call a method that isn't supported by the operating system).SyntaxError
: occurs when trying to execute code with invalid syntax.
SecurityError
: raised when a potentially unsafe operation is attempted.SignalException
: used when a signal is received on a process.Interrupt
: raised if the interrupt signal is received (i.e., a user pressed Ctrl-C).
StandardError
: used for the most common types of exceptions. Usually the subclasses will be raised rather thanStandardError
itself. However, when a rescue clause without a specificStandardError
subclass is executed,StandardError
will be raised.ArgumentError
: occurs when arguments are incorrect (i.e., the wrong number of arguments).FiberError
: raised if an invalid operation is being attempted on a Fiber (i.e., trying to call a dead Fiber).IndexError
: used when the index is invalid.KeyError
: occurs if a specified key is not found.StopIteration
: raised to stop the iteration.IOError
: raised during an input/output operation failure.EOFError
: occurs when reaching the end of the file by some IO operations.LocalJumpError
: raised if Ruby cannot yield as requested in the code.NameError
: raised if a name is undefined or invalid.NoMethodError
: used when a method is called on a receiver that doesn't have the method defined, and the receiver doesn't respond withmethod_missing
.RangeError
: raised if a numerical value is out of range.FloatDomainError
: occurs when attempting to convert certain float values to unsupported classes.RegexpError
: raised if a given regular expression is invalid.RuntimeError
: used when given an invalid operation. This is a generic error class.SystemCallError
: raised for low-level, platform-dependent errors. These exceptions look likeErrno:xxx
.ThreadError
: occurs if an invalid operation is being attempted on a Thread.TypeError
: raised when an object is not of the expected type.ZeroDivisionError
: used if attempting to divide an integer by 0.
SystemExit
: raised if theexit
method is called to terminate the script.SystemStackError
: occurs during a stack overflow (i.e., in the case of an accidental infinite loop).
Basic Ruby Error Handling
Okay, so now we know what Ruby's exception hierarchy looks like, and why we need to Raise and Rescue our application's exceptions. But how do you actually do this? If you're a beginner or just new to Ruby, this might all sound fantastic in theory, but you need to see some code to actually understand what you're supposed to do.
Here's an example program that handles an exception:
def handle_exception
puts 'Lalala, our app is running without errors.'
raise 'Oh no, a error has occurred.'
rescue
puts 'Hooray the error has been rescued instead of terminating the program.'
end
handle_exception
Level Up: Ruby + Rollbar = ❤️
So far, so good. We've got our Ruby error handling down, and we're feeling like old pros. 🙂 But let's say you want to keep track of the errors that are occurring in your application, maybe even get some alerts when a certain number of exceptions are raised. What do you do? You could write some custom code and try to do this all yourself...or you could simply integrate your application with Rollbar and set your error handling, logging, and alerting on auto-pilot.
Getting Started with Rollbar
To get started, you'll need to sign up for a Rollbar account and name and create the new Ruby 'project' you will be monitoring with Rollbar. You get two weeks free when you sign up, so you can see if Rollbar is right for you.
Once you've signed up for an account you'll receive a server-side access
token which you'll need to save for later.
Installing the Gem
Installing the Gem is super easy! First, add this line to your application's Gemfile:
gem 'rollbar'
And then execute:
$ bundle install
If you don't use bundler, execute this instead:
$ gem install rollbar
Unless you are using JRuby, we suggest also installing Oj for JSON serialization. Add this line to your Gemfile:
gem 'oj', '~> 2.12.14'
and then run bundle install
again.
Basic Ruby Integration
Rollbar isn't dependent on Rack or Rails for most of its functionality, but if you're using Rack or Rails, there is more info on using both of these Ruby frameworks below. In a plain Ruby project, assuming you've installed the Rollbar gem, you just need to do these three easy steps:
- Require Rollbar
- Configure Rollbar
- Send Rollbar data
require 'rollbar'
Rollbar.configure do |config|
config.access_token = "POST_SERVER_ITEM_ACCESS_TOKEN"
# Any other configuration settings you might wish to have
end
Rollbar.debug("Running Script")
begin
run_script ARGV
rescue Exception => e # Never rescue Exception *unless* you reraise in rescue body
Rollbar.error(e)
raise e
end
Rollbar.info("Script ran successfully")
See the configuration reference guide on GitHub for further information on more advanced settings and granular configuration settings.
Using Rails
Run the following command from your Rails root:
$ rails generate rollbar POST_SERVER_ITEM_ACCESS_TOKEN
Be sure to replace POST_SERVER_ITEM_ACCESS_TOKEN
with your project's post_server_item
access token, which you can find in the Rollbar.com interface.
That will create the file config/initializers/rollbar.rb
, which initializes Rollbar and holds your access token and other configuration values.
If you want to store your access token outside of your repo, run the same command without arguments and create an environment variable ROLLBAR_ACCESS_TOKEN
that holds your server-side access token:
$ rails generate rollbar
$ export ROLLBAR_ACCESS_TOKEN=POST_SERVER_ITEM_ACCESS_TOKEN
For Heroku users:
If you're on Heroku, you can store the access token in your Heroku config:
$ heroku config:add ROLLBAR_ACCESS_TOKEN=POST_SERVER_ITEM_ACCESS_TOKEN
Using Sinatra
Initialize Rollbar with your access token somewhere during startup:
Rollbar.configure do |config|
config.access_token = 'POST_SERVER_ITEM_ACCESS_TOKEN'
config.disable_rack_monkey_patch = true
# other configuration settings
# ...
end
Then mount the middleware in your app, like:
require 'rollbar/middleware/sinatra'
class MyApp < Sinatra::Base
use Rollbar::Middleware::Sinatra
# other middleware/etc
# ...
end
Using Other Rack Frameworks
Initialize Rollbar with your access token somewhere during startup:
Rollbar.configure do |config|
config.access_token = 'POST_SERVER_ITEM_ACCESS_TOKEN'
# other configuration settings
# ...
end
Be sure to replace POST_SERVER_ITEM_ACCESS_TOKEN
with your project's post_server_item
access token, which you can find in the Rollbar.com interface.
The gem monkey patches Rack::Builder
so Rollbar reports will be sent automatically without any other action. If you prefer to disable the monkey patch, apply this change to your config::
Rollbar.configure do |config|
config.disable_rack_monkey_patch = true
# other configuration settings
# ...
end
If you disabled the Rack::Builder
monkey patch or it doesn't work for the Rack framework you are using, then add our Rack middleware to your app:
require 'rollbar/middleware/rack'
use Rollbar::Middleware::Rack
Test Your Installation
If you're not using Rails, you may first need to add the following to your Rakefile:
require 'rollbar/rake_tasks'
You may also need to add an :environment task to your Rakefile if you haven't already defined one. At minimum, this task should call Rollbar.configure() and set your access token.
task :environment do
Rollbar.configure do |config |
config.access_token = '...'
end
end
To confirm that it worked, run:
$ rake rollbar:test
This will raise an exception within a test request; if it works, you'll see a stacktrace in the console, and the exception will appear in the Rollbar dashboard.
Integration with Rollbar.js
The gem has a cool feature - you can configure the gem to enable Rollbar.js on your site to report your JavaScript errors using Rollbar.js.
Rollbar.configure do |config|
# common gem configuration
# ...
config.js_enabled = true
config.js_options = {
accessToken: "POST_CLIENT_ITEM_ACCESS_TOKEN",
captureUncaught: true,
payload: {
environment: "production"
}
}
end
The Hash
passed to #js_options=
should have the same available options that you can find in Rollbar.js, using symbols or strings for the keys.
For further information, you'll want to check out the gem docs for advanced ways to use the gem.
Diagnosing and debugging Ruby errors with Rollbar
Now that you have Rollbar integrated into your Ruby application, any errors that occur will be automatically captured and viewable from your dashboard and errors page within Rollbar (screenshot below). You'll be able to easily see what errors are occurring, how often they occur and the full context and analytics into your Ruby applications errors. Rollbar provides a detailed stack trace of every ruby exception allowing you to see exactly what's happening in your application when an error occurs. You can also view the user's browser and OS where the error occurred.
Errors are grouped by cause and frequency so that you can prioritize which ones to work on first. You'll be able to view trends over time. If a certain error spikes in frequency, you'll know about it right away. Below are more features worth noting:
- Errors automatically get grouped by root cause.
- Tons of context data like stack traces, request params, URL and environment.
- Integrate your favorite tools like Slack, GitHub, JIRA, Pivotal Tracker, Trello, PagerDuty.
- Tons of context data like stack traces, request params, URL and environment.
- View trends by type of error, browser, code deployment, OS, location, users, host.
- Mark an item as Resolved, Mute or Assign errors to others on your team to fix.
- Keep track of code deployments and correlate them them to new error occurrences.
With Rollbar, you can rest assured that you'll know about any bugs that might make their way into your Ruby projects. If you run into any issues, we're always available to help at [email protected]. Happy hacking!