aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Schierbeck <daniel.schierbeck@gmail.com>2018-10-24 16:00:31 +0200
committerJeremy Daer <jeremydaer@gmail.com>2019-03-19 08:35:09 -0700
commit04ae0b0b5e594e0bb99c5cd608921745977bcdcd (patch)
treec01abaa20879bdcc3ae50ddb90afe285f824447c
parent299573adc60fe0f7aa68f9c66df5ffe2efb0df40 (diff)
downloadrails-04ae0b0b5e594e0bb99c5cd608921745977bcdcd.tar.gz
rails-04ae0b0b5e594e0bb99c5cd608921745977bcdcd.tar.bz2
rails-04ae0b0b5e594e0bb99c5cd608921745977bcdcd.zip
Instrument middleware processing
Adds ActiveSupport::Notifications instrumentation of the processing of each middleware in the stack.
-rw-r--r--actionpack/lib/action_dispatch/middleware/stack.rb23
-rw-r--r--actionpack/test/dispatch/middleware_stack_test.rb41
2 files changed, 57 insertions, 7 deletions
diff --git a/actionpack/lib/action_dispatch/middleware/stack.rb b/actionpack/lib/action_dispatch/middleware/stack.rb
index 7a2fcd6db7..f0c869fba0 100644
--- a/actionpack/lib/action_dispatch/middleware/stack.rb
+++ b/actionpack/lib/action_dispatch/middleware/stack.rb
@@ -34,7 +34,28 @@ module ActionDispatch
end
def build(app)
- klass.new(app, *args, &block)
+ InstrumentationProxy.new(klass.new(app, *args, &block), 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
diff --git a/actionpack/test/dispatch/middleware_stack_test.rb b/actionpack/test/dispatch/middleware_stack_test.rb
index 5f43e5a3c5..90f2eccd19 100644
--- a/actionpack/test/dispatch/middleware_stack_test.rb
+++ b/actionpack/test/dispatch/middleware_stack_test.rb
@@ -3,13 +3,24 @@
require "abstract_unit"
class MiddlewareStackTest < ActiveSupport::TestCase
- class FooMiddleware; end
- class BarMiddleware; end
- class BazMiddleware; end
- class HiyaMiddleware; end
- class BlockMiddleware
+ class Base
+ def initialize(app)
+ @app = app
+ end
+
+ def call(env)
+ @app.call(env)
+ end
+ end
+
+ class FooMiddleware < Base; end
+ class BarMiddleware < Base; end
+ class BazMiddleware < Base; end
+ class HiyaMiddleware < Base; end
+ class BlockMiddleware < Base
attr_reader :block
- def initialize(&block)
+ def initialize(app, &block)
+ super(app)
@block = block
end
end
@@ -109,6 +120,24 @@ class MiddlewareStackTest < ActiveSupport::TestCase
assert_equal @stack.last, @stack.last
end
+ test "instruments the execution of middlewares" do
+ app = @stack.build(proc { |env| [200, {}, []] })
+ env = {}
+
+ events = []
+
+ subscriber = proc do |*args|
+ events << ActiveSupport::Notifications::Event.new(*args)
+ end
+
+ ActiveSupport::Notifications.subscribed(subscriber, "process_middleware.action_dispatch") do
+ app.call(env)
+ end
+
+ assert_equal 2, events.count
+ assert_equal ["MiddlewareStackTest::BarMiddleware", "MiddlewareStackTest::FooMiddleware"], events.map { |e| e.payload[:middleware] }
+ end
+
test "includes a middleware" do
assert_equal true, @stack.include?(ActionDispatch::MiddlewareStack::Middleware.new(BarMiddleware, nil, nil))
end