action_profiler 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +32 -0
- data/Manifest.txt +12 -0
- data/README +64 -0
- data/Rakefile +61 -0
- data/bin/action_profiler +6 -0
- data/lib/action_profiler.rb +3 -0
- data/lib/action_profiler/path2class.rb +12 -0
- data/lib/action_profiler/prof_processor.rb +39 -0
- data/lib/action_profiler/profiled_processor.rb +208 -0
- data/lib/action_profiler/profiler_processor.rb +24 -0
- data/lib/action_profiler/test_processor.rb +130 -0
- data/lib/action_profiler/zenprofiler_processor.rb +24 -0
- metadata +51 -0
data/LICENSE
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
Portions copyright 2004 David Heinemeier Hansson.
|
2
|
+
|
3
|
+
All original code copyright 2005 Eric Hodel, The Robot Co-op. All rights
|
4
|
+
reserved.
|
5
|
+
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
7
|
+
modification, are permitted provided that the following conditions
|
8
|
+
are met:
|
9
|
+
|
10
|
+
1. Redistributions of source code must retain the above copyright
|
11
|
+
notice, this list of conditions and the following disclaimer.
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright
|
13
|
+
notice, this list of conditions and the following disclaimer in the
|
14
|
+
documentation and/or other materials provided with the distribution.
|
15
|
+
3. Neither the names of the authors nor the names of their contributors
|
16
|
+
may be used to endorse or promote products derived from this software
|
17
|
+
without specific prior written permission.
|
18
|
+
4. Redistribution in Rails or any sub-projects of Rails is not allowed
|
19
|
+
until Rails runs without warnings with the ``-W2'' flag enabled.
|
20
|
+
|
21
|
+
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
|
22
|
+
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
23
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
24
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
|
25
|
+
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
26
|
+
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
27
|
+
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
28
|
+
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
29
|
+
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
30
|
+
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
31
|
+
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
32
|
+
|
data/Manifest.txt
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
LICENSE
|
2
|
+
Manifest.txt
|
3
|
+
README
|
4
|
+
Rakefile
|
5
|
+
bin/action_profiler
|
6
|
+
lib/action_profiler.rb
|
7
|
+
lib/action_profiler/path2class.rb
|
8
|
+
lib/action_profiler/prof_processor.rb
|
9
|
+
lib/action_profiler/profiled_processor.rb
|
10
|
+
lib/action_profiler/profiler_processor.rb
|
11
|
+
lib/action_profiler/test_processor.rb
|
12
|
+
lib/action_profiler/zenprofiler_processor.rb
|
data/README
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
= Action Profiler
|
2
|
+
|
3
|
+
Full Documentation:
|
4
|
+
|
5
|
+
http://rails-analyzer.rubyforge.org/action_profiler
|
6
|
+
|
7
|
+
Rubyforge Project:
|
8
|
+
|
9
|
+
http://rubyforge.org/projects/rails-analyzer
|
10
|
+
|
11
|
+
== About
|
12
|
+
|
13
|
+
Action Profiler allows you to profile a single Rails action to determine what
|
14
|
+
to optimize. You can use the Production Log Analyzer and action_grep to
|
15
|
+
determine which actions you should profile and what arguments to use.
|
16
|
+
|
17
|
+
Information on the Production Log Analyzer can be found at:
|
18
|
+
|
19
|
+
http://rails-analyzer.rubyforge.org/pl_analyze
|
20
|
+
|
21
|
+
=== Profilers
|
22
|
+
|
23
|
+
action_profiler can use three profilers, Ruby's builtin profiler class,
|
24
|
+
Shugo Maeda's Prof or Ryan Davis' ZenProfile. For the last two profilers you
|
25
|
+
will need Ruby 1.8.3 or better.
|
26
|
+
|
27
|
+
=== Running Action Profiler
|
28
|
+
|
29
|
+
Typically, action_profiler will be run from the root of your Rails
|
30
|
+
application:
|
31
|
+
|
32
|
+
$ action_profiler GamesController#index
|
33
|
+
Warmup...
|
34
|
+
Profiling...
|
35
|
+
[ profile output ]
|
36
|
+
$
|
37
|
+
|
38
|
+
If you need to run action_profiler from some other path, the -p command line
|
39
|
+
option can be used to specify the location of your Rails application.
|
40
|
+
|
41
|
+
action_profiler -p ~/Worx/X/CCR GamesController#index
|
42
|
+
|
43
|
+
Paramaters can be specified after the controller and action:
|
44
|
+
|
45
|
+
action_profiler GamesController#index ":id => 1"
|
46
|
+
|
47
|
+
If you need to make sure a page is working correctly you can specify -o and no
|
48
|
+
profiling will occur and the generated page will be printed out instead:
|
49
|
+
|
50
|
+
$ action_profiler -o GamesController#show ":id => 1"
|
51
|
+
<html>
|
52
|
+
[ lots of HTML output ]
|
53
|
+
$
|
54
|
+
|
55
|
+
== Gem Installation
|
56
|
+
|
57
|
+
gem install action_profiler
|
58
|
+
|
59
|
+
== Download
|
60
|
+
|
61
|
+
http://rubyforge.org/frs/?group_id=586
|
62
|
+
|
63
|
+
(Sorry, no manual installation script is available for the .tgz)
|
64
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/testtask'
|
4
|
+
require 'rake/rdoctask'
|
5
|
+
require 'rake/gempackagetask'
|
6
|
+
require 'rake/contrib/sshpublisher'
|
7
|
+
|
8
|
+
$VERBOSE = nil
|
9
|
+
|
10
|
+
spec = Gem::Specification.new do |s|
|
11
|
+
s.name = 'action_profiler'
|
12
|
+
s.version = '1.0.0'
|
13
|
+
s.summary = 'A profiler for Rails controllers'
|
14
|
+
s.author = 'Eric Hodel'
|
15
|
+
s.email = 'eric@robotcoop.com'
|
16
|
+
|
17
|
+
s.has_rdoc = true
|
18
|
+
s.files = File.read('Manifest.txt').split($/)
|
19
|
+
s.require_path = 'lib'
|
20
|
+
s.executables = ['action_profiler']
|
21
|
+
s.default_executable = 'action_profiler'
|
22
|
+
end
|
23
|
+
|
24
|
+
desc 'Run tests'
|
25
|
+
task :default => [ :test ]
|
26
|
+
|
27
|
+
Rake::TestTask.new('test') do |t|
|
28
|
+
t.libs << 'test'
|
29
|
+
t.pattern = 'test/test_*.rb'
|
30
|
+
t.verbose = true
|
31
|
+
end
|
32
|
+
|
33
|
+
desc 'Generate RDoc'
|
34
|
+
Rake::RDocTask.new :rdoc do |rd|
|
35
|
+
rd.rdoc_dir = 'doc'
|
36
|
+
rd.rdoc_files.add 'lib', 'README', 'LICENSE'
|
37
|
+
rd.main = 'README'
|
38
|
+
rd.options << '-d' if `which dot` =~ /\/dot/
|
39
|
+
end
|
40
|
+
|
41
|
+
desc 'Build Gem'
|
42
|
+
Rake::GemPackageTask.new spec do |pkg|
|
43
|
+
pkg.need_tar = true
|
44
|
+
end
|
45
|
+
|
46
|
+
desc 'Sends RDoc to RubyForge'
|
47
|
+
task :send_rdoc => [ :rerdoc ] do
|
48
|
+
publisher = Rake::SshDirPublisher.new('drbrain@rubyforge.org',
|
49
|
+
'/var/www/gforge-projects/rails-analyzer/action_profiler',
|
50
|
+
'doc')
|
51
|
+
publisher.upload
|
52
|
+
end
|
53
|
+
|
54
|
+
desc 'Clean up'
|
55
|
+
task :clean => [ :clobber_rdoc, :clobber_package ]
|
56
|
+
|
57
|
+
desc 'Clean up'
|
58
|
+
task :clobber => [ :clean ]
|
59
|
+
|
60
|
+
# vim: syntax=Ruby
|
61
|
+
|
data/bin/action_profiler
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'prof'
|
2
|
+
require 'rubyprof_ext' # From Rails
|
3
|
+
|
4
|
+
Prof.clock_mode = Prof::GETTIMEOFDAY
|
5
|
+
|
6
|
+
##
|
7
|
+
# A ProfiledProcessor that uses Shugo Maeda's Prof profiler.
|
8
|
+
#
|
9
|
+
# The Prof profiler requires Ruby 1.8.3 or better and can be found at
|
10
|
+
# http://shugo.net/archive/ruby-prof/
|
11
|
+
#
|
12
|
+
# The Prof profiler is configured to use gettimeofday(2). There is no way to
|
13
|
+
# change this setting.
|
14
|
+
|
15
|
+
class ProfProcessor < ProfiledProcessor
|
16
|
+
|
17
|
+
def initialize(*args) # :nodoc:
|
18
|
+
super
|
19
|
+
@profile_data = nil
|
20
|
+
end
|
21
|
+
|
22
|
+
def start_profile # :nodoc:
|
23
|
+
Prof.start
|
24
|
+
end
|
25
|
+
|
26
|
+
##
|
27
|
+
# Prof returns profile data on Prof.stop, so save it for printing.
|
28
|
+
|
29
|
+
def stop_profile # :nodoc:
|
30
|
+
@profile_data = Prof.stop
|
31
|
+
end
|
32
|
+
|
33
|
+
def print_profile(io = STDERR) # :nodoc:
|
34
|
+
return unless @profile_data
|
35
|
+
Prof.print_profile @profile_data, io
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
@@ -0,0 +1,208 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
require 'action_profiler/test_processor'
|
4
|
+
|
5
|
+
def debug(msg)
|
6
|
+
STDERR.puts msg if $AP_DEBUG
|
7
|
+
end
|
8
|
+
|
9
|
+
##
|
10
|
+
# A Rails action processor that profiles an entire action.
|
11
|
+
#
|
12
|
+
# ProfiledProcessor is an abstract class. A subclasses must implement
|
13
|
+
# #start_profile, #stop_profile and #print_profile.
|
14
|
+
|
15
|
+
class ProfiledProcessor < TestProcessor
|
16
|
+
|
17
|
+
PROFILERS = ['ZenProfiler', 'Prof', 'Profiler']
|
18
|
+
|
19
|
+
##
|
20
|
+
# Processes +args+ then runs a profile based on the arguments given.
|
21
|
+
|
22
|
+
def self.process_args(args = ARGV)
|
23
|
+
app_path = Dir.pwd
|
24
|
+
method = 'GET'
|
25
|
+
only_html = false
|
26
|
+
processor_klass = nil
|
27
|
+
times = 1
|
28
|
+
|
29
|
+
opts = OptionParser.new do |opts|
|
30
|
+
opts.banner = "Usage: #{File.basename $0} [options] method [params [session [flash]]]"
|
31
|
+
|
32
|
+
opts.separator ''
|
33
|
+
opts.separator 'method: controller and action to run "GamesController#index"'
|
34
|
+
opts.separator 'params, session, flash: Hash-style arguments ":id => 5"'
|
35
|
+
opts.separator ''
|
36
|
+
|
37
|
+
opts.on("-m", "--method=HTTP_METHOD",
|
38
|
+
"HTTP request method for this action",
|
39
|
+
"Default: #{method}") do |val|
|
40
|
+
method = val
|
41
|
+
end
|
42
|
+
|
43
|
+
opts.on("-o", "--[no-]only-html",
|
44
|
+
"Only output rendered page",
|
45
|
+
"Default: #{only_html}") do |val|
|
46
|
+
only_html = val
|
47
|
+
end
|
48
|
+
|
49
|
+
opts.on("-p", "--app-path=PATH",
|
50
|
+
"Path to Rails application root",
|
51
|
+
"Default: current directory") do |val|
|
52
|
+
unless File.directory? val then
|
53
|
+
raise OptionParser::InvalidArgument, "bad path: #{val}"
|
54
|
+
end
|
55
|
+
|
56
|
+
app_path = val
|
57
|
+
end
|
58
|
+
|
59
|
+
opts.on("-P", "--profiler=PROFILER",
|
60
|
+
"Profiler to use",
|
61
|
+
"Default: ZenProfiler, Prof then Profiler") do |val|
|
62
|
+
begin
|
63
|
+
processor_klass = load_processor val
|
64
|
+
rescue LoadError
|
65
|
+
raise OptionParser::InvalidArgument, "can't load #{val}_processor"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
opts.on("-t", "--times=TIMES", Integer,
|
70
|
+
"Times to run the action under the profiler",
|
71
|
+
"Default: #{times}") do |val|
|
72
|
+
times = val
|
73
|
+
end
|
74
|
+
|
75
|
+
opts.separator ''
|
76
|
+
opts.on("-h", "--help", "Display this help") { STDERR.puts opts; exit 1 }
|
77
|
+
opts.on("-d", "--debug", "Enable debugging output") do |val|
|
78
|
+
$AP_DEBUG = val
|
79
|
+
end
|
80
|
+
opts.separator ''
|
81
|
+
|
82
|
+
opts.parse! args
|
83
|
+
end
|
84
|
+
|
85
|
+
processor_klass = load_default_processor if processor_klass.nil?
|
86
|
+
|
87
|
+
begin
|
88
|
+
Dir.chdir app_path
|
89
|
+
require 'config/environment'
|
90
|
+
require 'application' # HACK Rails can't find this by itself
|
91
|
+
rescue LoadError => e
|
92
|
+
debug "Application load error \"#{e.message}\""
|
93
|
+
raise OptionParser::InvalidArgument, "could not load application, check your path"
|
94
|
+
end
|
95
|
+
|
96
|
+
raise OptionParser::ParseError, "action not specified" if args.empty?
|
97
|
+
action = args.shift
|
98
|
+
|
99
|
+
raise OptionParser::ParseError, "too many arguments" if args.length > 3
|
100
|
+
|
101
|
+
begin
|
102
|
+
params, session, flash = args.map { |arg| eval "{#{arg}}" }
|
103
|
+
rescue Exception
|
104
|
+
raise OptionParser::ParseError, "invalid param/session/flash argument"
|
105
|
+
end
|
106
|
+
|
107
|
+
params ||= {}
|
108
|
+
session ||= {}
|
109
|
+
flash ||= {}
|
110
|
+
|
111
|
+
debug "Using #{processor_klass.inspect} processor"
|
112
|
+
|
113
|
+
pp = processor_klass.new action, method, params, session, flash, only_html
|
114
|
+
pp.profile times
|
115
|
+
|
116
|
+
rescue ArgumentError, OptionParser::ParseError => e
|
117
|
+
STDERR.puts e.message
|
118
|
+
debug "\t#{$!.backtrace.join("\n\t")}"
|
119
|
+
STDERR.puts
|
120
|
+
STDERR.puts opts.to_s
|
121
|
+
exit 1
|
122
|
+
end
|
123
|
+
|
124
|
+
##
|
125
|
+
# Attempts to load the default profilers in order. Returns the first
|
126
|
+
# successfully found profiler class.
|
127
|
+
|
128
|
+
def self.load_default_processor
|
129
|
+
PROFILERS.each do |profiler|
|
130
|
+
begin
|
131
|
+
return load_processor(profiler)
|
132
|
+
rescue LoadError => e
|
133
|
+
end
|
134
|
+
end
|
135
|
+
raise "couldn't load any profilers, how strange, sorry about that"
|
136
|
+
end
|
137
|
+
|
138
|
+
##
|
139
|
+
# Attempts to load a processor starting with +name+. Returns the loaded
|
140
|
+
# class if successful.
|
141
|
+
|
142
|
+
def self.load_processor(name)
|
143
|
+
debug "Loading #{name}Processor"
|
144
|
+
# HACK I have no fucking clue how or why Rails' require mucks shit up,
|
145
|
+
# nor can I reproduce it in a small testcase.
|
146
|
+
require__ "action_profiler/#{name.downcase}_processor"
|
147
|
+
return Object.path2class("#{name}Processor")
|
148
|
+
rescue LoadError => e
|
149
|
+
debug "Failed to load #{name}Processor: #{e.message}"
|
150
|
+
raise
|
151
|
+
end
|
152
|
+
|
153
|
+
##
|
154
|
+
# If +only_html+ is true then only the rendered page will be displayed and
|
155
|
+
# no profiling will be performed. See TestProcessor#new for the rest.
|
156
|
+
|
157
|
+
def initialize(action, method, params, session, flash, only_html)
|
158
|
+
super action, method, params, session, flash
|
159
|
+
@only_html = only_html
|
160
|
+
end
|
161
|
+
|
162
|
+
##
|
163
|
+
# Profiles the action, running it under the profiler +times+ times after
|
164
|
+
# three warmup actions.
|
165
|
+
|
166
|
+
def profile(times = 1)
|
167
|
+
if @only_html then
|
168
|
+
process
|
169
|
+
puts @response.body
|
170
|
+
return
|
171
|
+
end
|
172
|
+
|
173
|
+
STDERR.puts "Warmup..."
|
174
|
+
3.times { process }
|
175
|
+
|
176
|
+
begin
|
177
|
+
STDERR.puts "Profiling..."
|
178
|
+
start_profile
|
179
|
+
times.times { process }
|
180
|
+
stop_profile
|
181
|
+
ensure
|
182
|
+
print_profile
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
##
|
187
|
+
# Implemented by a subclass to start the profiler it uses.
|
188
|
+
|
189
|
+
def start_profile
|
190
|
+
raise NotImplementedError
|
191
|
+
end
|
192
|
+
|
193
|
+
##
|
194
|
+
# Implemented by a subclass to stop the profiler it uses.
|
195
|
+
|
196
|
+
def stop_profile
|
197
|
+
raise NotImplementedError
|
198
|
+
end
|
199
|
+
|
200
|
+
##
|
201
|
+
# Implemented by a subclass to print out the profile data to +io+.
|
202
|
+
|
203
|
+
def print_profile(io)
|
204
|
+
raise NotImplementedError
|
205
|
+
end
|
206
|
+
|
207
|
+
end
|
208
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'profiler'
|
2
|
+
|
3
|
+
##
|
4
|
+
# A ProfiledProcessor that uses Ruby's built-in Profiler__ class.
|
5
|
+
#
|
6
|
+
# ProfilerProcessor is very slow. You really want to upgrade to Ruby 1.8.3 or
|
7
|
+
# better and use ZenProfilerProcessor or ProfProcessor.
|
8
|
+
|
9
|
+
class ProfilerProcessor < ProfiledProcessor
|
10
|
+
|
11
|
+
def start_profile # :nodoc:
|
12
|
+
Profiler__.start_profile
|
13
|
+
end
|
14
|
+
|
15
|
+
def stop_profile # :nodoc:
|
16
|
+
Profiler__.stop_profile
|
17
|
+
end
|
18
|
+
|
19
|
+
def print_profile(io = STDERR) # :nodoc:
|
20
|
+
Profiler__.print_profile io
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'action_controller'
|
3
|
+
|
4
|
+
require 'action_profiler/path2class'
|
5
|
+
|
6
|
+
# :stopdoc:
|
7
|
+
|
8
|
+
# This exists because Rails coupled test processing to unit testing.
|
9
|
+
|
10
|
+
# Don't load assertions or deprecated assertions by faking entries in $".
|
11
|
+
gs = Gem::GemPathSearcher.new
|
12
|
+
path = gs.find('action_controller/test_process').full_gem_path
|
13
|
+
$" << File.join(path, 'lib', 'action_controller', 'assertions.rb')
|
14
|
+
$" << File.join(path, 'lib', 'action_controller', 'deprecated_assertions.rb')
|
15
|
+
|
16
|
+
# This lameness exists because Rails injects into Test::Unit::TestCase when
|
17
|
+
# it should use subclasses.
|
18
|
+
|
19
|
+
module Test; end
|
20
|
+
module Test::Unit; end
|
21
|
+
class Test::Unit::TestCase; end
|
22
|
+
|
23
|
+
# :startdoc:
|
24
|
+
|
25
|
+
require 'action_controller/test_process'
|
26
|
+
|
27
|
+
##
|
28
|
+
# TestProcessor is a class that exercises a Rails controller action.
|
29
|
+
#
|
30
|
+
# TestProcessor is heavily based on ActionPack's
|
31
|
+
# lib/action_controller/test_process.rb
|
32
|
+
#
|
33
|
+
# The original can be found at: http://dev.rubyonrails.org/browser/trunk/actionpack/lib/action_controller/test_process.rb
|
34
|
+
#
|
35
|
+
# The methods #process and #build_request_uri are copyright (c) 2004 David
|
36
|
+
# Heinemeier Hansson and are used under the MIT License. All original code is
|
37
|
+
# subject to the LICENSE file included with Action Profiler.
|
38
|
+
#--
|
39
|
+
# Per the MIT license:
|
40
|
+
#
|
41
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
42
|
+
# a copy of this software and associated documentation files (the
|
43
|
+
# "Software"), to deal in the Software without restriction, including
|
44
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
45
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
46
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
47
|
+
# the following conditions:
|
48
|
+
#
|
49
|
+
# The above copyright notice and this permission notice shall be
|
50
|
+
# included in all copies or substantial portions of the Software.
|
51
|
+
#
|
52
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
53
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
54
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
55
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
56
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
57
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
58
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
59
|
+
|
60
|
+
class TestProcessor
|
61
|
+
|
62
|
+
##
|
63
|
+
# Creates a new TestProcessor that will profile +action+ with +method+.
|
64
|
+
# +params+, +session+ and +flash+ are hashes for use in processing the
|
65
|
+
# request.
|
66
|
+
#
|
67
|
+
# +action+ is a String with the format "GamesController#index".
|
68
|
+
#
|
69
|
+
# +method+ is one of the HTTP request methods, get, post, etc.
|
70
|
+
|
71
|
+
def initialize(action, method, params = nil, session = nil, flash = nil)
|
72
|
+
unless action =~ /^([:\w]+Controller)#(\w+)$/ then
|
73
|
+
raise ArgumentError, "invalid action name"
|
74
|
+
end
|
75
|
+
|
76
|
+
@controller_name = $1
|
77
|
+
@action_name = $2
|
78
|
+
@method = method.downcase
|
79
|
+
|
80
|
+
@params = params
|
81
|
+
@session = session
|
82
|
+
@flash = flash
|
83
|
+
|
84
|
+
begin
|
85
|
+
controller_klass = Object.path2class @controller_name
|
86
|
+
rescue NameError
|
87
|
+
raise ArgumentError, "can't find controller #{@controller_name}"
|
88
|
+
end
|
89
|
+
|
90
|
+
@controller = controller_klass.new
|
91
|
+
@request = ActionController::TestRequest.new
|
92
|
+
@response = ActionController::TestResponse.new
|
93
|
+
ActionMailer::Base.delivery_method = :test
|
94
|
+
ActionMailer::Base.deliveries = []
|
95
|
+
end
|
96
|
+
|
97
|
+
##
|
98
|
+
# Runs this action.
|
99
|
+
|
100
|
+
def process
|
101
|
+
@request.recycle!
|
102
|
+
|
103
|
+
@html_document = nil # Why? Who knows!
|
104
|
+
@request.env['REQUEST_METHOD'] = @method
|
105
|
+
@request.action = @action_name
|
106
|
+
|
107
|
+
@request.assign_parameters(@controller.class.controller_path, @action_name,
|
108
|
+
@params)
|
109
|
+
|
110
|
+
@request.session = ActionController::TestSession.new @session
|
111
|
+
@request.session['flash'] = ActionController::Flash::FlashHash.new
|
112
|
+
@request.session['flash'].update @flash
|
113
|
+
|
114
|
+
build_request_uri
|
115
|
+
@controller.process @request, @response
|
116
|
+
end
|
117
|
+
|
118
|
+
private
|
119
|
+
|
120
|
+
def build_request_uri
|
121
|
+
return if @request.env['REQUEST_URI']
|
122
|
+
options = @controller.send :rewrite_options, @params
|
123
|
+
options.update :only_path => true, :action => @action_name
|
124
|
+
|
125
|
+
url = ActionController::UrlRewriter.new @request, @params
|
126
|
+
@request.set_REQUEST_URI url.rewrite(options)
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'zenprofile'
|
2
|
+
|
3
|
+
##
|
4
|
+
# A ProfiledProcessor that uses Ryan Davis' ZenProfiler.
|
5
|
+
#
|
6
|
+
# The ZenProfiler profiler requires Ruby 1.8.3 or better and RubyInline.
|
7
|
+
# ZenProfiler can be found at http://rubyforge.org/frs/?group_id=712
|
8
|
+
|
9
|
+
class ZenProfilerProcessor < ProfiledProcessor
|
10
|
+
|
11
|
+
def start_profile # :nodoc:
|
12
|
+
ZenProfiler.start
|
13
|
+
end
|
14
|
+
|
15
|
+
def stop_profile # :nodoc:
|
16
|
+
ZenProfiler.stop
|
17
|
+
end
|
18
|
+
|
19
|
+
def print_profile(io = STDERR) # :nodoc:
|
20
|
+
ZenProfiler.print_profile io
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
metadata
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.8.11
|
3
|
+
specification_version: 1
|
4
|
+
name: action_profiler
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 1.0.0
|
7
|
+
date: 2005-11-15 00:00:00 -08:00
|
8
|
+
summary: A profiler for Rails controllers
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: eric@robotcoop.com
|
12
|
+
homepage:
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire:
|
16
|
+
default_executable: action_profiler
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
-
|
22
|
+
- ">"
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: 0.0.0
|
25
|
+
version:
|
26
|
+
platform: ruby
|
27
|
+
signing_key:
|
28
|
+
cert_chain:
|
29
|
+
authors:
|
30
|
+
- Eric Hodel
|
31
|
+
files:
|
32
|
+
- LICENSE
|
33
|
+
- Manifest.txt
|
34
|
+
- README
|
35
|
+
- Rakefile
|
36
|
+
- bin/action_profiler
|
37
|
+
- lib/action_profiler.rb
|
38
|
+
- lib/action_profiler/path2class.rb
|
39
|
+
- lib/action_profiler/prof_processor.rb
|
40
|
+
- lib/action_profiler/profiled_processor.rb
|
41
|
+
- lib/action_profiler/profiler_processor.rb
|
42
|
+
- lib/action_profiler/test_processor.rb
|
43
|
+
- lib/action_profiler/zenprofiler_processor.rb
|
44
|
+
test_files: []
|
45
|
+
rdoc_options: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
executables:
|
48
|
+
- action_profiler
|
49
|
+
extensions: []
|
50
|
+
requirements: []
|
51
|
+
dependencies: []
|