action_profiler 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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: []
|