Ruby on Rails

How to install Sentry to a Ruby on Rails application on a production environment

This minipost will guide you through all the required steps in order to successfully perform an advanced installation of Sentry on a Ruby on Rails application for production environment monitoring.

Navigate to sentry.io and create your account, if you haven’t done so far. We will assume that you have already created an account and a project inside your Sentry organization. Therefore, we assume that we already have a RoR application with the name appname.

Add to your Gemfile the Sentry official gem:

gem "sentry-raven"

and bundle install your project:

$ bundle install

Create a Sentry initializer(config/initializers/sentry.rb):

Raven.configure do |config|
  # Raven reports on the following environments
  config.environments = %w(staging production)
  # Sentry respects the sanitized fields specified in:
  # config/initializers/filter_parameter_logging.rb
  config.sanitize_fields = Rails.application.config.filter_parameters.map(&:to_s)
  # Raven sends events asynchronous to sentry, using the jobs/sentry_job.rb
  config.async = lambda { |event| SentryJob.perform_later(event) }
  # Overwrite excluded exceptions
  config.excluded_exceptions = []
end

To explain the above configuration, comments have been added before each line to make it straight forward. However, I would like to make clear some information about the sentry excluded exceptions line of configuration:

 config.excluded_exceptions = []

By default, Sentry is configured to exclude the following exceptions:

IGNORE_DEFAULT = [
      'AbstractController::ActionNotFound',
      'ActionController::InvalidAuthenticityToken',
      'ActionController::RoutingError',
      'ActionController::UnknownAction',
      'ActiveRecord::RecordNotFound',
      'CGI::Session::CookieStore::TamperedWithCookie',
      'Mongoid::Errors::DocumentNotFound',
      'Sinatra::NotFound'
    ].freeze

By adding = [], you override the IGNORE_DEFAULT as an empty array, and as a result, Sentry will receive all the exceptions specified above. For instance, if you are trying to test Sentry with an ActionController::RoutingError, you will not be able to see the exception on Sentry dashboard, unless you overwrite the above configuration!

Another very important part of the configuration is, the Sentry ActiveJob that will report asynchronous using Sidekiq background jobs. If you have not configure sidekiq to work on the project, just completely ignore the above setup and comment it out, otherwise, configure Sidekiq in production environment.

Very important is that you need to identify all the application attributes with sensitive information that you do not want to be reported on the error logs with the actual values. Therefore, make sure that you have added all the sensitive attribute information of the filter_parameter_logging.rb (config/initializers/filter_parameter_logging.rb) where, depending on the application, should look like the following:

Rails.application.config.filter_parameters += [:password, :password_confirmation]

Now, let's create and define the SentryJob(app/jobs/sentry_job.rb):

# Job: Raven sends asynchronous events to sentry (deliver_later)
class SentryJob < ActiveJob::Base
  queue_as :sentry

  def perform(event)
    Raven.send_event(event)
  end
end

Notice, that a specific Sidekiq Queue for :sentry has been allocated.

To make this queue work in production, you should also alter your Procfile:

web: bundle exec puma -C config/puma.rb
worker: bundle exec sidekiq -C config/sidekiq.yml

To include sentry queue to your sidekiq workers, update Sidekiq configuration .yml file with the queue name:

---
:queues:
  - default
  - mailers
  - sentry

As a final step we need to add the raven before_action callback on our Application Controller like the following:

class ApplicationController < ActionController::Base
  before_action :set_raven_context

  private

  def set_raven_context
    Raven.user_context(id: session[:current_user_id]) # or anything else in session
    Raven.extra_context(params: params.to_unsafe_h, url: request.url)
  end
End

Navigate to your sentry.io dashboard and get the SENTRY_DSN and store it on your server in an environmental variable.

To do that in a Dokku server:

dokku config:set appname SENTRY_DSN=https://[email protected]/999s
-----> Setting config vars
       SENTRY_DSN: https://[email protected]/999s
-----> Restarting app appname

With a pretty similar fashion you can add it to your Heroku server:

heroku config:set SENTRY_DSN=https://[email protected]/999s 

Commit & deploy to your Dokku server all the changes:

$ git push dokku master

At your deployment logs, you should start noticing the following lines from Sentry:

I, [2019-02-22T17:11:36.439264 #341]  INFO -- : Raven 2.9.0 ready to catch errors

Your application server will now be able to send your application errors to your sentry dashboard at sentry.io.