aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib/active_support/notifications/instrumenter.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activesupport/lib/active_support/notifications/instrumenter.rb')
-rw-r--r--activesupport/lib/active_support/notifications/instrumenter.rb84
1 files changed, 78 insertions, 6 deletions
diff --git a/activesupport/lib/active_support/notifications/instrumenter.rb b/activesupport/lib/active_support/notifications/instrumenter.rb
index e99f5ee688..a03e7e483e 100644
--- a/activesupport/lib/active_support/notifications/instrumenter.rb
+++ b/activesupport/lib/active_support/notifications/instrumenter.rb
@@ -13,14 +13,15 @@ module ActiveSupport
@notifier = notifier
end
- # Instrument the given block by measuring the time taken to execute it
- # and publish it. Notice that events get sent even if an error occurs
- # in the passed-in block.
+ # Given a block, instrument it by measuring the time taken to execute
+ # and publish it. Without a block, simply send a message via the
+ # notifier. Notice that events get sent even if an error occurs in the
+ # passed-in block.
def instrument(name, payload = {})
# some of the listeners might have state
listeners_state = start name, payload
begin
- yield payload
+ yield payload if block_given?
rescue Exception => e
payload[:exception] = [e.class.name, e.message]
payload[:exception_object] = e
@@ -52,8 +53,13 @@ module ActiveSupport
end
class Event
- attr_reader :name, :time, :transaction_id, :payload, :children
- attr_accessor :end
+ attr_reader :name, :time, :end, :transaction_id, :payload, :children
+
+ def self.clock_gettime_supported? # :nodoc:
+ defined?(Process::CLOCK_PROCESS_CPUTIME_ID) &&
+ !Gem.win_platform?
+ end
+ private_class_method :clock_gettime_supported?
def initialize(name, start, ending, transaction_id, payload)
@name = name
@@ -63,6 +69,47 @@ 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
+
+ def end=(ending)
+ ActiveSupport::Deprecation.deprecation_warning(:end=, :finish!)
+ @end = ending
+ 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 +135,31 @@ module ActiveSupport
def parent_of?(event)
@children.include? event
end
+
+ private
+ def now
+ Concurrent.monotonic_time
+ end
+
+ if clock_gettime_supported?
+ 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