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).

Constants

RACK_FILTERS

@return [Array<Class>] the list of Rack filters that read Rack request

information and append it to notices

Public Class Methods

new(app, notifier_name = :default) click to toggle source

rubocop:enable Style/ClassVars

# File lib/airbrake/rack/middleware.rb, line 31
def initialize(app, notifier_name = :default)
  @app = app
  @notifier = Airbrake[notifier_name]

  # Prevent adding same filters to the same notifier.
  return if @@known_notifiers.include?(notifier_name)
  @@known_notifiers << notifier_name

  return unless @notifier
  RACK_FILTERS.each do |filter|
    @notifier.add_filter(filter.new)
  end
end

Public Instance Methods

call(env) click to toggle source

Rescues any exceptions, sends them to Airbrake and re-raises the exception. @param [Hash] env the Rack environment

# File lib/airbrake/rack/middleware.rb, line 49
def call(env)
  # rubocop:disable Lint/RescueException
  begin
    response = @app.call(env)
  rescue Exception => ex
    notify_airbrake(ex, env)
    raise ex
  end
  # rubocop:enable Lint/RescueException

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

  response
end

Private Instance Methods

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 90
def framework_exception(env)
  env['action_dispatch.exception'] ||
    env['sinatra.error'] ||
    env['rack.exception']
end
notify_airbrake(exception, env) click to toggle source
# File lib/airbrake/rack/middleware.rb, line 67
def notify_airbrake(exception, env)
  notice = @notifier.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] =
    if defined?(ActionDispatch::Request)
      ActionDispatch::Request.new(env)
    else
      ::Rack::Request.new(env)
    end

  @notifier.notify(notice)
end