diff options
Diffstat (limited to 'actionpack/lib/action_dispatch/middleware/stack.rb')
-rw-r--r-- | actionpack/lib/action_dispatch/middleware/stack.rb | 37 |
1 files changed, 34 insertions, 3 deletions
diff --git a/actionpack/lib/action_dispatch/middleware/stack.rb b/actionpack/lib/action_dispatch/middleware/stack.rb index b82f8aa3a3..775110d95e 100644 --- a/actionpack/lib/action_dispatch/middleware/stack.rb +++ b/actionpack/lib/action_dispatch/middleware/stack.rb @@ -36,6 +36,31 @@ module ActionDispatch def build(app) klass.new(app, *args, &block) end + + def build_instrumented(app) + InstrumentationProxy.new(build(app), inspect) + end + end + + # This class is used to instrument the execution of a single middleware. + # It proxies the `call` method transparently and instruments the method + # call. + class InstrumentationProxy + EVENT_NAME = "process_middleware.action_dispatch" + + def initialize(middleware, class_name) + @middleware = middleware + + @payload = { + middleware: class_name, + } + end + + def call(env) + ActiveSupport::Notifications.instrument(EVENT_NAME, @payload) do + @middleware.call(env) + end + end end include Enumerable @@ -97,12 +122,18 @@ module ActionDispatch middlewares.push(build_middleware(klass, args, block)) end - def build(app = Proc.new) - middlewares.freeze.reverse.inject(app) { |a, e| e.build(a) } + def build(app = nil, &block) + instrumenting = ActiveSupport::Notifications.notifier.listening?(InstrumentationProxy::EVENT_NAME) + middlewares.freeze.reverse.inject(app || block) do |a, e| + if instrumenting + e.build_instrumented(a) + else + e.build(a) + end + end end private - def assert_index(index, where) i = index.is_a?(Integer) ? index : middlewares.index { |m| m.klass == index } raise "No such middleware to insert #{where}: #{index.inspect}" unless i |