Ruby Notifier For Yeller

This is the Ruby client library for http://yellerapp.com. It lets you automatically detect errors in your application, and reports them via Yeller's API, so you can debug and fix them quickly.

There's built in support for Rails, Rack and Sinatra.

Adding to your project

yeller_ruby is distributed via rubygems. If you use bundler, add it to your Gemfile:

gem "yeller_ruby"

Otherwise you can install it:

gem install yeller_ruby

Ruby

Once you've got the gem installed, you'll need to setup a Yeller client. This means you'll need the api key from your Yeller project (which you can find on your project's setting screen). Once you have the api key, you can create a client like this:

yeller_client = Yeller.client do |client|
  client.token = "YOUR_TOKEN_HERE"
end

To report an exception, pass it into client#report. That's all you need for basic usage, after that the exception will be reported to the server, with it's stacktrace, message, type, the current host etc.

Report your own exception

begin
  # your code here
rescue StandardError => e
  yeller_client.report(e)
end

Reporting more data

Often when you want to report an exception, you have some additional data to report with it. For example, in a web application, the http request that you were processing when an exception was thrown would be helpful when debugging said exception. Yeller supports this, you can pass a hash of additional data to Yeller::Client#report, as a :custom_data option:

begin
  # your code here
rescue StandardError => e
  yeller_client.report(e, :custom_data => {:params => request.params})
end

Other customizable fields

Yeller supports a few other customizable fields.

For web applications, you can report the url you were processing:

yeller_client.report(e, :url => 'http://example.com/posts/1')

You can report the location the exception happened at. In a web application, this might be the controller action the exception ocurred in, for background jobs, the job class/queue:

yeller_client.report(e, :location => 'BillingController#update')

All of those fields are optional.

Configuration

yeller_ruby supports a few configuration options outside of the api token. You can change which servers you report to, override the hostname that's reported, or override the environment:

yeller_client = Yeller.client do |client|
  client.token = 'YOUR_TOKEN_HERE'
  client.environment = 'production'
  client.host = 'myserver.example.com'

  # to remove the default set of yeller api servers:
  client.remove_default_servers

  # to add a custom https server:
  client.add_server 'example.com', 443

  # to add a custom insecure http server (not recommended,
  # and yellerapp.com's servers don't support http, for
  # security reasons. Mostly just used for testing.
  client.add_insecure_server 'example.com', 80

  # to add a 'development environment'
  # exceptions aren't reported in development environments
  client.development_environments << 'staging'

  # to override the default development environments
  client.development_environments = ['test']
end

Robustness

This client does smart roundtripping/timeouts, so it can handle problems with individual yeller servers. After trying all the servers twice, it will stop reporting the current exception, then try each one again for the next one.

Note that in the case of network partitions, this can lead to an exception being recorded multiple times, e.g. if a connection fails (leading to a socket error) whilst reading the response from the api, but after the api has received the error. We err on the side of double reporting errors rather than potentially missing them.

What happens if the yeller api throws an error?

If the yeller api fails after trying each server twice, the client will report this error to it's error handler, which by default logs to stdout.

You can change this behaviour in the configuration:

yeller_client = Yeller.client do |client|
  client.token = 'YOUR_TOKEN_HERE'
  client.environment = 'production'
  client.host = 'myserver.example.com'
  client.error_handler = YOUR_ERROR_HANDLER
end

error_handler is any object that responds to handle, a method that takes the http api error as it's sole argument. Yeller also ships with a logging error handler, so if you have a logger in your application already, you can use that:

config.error_handler = Yeller::LogErrorHandler.new(your_logger)

Rack

Because there isn't a decent way to pass a block into a rack middleware that you're using with use (in a way that doesn't look awful anyway), Yeller::Rack relies on a global instance of the yeller client. Configure it thusly:

Yeller::Rack.configure do |config|
  config.token = 'YOUR API KEY HERE'
end

The config block takes all the same options as Yeller.client (indeed, it's directly passed into it). After configuration, simply use the middleware:

use Yeller::Rack

Sinatra

Yeller's Sinatra integration uses the Rack middleware. Here's what it looks like:

require 'sinatra'
require 'yeller/rack'

Yeller::Rack.configure do |config|
  config.token = 'YOUR API KEY HERE'
end

use Yeller::Rack
get '/' do
  raise "error"
end

Sending Affected Users

Yeller supports tracking the users affected by a particular exception. Simply attach a :user field under custom_data with an id field that's an integer:

client.report(my_exception,
  :custom_data => {
    :user => {:id  => user.id}
  }
)

Marking In App Stacktrace Frames

Yeller can highlight stacktrace lines coming from your application, and hide those that don't. This can make a big difference when reading what would otherwise be very long Ruby stacktraces:

Overriding the default project root

By default, Yeller uses Dir.pw for the project root. If this isn't right for you, you can override it in the configuration block:

yeller_client = Yeller.client do |client|
  client.token = "YOUR_TOKEN_HERE"
  client.project_root = '/var/www/my_app'
end

Note that this doesn't affect which frames you can see - you can always display all the frames:

Questions

If you have any questions, feel free to shoot me an email, .

Bugs? Improvements? This Client Library is Open Source

If you're curious about this library, it's open source, and available on: github