You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
152 lines
4.7 KiB
152 lines
4.7 KiB
module Rack
|
|
class MiniProfiler
|
|
module ProfilingMethods
|
|
|
|
def record_sql(query, elapsed_ms)
|
|
c = current
|
|
return unless c
|
|
c.current_timer.add_sql(query, elapsed_ms, c.page_struct, c.skip_backtrace, c.full_backtrace) if (c && c.current_timer)
|
|
end
|
|
|
|
def start_step(name)
|
|
if current
|
|
parent_timer = current.current_timer
|
|
current.current_timer = current_timer = current.current_timer.add_child(name)
|
|
[current_timer,parent_timer]
|
|
end
|
|
end
|
|
|
|
def finish_step(obj)
|
|
if obj && current
|
|
current_timer, parent_timer = obj
|
|
current_timer.record_time
|
|
current.current_timer = parent_timer
|
|
end
|
|
end
|
|
|
|
# perform a profiling step on given block
|
|
def step(name, opts = nil)
|
|
if current
|
|
parent_timer = current.current_timer
|
|
result = nil
|
|
current.current_timer = current_timer = current.current_timer.add_child(name)
|
|
begin
|
|
result = yield if block_given?
|
|
ensure
|
|
current_timer.record_time
|
|
current.current_timer = parent_timer
|
|
end
|
|
else
|
|
yield if block_given?
|
|
end
|
|
end
|
|
|
|
def unprofile_method(klass, method)
|
|
|
|
clean = clean_method_name(method)
|
|
|
|
with_profiling = ("#{clean}_with_mini_profiler").intern
|
|
without_profiling = ("#{clean}_without_mini_profiler").intern
|
|
|
|
if klass.send :method_defined?, with_profiling
|
|
klass.send :alias_method, method, without_profiling
|
|
klass.send :remove_method, with_profiling
|
|
klass.send :remove_method, without_profiling
|
|
end
|
|
end
|
|
|
|
def counter_method(klass, method, &blk)
|
|
self.profile_method(klass, method, :counter, &blk)
|
|
end
|
|
|
|
def uncounter_method(klass, method)
|
|
self.unprofile_method(klass, method)
|
|
end
|
|
|
|
def profile_method(klass, method, type = :profile, &blk)
|
|
default_name = type==:counter ? method.to_s : klass.to_s + " " + method.to_s
|
|
clean = clean_method_name(method)
|
|
|
|
with_profiling = ("#{clean}_with_mini_profiler").intern
|
|
without_profiling = ("#{clean}_without_mini_profiler").intern
|
|
|
|
if klass.send :method_defined?, with_profiling
|
|
return # dont double profile
|
|
end
|
|
|
|
klass.send :alias_method, without_profiling, method
|
|
klass.send :define_method, with_profiling do |*args, &orig|
|
|
return self.send without_profiling, *args, &orig unless Rack::MiniProfiler.current
|
|
|
|
name = default_name
|
|
if blk
|
|
name =
|
|
if respond_to?(:instance_exec)
|
|
instance_exec(*args, &blk)
|
|
else
|
|
# deprecated in Rails 4.x
|
|
blk.bind(self).call(*args)
|
|
end
|
|
end
|
|
|
|
result = nil
|
|
parent_timer = Rack::MiniProfiler.current.current_timer
|
|
|
|
if type == :counter
|
|
start = Time.now
|
|
begin
|
|
result = self.send without_profiling, *args, &orig
|
|
ensure
|
|
duration_ms = (Time.now - start).to_f * 1000
|
|
parent_timer.add_custom(name, duration_ms, Rack::MiniProfiler.current.page_struct )
|
|
end
|
|
else
|
|
page_struct = Rack::MiniProfiler.current.page_struct
|
|
|
|
Rack::MiniProfiler.current.current_timer = current_timer = parent_timer.add_child(name)
|
|
begin
|
|
result = self.send without_profiling, *args, &orig
|
|
ensure
|
|
current_timer.record_time
|
|
Rack::MiniProfiler.current.current_timer = parent_timer
|
|
end
|
|
end
|
|
|
|
result
|
|
end
|
|
klass.send :alias_method, method, with_profiling
|
|
end
|
|
|
|
# Add a custom timing. These are displayed similar to SQL/query time in
|
|
# columns expanding to the right.
|
|
#
|
|
# type - String counter type. Each distinct type gets its own column.
|
|
# duration_ms - Duration of the call in ms. Either this or a block must be
|
|
# given but not both.
|
|
#
|
|
# When a block is given, calculate the duration by yielding to the block
|
|
# and keeping a record of its run time.
|
|
#
|
|
# Returns the result of the block, or nil when no block is given.
|
|
def counter(type, duration_ms=nil)
|
|
result = nil
|
|
if block_given?
|
|
start = Time.now
|
|
result = yield
|
|
duration_ms = (Time.now - start).to_f * 1000
|
|
end
|
|
return result if current.nil? || !request_authorized?
|
|
current.current_timer.add_custom(type, duration_ms, current.page_struct)
|
|
result
|
|
end
|
|
|
|
private
|
|
|
|
def clean_method_name(method)
|
|
method.to_s.gsub(/[\?\!]/, "")
|
|
end
|
|
|
|
end
|
|
end
|
|
end
|