3 module ActionController
#:nodoc:
4 # The benchmarking module times the performance of actions and reports to the logger. If the Active Record
5 # package has been included, a separate timing section for database calls will be added as well.
6 module Benchmarking
#:nodoc:
7 def self.included(base
)
8 base
.extend(ClassMethods
)
11 alias_method_chain
:perform_action, :benchmark
12 alias_method_chain
:render, :benchmark
17 # Log and benchmark the workings of a single block and silence whatever logging that may have happened inside it
18 # (unless <tt>use_silence</tt> is set to false).
20 # The benchmark is only recorded if the current level of the logger matches the <tt>log_level</tt>, which makes it
21 # easy to include benchmarking statements in production software that will remain inexpensive because the benchmark
22 # will only be conducted if the log level is low enough.
23 def benchmark(title
, log_level
= Logger
::DEBUG, use_silence
= true)
24 if logger
&& logger
.level
== log_level
26 seconds
= Benchmark
.realtime
{ result
= use_silence
? silence
{ yield } : yield }
27 logger
.add(log_level
, "#{title} (#{('%.1f' % (seconds * 1000))}ms)")
34 # Silences the logger for the duration of the block.
36 old_logger_level
, logger
.level
= logger
.level
, Logger
::ERROR if logger
39 logger
.level
= old_logger_level
if logger
44 def render_with_benchmark(options
= nil, extra_options
= {}, &block
)
46 if Object
.const_defined
?("ActiveRecord") && ActiveRecord
::Base.connected
?
47 db_runtime
= ActiveRecord
::Base.connection
.reset_runtime
51 @view_runtime = Benchmark
::realtime { render_output
= render_without_benchmark(options
, extra_options
, &block
) }
53 if Object
.const_defined
?("ActiveRecord") && ActiveRecord
::Base.connected
?
54 @db_rt_before_render = db_runtime
55 @db_rt_after_render = ActiveRecord
::Base.connection
.reset_runtime
56 @view_runtime -= @db_rt_after_render
61 render_without_benchmark(options
, extra_options
, &block
)
66 def perform_action_with_benchmark
68 seconds
= [ Benchmark
::measure{ perform_action_without_benchmark
}.real
, 0.0001 ].max
69 logging_view
= defined?(@view_runtime)
70 logging_active_record
= Object
.const_defined
?("ActiveRecord") && ActiveRecord
::Base.connected
?
72 log_message
= "Completed in #{sprintf("%.0f
", seconds * 1000)}ms"
74 if logging_view
|| logging_active_record
76 log_message
<< view_runtime
if logging_view
78 if logging_active_record
79 log_message
<< ", " if logging_view
80 log_message
<< active_record_runtime
+ ")"
86 log_message
<< " | #{headers["Status
"]}"
87 log_message
<< " [#{complete_request_uri rescue "unknown
"}]"
89 logger
.info(log_message
)
90 response
.headers
["X-Runtime"] = "#{sprintf("%.0f
", seconds * 1000)}ms"
92 perform_action_without_benchmark
97 "View: %.0f" % (@view_runtime * 1000)
100 def active_record_runtime
101 db_runtime
= ActiveRecord
::Base.connection
.reset_runtime
102 db_runtime
+= @db_rt_before_render if @db_rt_before_render
103 db_runtime
+= @db_rt_after_render if @db_rt_after_render
104 "DB: %.0f" % (db_runtime
* 1000)