Hoptoad as an online application events log

Now everyone’s familiar with Hoptoad, right? It’s “cool”, “slick”, “essential” and is “your friend” when it comes to collecting and analyzing errors in your Rails application.

“When an uncaught exception occurs, HoptoadNotifier will POST the relevant data to the Hoptoad server specified in your environment.” But besides that it can also store any kind of information you want. That’s what the documentation says:

1 #If you want to log arbitrary things which you've rescued yourself from a
2 #controller, you can do something like this:
3 
4 rescue => ex
5   notify_hoptoad(ex)
6   flash[:failure] = 'Encryptions could not be rerouted, try again.'
7 end

What it does not say (but the comments in the sources do) is that you can also pass a hash to notify_hoptoad method and store whatever you want, not just an exception. And you can also use it anywhere, not just in controllers.

Now let’s assume you have an online store that uses some sort of third party API to calculate shipping costs. That API like any other thing you have no control over can unpredictably go down from time to time. In that case you don’t want to display an error page, but instead use some predefined shipping rate and let the customer complete his purchase. But still you want to be aware of that say to analyze how stable the API is and maybe start looking for something else if it goes down too often.

So inside your code where you make a call to the API you can notify Hoptoad when it goes down like this:

 1 begin
 2   params = {
 3     :quantity => total_quantity,
 4     :weight   => total_weight,
 5     :country  => country,
 6     :postcode => postcode    
 7   }
 8   self.shipping_rates = ShippingCalculator.new(params).shipping_rates 
 9 rescue => e
10   HoptoadNotifier.notify(
11     :error_class   => "Shipping Calculator Error",
12     :error_message => "Shipping Calculator Error: #{e.message}",
13     :request       => {:params => params}
14   )
15   self.shipping_rates = [default_shipping_rate] 
16 end

While in your controllers you can use the “notify_hoptoad” method which is mixed in when the plugin is loaded, anywhere else in your code HoptoadNotifier.notify can be used that like the “notify_hoptoad” accepts either an exception or a hash. It’s all clear with an exception – Hoptoad will get all the information about the error itself. As for a hash, this are the keys you should pass:

  • :error_class – Use this to group similar errors together. Apparently when Hoptoad catches an exception it sends the class name of that exception object.
  • :error_message – This is the title of the error you see in the errors list. For exceptions it is “#{exception.class.name}: #{exception.message}”
  • :request – While there are several ways to send additional data to Hoptoad, I’ve found passing a Hash with :params key as :request suitable for the situation described above. Apparently when Hoptoad catches an exception in a controller the actual HTTP client request is being sent using this key.

Hoptoad merges the hash you pass with these default options:

 1 def default_notice_options #:nodoc:
 2   {
 3     :api_key       => HoptoadNotifier.api_key,
 4     :error_message => 'Notification',
 5     :backtrace     => caller,
 6     :request       => {},
 7     :session       => {},
 8     :environment   => ENV.to_hash
 9   }
10 end

As you can see there are several other parameters you can set / override.

So at the end of the day I have a store that allows people to buy stuff no matter what happens to the Shipping API I use and at the same time I keep track of problems that occur in the background using a nice and friendly web interface