Cameron
Cameron

Reputation: 28853

Notify Airbrake when capturing an exception and manually logging the error

In our Rails application we use Airbrake connected to a hosted Errbit server.

We use rescue and rescue_from in a lot of places where we want to handle any exceptions in a particular way and then we log the exception ourselves before returning a response.

Some examples we have in our ApplicationController:

  rescue_from CanCan::AccessDenied do |e|
    Rails.logger.error "CanCan exception: #{e.message}"
    render 'errors/401', status: 401
  end

  rescue_from ActionController::InvalidAuthenticityToken do |e|
    Rails.logger.error "Authenticity exception: #{e.message}"
    render 'errors/csrf', status: 400
  end

And then we also have some in individual methods such as an API:

def try_request
  Response.new(yield)
rescue RestClient::Unauthorized,
       RestClient::ExceptionWithResponse,
       RestClient::InternalServerError,
       RestClient::BadRequest => e
  Rails.logger.error "API exception: #{e.message}"
  Response.new(e.response)
end

However by using rescue we noticed that Errbit was no longer picking up our execeptions because we were capturing them... makes sense... but we want to still see these in our Errbit reports!

You can manually notify Airbrake with:

Airbrake.notify(e)

But we were hoping to avoid having to put this code in every single rescue block.

Is it possible to have a higher-level statement that can notify Airbrake automatically when manually logging errors? Perhaps middleware that is called when Rails.logger.error is called?

Upvotes: 1

Views: 1281

Answers (1)

Vasfed
Vasfed

Reputation: 18504

rescue is ruby clause, you cannot override it directly (and even if you could - it would not be a great idea)

In all your examples there's Rails.logger.error, you can make yourself a helper like:

module MyErrorNotifier
  def self.notify(message, exception, params = {}, &block)
    Rails.logger.error("#{message}: #{exception.message}")
    Airbrake.notify(exception, params, &block)
  end
end

and instead of logger call it:

def try_request
 ...
rescue e
  MyErrorNotifier.notify("Foo exception happened", e)
  Response.new(e.response)
end

Upvotes: 1

Related Questions