aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib/active_support/notifications
diff options
context:
space:
mode:
Diffstat (limited to 'activesupport/lib/active_support/notifications')
-rw-r--r--activesupport/lib/active_support/notifications/fanout.rb42
-rw-r--r--activesupport/lib/active_support/notifications/instrumenter.rb61
2 files changed, 101 insertions, 2 deletions
diff --git a/activesupport/lib/active_support/notifications/fanout.rb b/activesupport/lib/active_support/notifications/fanout.rb
index 25aab175b4..4e4ca70942 100644
--- a/activesupport/lib/active_support/notifications/fanout.rb
+++ b/activesupport/lib/active_support/notifications/fanout.rb
@@ -70,12 +70,29 @@ module ActiveSupport
module Subscribers # :nodoc:
def self.new(pattern, listener)
+ subscriber_class = Timed
+
if listener.respond_to?(:start) && listener.respond_to?(:finish)
- subscriber = Evented.new pattern, listener
+ subscriber_class = Evented
else
- subscriber = Timed.new pattern, listener
+ # Doing all this to detect a block like `proc { |x| }` vs
+ # `proc { |*x| }` or `proc { |**x| }`
+ if listener.respond_to?(:parameters)
+ params = listener.parameters
+ if params.length == 1 && params.first.first == :opt
+ subscriber_class = EventObject
+ end
+ end
end
+ wrap_all pattern, subscriber_class.new(pattern, listener)
+ end
+
+ def self.event_object_subscriber(pattern, block)
+ wrap_all pattern, EventObject.new(pattern, block)
+ end
+
+ def self.wrap_all(pattern, subscriber)
unless pattern
AllMessages.new(subscriber)
else
@@ -130,6 +147,27 @@ module ActiveSupport
end
end
+ class EventObject < Evented
+ def start(name, id, payload)
+ stack = Thread.current[:_event_stack] ||= []
+ event = build_event name, id, payload
+ event.start!
+ stack.push event
+ end
+
+ def finish(name, id, payload)
+ stack = Thread.current[:_event_stack]
+ event = stack.pop
+ event.finish!
+ @delegate.call event
+ end
+
+ private
+ def build_event(name, id, payload)
+ ActiveSupport::Notifications::Event.new name, nil, nil, id, payload
+ end
+ end
+
class AllMessages # :nodoc:
def initialize(delegate)
@delegate = delegate
diff --git a/activesupport/lib/active_support/notifications/instrumenter.rb b/activesupport/lib/active_support/notifications/instrumenter.rb
index e99f5ee688..f8344912bb 100644
--- a/activesupport/lib/active_support/notifications/instrumenter.rb
+++ b/activesupport/lib/active_support/notifications/instrumenter.rb
@@ -63,6 +63,42 @@ module ActiveSupport
@end = ending
@children = []
@duration = nil
+ @cpu_time_start = nil
+ @cpu_time_finish = nil
+ @allocation_count_start = 0
+ @allocation_count_finish = 0
+ end
+
+ # Record information at the time this event starts
+ def start!
+ @time = now
+ @cpu_time_start = now_cpu
+ @allocation_count_start = now_allocations
+ end
+
+ # Record information at the time this event finishes
+ def finish!
+ @cpu_time_finish = now_cpu
+ @end = now
+ @allocation_count_finish = now_allocations
+ end
+
+ # Returns the CPU time (in milliseconds) passed since the call to
+ # +start!+ and the call to +finish!+
+ def cpu_time
+ (@cpu_time_finish - @cpu_time_start) * 1000
+ end
+
+ # Returns the idle time time (in milliseconds) passed since the call to
+ # +start!+ and the call to +finish!+
+ def idle_time
+ duration - cpu_time
+ end
+
+ # Returns the number of allocations made since the call to +start!+ and
+ # the call to +finish!+
+ def allocations
+ @allocation_count_finish - @allocation_count_start
end
# Returns the difference in milliseconds between when the execution of the
@@ -88,6 +124,31 @@ module ActiveSupport
def parent_of?(event)
@children.include? event
end
+
+ private
+ def now
+ Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ end
+
+ if defined?(Process::CLOCK_PROCESS_CPUTIME_ID)
+ def now_cpu
+ Process.clock_gettime(Process::CLOCK_PROCESS_CPUTIME_ID)
+ end
+ else
+ def now_cpu
+ 0
+ end
+ end
+
+ if defined?(JRUBY_VERSION)
+ def now_allocations
+ 0
+ end
+ else
+ def now_allocations
+ GC.stat :total_allocated_objects
+ end
+ end
end
end
end