aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib
diff options
context:
space:
mode:
authorJoshua Peek <josh@joshpeek.com>2009-09-24 12:13:09 -0500
committerJoshua Peek <josh@joshpeek.com>2009-09-24 12:13:09 -0500
commit9f96708f53b4eee8830554dd8f0a482160ef4c73 (patch)
treec2899c3716b0ae6715cd617d1d6b443f84da205b /actionpack/lib
parentc2f8b4e92f8487b83a7c7bd0f19e535a9122d20e (diff)
downloadrails-9f96708f53b4eee8830554dd8f0a482160ef4c73.tar.gz
rails-9f96708f53b4eee8830554dd8f0a482160ef4c73.tar.bz2
rails-9f96708f53b4eee8830554dd8f0a482160ef4c73.zip
Resurrect AC::Benchmarking [#3140 state:resolved]
Diffstat (limited to 'actionpack/lib')
-rw-r--r--actionpack/lib/action_controller.rb7
-rw-r--r--actionpack/lib/action_controller/base.rb1
-rw-r--r--actionpack/lib/action_controller/metal/benchmarking.rb92
3 files changed, 97 insertions, 3 deletions
diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb
index c0b7234cbf..6702cb47f8 100644
--- a/actionpack/lib/action_controller.rb
+++ b/actionpack/lib/action_controller.rb
@@ -1,10 +1,12 @@
module ActionController
autoload :Base, "action_controller/base"
+ autoload :Benchmarking, "action_controller/metal/benchmarking"
autoload :ConditionalGet, "action_controller/metal/conditional_get"
+ autoload :Helpers, "action_controller/metal/helpers"
autoload :HideActions, "action_controller/metal/hide_actions"
+ autoload :Layouts, "action_controller/metal/layouts"
autoload :Metal, "action_controller/metal"
autoload :Middleware, "action_controller/middleware"
- autoload :Layouts, "action_controller/metal/layouts"
autoload :RackConvenience, "action_controller/metal/rack_convenience"
autoload :Rails2Compatibility, "action_controller/metal/compatibility"
autoload :Redirector, "action_controller/metal/redirector"
@@ -12,10 +14,9 @@ module ActionController
autoload :RenderOptions, "action_controller/metal/render_options"
autoload :Rescue, "action_controller/metal/rescuable"
autoload :Responder, "action_controller/metal/responder"
+ autoload :Session, "action_controller/metal/session"
autoload :Testing, "action_controller/metal/testing"
autoload :UrlFor, "action_controller/metal/url_for"
- autoload :Session, "action_controller/metal/session"
- autoload :Helpers, "action_controller/metal/helpers"
# Ported modules
# require 'action_controller/routing'
diff --git a/actionpack/lib/action_controller/base.rb b/actionpack/lib/action_controller/base.rb
index f5bd0a00a1..5338a70104 100644
--- a/actionpack/lib/action_controller/base.rb
+++ b/actionpack/lib/action_controller/base.rb
@@ -14,6 +14,7 @@ module ActionController
include ActionController::Layouts
include ActionController::ConditionalGet
include ActionController::RackConvenience
+ include ActionController::Benchmarking
# Legacy modules
include SessionManagement
diff --git a/actionpack/lib/action_controller/metal/benchmarking.rb b/actionpack/lib/action_controller/metal/benchmarking.rb
new file mode 100644
index 0000000000..d4cb1e122d
--- /dev/null
+++ b/actionpack/lib/action_controller/metal/benchmarking.rb
@@ -0,0 +1,92 @@
+require 'benchmark'
+
+module ActionController #:nodoc:
+ # The benchmarking module times the performance of actions and reports to the logger. If the Active Record
+ # package has been included, a separate timing section for database calls will be added as well.
+ module Benchmarking #:nodoc:
+ extend ActiveSupport::Concern
+
+ module ClassMethods
+ # Log and benchmark the workings of a single block and silence whatever logging that may have happened inside it
+ # (unless <tt>use_silence</tt> is set to false).
+ #
+ # The benchmark is only recorded if the current level of the logger matches the <tt>log_level</tt>, which makes it
+ # easy to include benchmarking statements in production software that will remain inexpensive because the benchmark
+ # will only be conducted if the log level is low enough.
+ def benchmark(title, log_level = Logger::DEBUG, use_silence = true)
+ if logger && logger.level == log_level
+ result = nil
+ ms = Benchmark.ms { result = use_silence ? silence { yield } : yield }
+ logger.add(log_level, "#{title} (#{('%.1f' % ms)}ms)")
+ result
+ else
+ yield
+ end
+ end
+ end
+
+ protected
+ def render(*args, &block)
+ if logger
+ if Object.const_defined?("ActiveRecord") && ActiveRecord::Base.connected?
+ db_runtime = ActiveRecord::Base.connection.reset_runtime
+ end
+
+ render_output = nil
+ @view_runtime = Benchmark.ms { render_output = super }
+
+ if Object.const_defined?("ActiveRecord") && ActiveRecord::Base.connected?
+ @db_rt_before_render = db_runtime
+ @db_rt_after_render = ActiveRecord::Base.connection.reset_runtime
+ @view_runtime -= @db_rt_after_render
+ end
+
+ render_output
+ else
+ super
+ end
+ end
+
+ private
+ def process_action(*args)
+ if logger
+ ms = [Benchmark.ms { super }, 0.01].max
+ logging_view = defined?(@view_runtime)
+ logging_active_record = Object.const_defined?("ActiveRecord") && ActiveRecord::Base.connected?
+
+ log_message = 'Completed in %.0fms' % ms
+
+ if logging_view || logging_active_record
+ log_message << " ("
+ log_message << view_runtime if logging_view
+
+ if logging_active_record
+ log_message << ", " if logging_view
+ log_message << active_record_runtime + ")"
+ else
+ ")"
+ end
+ end
+
+ log_message << " | #{response.status}"
+ log_message << " [#{complete_request_uri rescue "unknown"}]"
+
+ logger.info(log_message)
+ response.headers["X-Runtime"] = "%.0f" % ms
+ else
+ super
+ end
+ end
+
+ def view_runtime
+ "View: %.0f" % @view_runtime
+ end
+
+ def active_record_runtime
+ db_runtime = ActiveRecord::Base.connection.reset_runtime
+ db_runtime += @db_rt_before_render if @db_rt_before_render
+ db_runtime += @db_rt_after_render if @db_rt_after_render
+ "DB: %.0f" % db_runtime
+ end
+ end
+end