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
# File lib/airbrake/rack/middleware.rb, line 14 def initialize(app) @app = app end
Public Instance Methods
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
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
# 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
# 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
Web framework middlewares often store rescued exceptions inside the Rack
env, but Rack
doesn’t have a standard key for it:
-
Rails
uses action_dispatch.exception: goo.gl/Kd694n -
Sinatra uses sinatra.error: goo.gl/LLkVL9
-
Goliath uses rack.exception: goo.gl/i7e1nA
# File lib/airbrake/rack/middleware.rb, line 84 def framework_exception(env) env['action_dispatch.exception'] || env['sinatra.error'] || env['rack.exception'] end
# 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