class Airbrake::Rack::Middleware

Airbrake Rack middleware for Rails and Sinatra applications (or any other Rack-compliant app). Any errors raised by the upstream application will be delivered to Airbrake and re-raised.

The middleware automatically sends information about the framework that uses it (name and version).

For Rails apps the middleware collects route performance statistics.

Public Class Methods

new(app) click to toggle source
# File lib/airbrake/rack/middleware.rb, line 14
def initialize(app)
  @app = app
end

Public Instance Methods

call(env) click to toggle source

Thread-safe {call!}.

@param [Hash] env the Rack environment @see github.com/airbrake/airbrake/issues/904

# File lib/airbrake/rack/middleware.rb, line 22
def call(env)
  dup.call!(env)
end
call!(env) click to toggle source

Rescues any exceptions, sends them to Airbrake and re-raises the exception. We also duplicate middleware to guarantee thread-safety.

@param [Hash] env the Rack environment

# File lib/airbrake/rack/middleware.rb, line 30
def call!(env)
  before_call(env)

  begin
    response = @app.call(env)
  rescue Exception => ex # rubocop:disable Lint/RescueException
    notify_airbrake(ex)
    raise ex
  end

  exception = framework_exception(env)
  notify_airbrake(exception) if exception

  response
ensure
  # Clear routes for the next request.
  RequestStore.clear
end

Private Instance Methods

before_call(env) click to toggle source
# File lib/airbrake/rack/middleware.rb, line 51
def before_call(env)
  # Rails hooks such as ActionControllerRouteSubscriber rely on this.
  RequestStore[:routes] = {}
  RequestStore[:request] = find_request(env)
end
find_request(env) click to toggle source
# File lib/airbrake/rack/middleware.rb, line 57
def find_request(env)
  if defined?(ActionDispatch::Request)
    ActionDispatch::Request.new(env)
  elsif defined?(Sinatra::Request)
    Sinatra::Request.new(env)
  else
    ::Rack::Request.new(env)
  end
end
framework_exception(env) click to toggle source

Web framework middlewares often store rescued exceptions inside the Rack env, but Rack doesn’t have a standard key for it:

# File lib/airbrake/rack/middleware.rb, line 84
def framework_exception(env)
  env['action_dispatch.exception'] ||
    env['sinatra.error'] ||
    env['rack.exception']
end
notify_airbrake(exception) click to toggle source
# File lib/airbrake/rack/middleware.rb, line 67
def notify_airbrake(exception)
  notice = Airbrake.build_notice(exception)
  return unless notice

  # ActionDispatch::Request correctly captures server port when using SSL:
  # See: https://github.com/airbrake/airbrake/issues/802
  notice.stash[:rack_request] = RequestStore[:request]

  Airbrake.notify(notice)
end