aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activesupport/lib/active_support/notifications.rb7
-rw-r--r--activesupport/lib/active_support/notifications/fanout.rb72
-rw-r--r--activesupport/lib/active_support/notifications/instrumenter.rb6
3 files changed, 70 insertions, 15 deletions
diff --git a/activesupport/lib/active_support/notifications.rb b/activesupport/lib/active_support/notifications.rb
index 13f675c654..8cf7bdafda 100644
--- a/activesupport/lib/active_support/notifications.rb
+++ b/activesupport/lib/active_support/notifications.rb
@@ -1,3 +1,6 @@
+require 'active_support/notifications/instrumenter'
+require 'active_support/notifications/fanout'
+
module ActiveSupport
# = Notifications
#
@@ -105,10 +108,6 @@ module ActiveSupport
# to log subscribers in a thread. You can use any queue implementation you want.
#
module Notifications
- autoload :Instrumenter, 'active_support/notifications/instrumenter'
- autoload :Event, 'active_support/notifications/instrumenter'
- autoload :Fanout, 'active_support/notifications/fanout'
-
@instrumenters = Hash.new { |h,k| h[k] = notifier.listening?(k) }
class << self
diff --git a/activesupport/lib/active_support/notifications/fanout.rb b/activesupport/lib/active_support/notifications/fanout.rb
index bb1111e0c2..17c99089c1 100644
--- a/activesupport/lib/active_support/notifications/fanout.rb
+++ b/activesupport/lib/active_support/notifications/fanout.rb
@@ -20,6 +20,14 @@ module ActiveSupport
@listeners_for.clear
end
+ def start(name, id, payload)
+ listeners_for(name).each { |s| s.start(name, id, payload) }
+ end
+
+ def finish(name, id, payload)
+ listeners_for(name).each { |s| s.finish(name, id, payload) }
+ end
+
def publish(name, *args)
listeners_for(name).each { |s| s.publish(name, *args) }
end
@@ -37,22 +45,32 @@ module ActiveSupport
end
module Subscribers # :nodoc:
- def self.new(pattern, block)
- if pattern
- Subscriber.new pattern, block
+ def self.new(pattern, listener)
+ if listener.respond_to?(:call)
+ subscriber = Timed.new pattern, listener
+ else
+ subscriber = Evented.new pattern, listener
+ end
+
+ unless pattern
+ AllMessages.new(subscriber)
else
- AllMessages.new pattern, block
+ subscriber
end
end
- class Subscriber #:nodoc:
+ class Evented #:nodoc:
def initialize(pattern, delegate)
@pattern = pattern
@delegate = delegate
end
- def publish(message, *args)
- @delegate.call(message, *args)
+ def start(name, id, payload)
+ @delegate.start name, id, payload
+ end
+
+ def finish(name, id, payload)
+ @delegate.finish name, id, payload
end
def subscribed_to?(name)
@@ -65,7 +83,45 @@ module ActiveSupport
end
end
- class AllMessages < Subscriber # :nodoc:
+ class Timed < Evented
+ def initialize(pattern, delegate)
+ @timestack = Hash.new { |h,id|
+ h[id] = Hash.new { |ids,name| ids[name] = [] }
+ }
+ super
+ end
+
+ def publish(name, *args)
+ @delegate.call name, *args
+ end
+
+ def start(name, id, payload)
+ @timestack[id][name].push Time.now
+ end
+
+ def finish(name, id, payload)
+ started = @timestack[id][name].pop
+ @delegate.call(name, started, Time.now, id, payload)
+ end
+ end
+
+ class AllMessages # :nodoc:
+ def initialize(delegate)
+ @delegate = delegate
+ end
+
+ def start(name, id, payload)
+ @delegate.start name, id, payload
+ end
+
+ def finish(name, id, payload)
+ @delegate.finish name, id, payload
+ end
+
+ def publish(name, *args)
+ @delegate.publish name, *args
+ end
+
def subscribed_to?(name)
true
end
diff --git a/activesupport/lib/active_support/notifications/instrumenter.rb b/activesupport/lib/active_support/notifications/instrumenter.rb
index 547df5c731..58e292c658 100644
--- a/activesupport/lib/active_support/notifications/instrumenter.rb
+++ b/activesupport/lib/active_support/notifications/instrumenter.rb
@@ -1,5 +1,6 @@
module ActiveSupport
module Notifications
+ # Instrumentors are stored in a thread local.
class Instrumenter
attr_reader :id
@@ -12,15 +13,14 @@ module ActiveSupport
# and publish it. Notice that events get sent even if an error occurs
# in the passed-in block
def instrument(name, payload={})
- started = Time.now
-
+ @notifier.start(name, @id, payload)
begin
yield
rescue Exception => e
payload[:exception] = [e.class.name, e.message]
raise e
ensure
- @notifier.publish(name, started, Time.now, @id, payload)
+ @notifier.finish(name, @id, payload)
end
end