Skip to Content
Course content

227: Error Tracking with Sentry in Ruby

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Look, I've spent way too many hours of my life grep-ing through massive text files in a production terminal, trying to find the exact line where a background job died. It's a miserable way to spend a Tuesday. That's why we use error tracking. Sentry isn't just a logger; it's an alert system that tells you exactly what happened, who it happened to, and the state of the locals when the crash occurred.

Getting Sentry into the project

For this lesson, we're going to build a simple OrderProcessor. Imagine we're processing a batch of orders from a CSV or an API. Some of the data is bound to be messy, and we want to know the second a "poison pill" record crashes our loop.

First, we need the gem. I'm adding it to my Gemfile, but for this quick example, you can just run gem install sentry-ruby.

require 'sentry-ruby'

Sentry.init do |config|
  config.dsn = 'https://your-public-key@sentry.io/your-project-id'
  config.environment = 'development'
end

I always make sure to set the environment. There's nothing worse than getting paged at 3 AM for an error that's only happening on a developer's local machine because they were testing some edge case.

Writing a brittle order processor

Now, let's write a class that does something simple but dangerous. I'll create a method that calculates the total price of an order. I'm intentionally making it fragile—if the price is missing (nil), it'll throw a NoMethodError.

class OrderProcessor
  def self.process(order)
    puts "Processing order ##{order[:id]}..."
    # This will crash if order[:price] is nil
    total = order[:price] * order[:quantity]
    puts "Total: $#{total}"
  end
end

orders = [
  { id: 1, price: 10.0, quantity: 2 },
  { id: 2, price: nil, quantity: 5 }, # The poison pill
  { id: 3, price: 15.0, quantity: 1 }
]

orders.each do |order|
  OrderProcessor.process(order)
end

If you run this, the script crashes on the second order, and the third order never even gets processed. That's bad for business.

Wait, why isn't it reporting?

Here is where I usually trip up when I'm rushing. I'll wrap the call in a begin/rescue block so the script keeps running, and I'll assume Sentry is just "watching" the process in the background. I'll write something like this:

orders.each do |order|
  begin
    OrderProcessor.process(order)
  rescue StandardError => e
    puts "Something went wrong with order #{order[:id]}"
    # I'm thinking: "Sentry is initialized, it should just see this, right?"
  end
end

I ran this, saw the "Something went wrong" message in my console, and checked my Sentry dashboard. Nothing. Empty. I spent five minutes wondering if my DSN was wrong or if the network was down.

The mistake? In a plain Ruby script (unlike a Rails app where Sentry hooks into the middleware), Sentry doesn't magically know you rescued an error. If you rescue it, you've told Ruby you've handled the situation. If you want Sentry to know about it, you have to explicitly tell it.

Fixing the capture logic

To fix this, I need to use Sentry.capture_exception. This sends the error object directly to the Sentry servers while still allowing my loop to continue to the next order.

orders.each do |order|
  begin
    OrderProcessor.process(order)
  rescue StandardError => e
    # This is the missing link
    Sentry.capture_exception(e) 
    puts "Logged error for order #{order[:id]} to Sentry. Moving on..."
  end
end

Now, when that NoMethodError hits, Sentry captures the stack trace, the version of Ruby I'm using, and the specific exception message. The script doesn't die, the other orders get processed, and I get a nice notification in my browser telling me exactly what failed.




📋 Practical Task

Build a Sentry-Integrated Weather Data Parser

Create a Ruby script that simulates fetching weather data for multiple cities. The data should be represented as an array of hashes. Some hashes should be missing the "temp" key, which should cause a crash when you try to perform a calculation (like converting Celsius to Fahrenheit).

Your script must:

  • Initialize Sentry with a placeholder DSN.
  • Iterate through the cities and attempt to calculate the Fahrenheit temperature.
  • Use a begin/rescue block to ensure that one malformed city doesn't stop the entire script from processing the rest.
  • Explicitly use Sentry.capture_exception inside the rescue block to report the failure.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.