fiveruns_tuneup 0.8.2
Sign up to get free protection for your applications and to get access to all the features.
- data/History.rdoc +3 -0
- data/Manifest +57 -0
- data/README.rdoc +44 -0
- data/Rakefile +15 -0
- data/assets/images/arrows.gif +0 -0
- data/assets/images/edit.png +0 -0
- data/assets/images/fade.png +0 -0
- data/assets/images/fade_down.png +0 -0
- data/assets/images/head.gif +0 -0
- data/assets/images/logo.gif +0 -0
- data/assets/images/logo_clear.png +0 -0
- data/assets/images/magnify.png +0 -0
- data/assets/images/pip.gif +0 -0
- data/assets/images/pointer.gif +0 -0
- data/assets/images/schema.png +0 -0
- data/assets/images/signin.gif +0 -0
- data/assets/images/spinner.gif +0 -0
- data/assets/images/warning.gif +0 -0
- data/assets/javascripts/prototype.js +2515 -0
- data/assets/javascripts/tuneup.js +30 -0
- data/assets/stylesheets/tuneup.css +204 -0
- data/bin/fiveruns_tuneup +26 -0
- data/fiveruns_tuneup.gemspec +49 -0
- data/init.rb +2 -0
- data/install.rb +18 -0
- data/lib/bumpspark_helper.rb +52 -0
- data/lib/fiveruns/tuneup.rb +103 -0
- data/lib/fiveruns/tuneup/asset_tags.rb +39 -0
- data/lib/fiveruns/tuneup/custom_methods.rb +8 -0
- data/lib/fiveruns/tuneup/environment.rb +29 -0
- data/lib/fiveruns/tuneup/instrumentation/action_controller/base.rb +59 -0
- data/lib/fiveruns/tuneup/instrumentation/action_view/base.rb +77 -0
- data/lib/fiveruns/tuneup/instrumentation/active_record/base.rb +126 -0
- data/lib/fiveruns/tuneup/instrumentation/cgi/session.rb +30 -0
- data/lib/fiveruns/tuneup/instrumentation/utilities.rb +172 -0
- data/lib/fiveruns/tuneup/multipart.rb +75 -0
- data/lib/fiveruns/tuneup/runs.rb +86 -0
- data/lib/fiveruns/tuneup/schema.rb +43 -0
- data/lib/fiveruns/tuneup/step.rb +219 -0
- data/lib/fiveruns/tuneup/urls.rb +23 -0
- data/lib/fiveruns/tuneup/version.rb +80 -0
- data/lib/fiveruns_tuneup.rb +1 -0
- data/lib/tuneup_config.rb +29 -0
- data/lib/tuneup_controller.rb +140 -0
- data/lib/tuneup_helper.rb +185 -0
- data/rails/init.rb +20 -0
- data/tasks/assets.rake +32 -0
- data/test/test_helper.rb +3 -0
- data/test/tuneup_test.rb +0 -0
- data/uninstall.rb +6 -0
- data/views/tuneup/_data.html.erb +15 -0
- data/views/tuneup/_flash.html.erb +6 -0
- data/views/tuneup/_link.html.erb +1 -0
- data/views/tuneup/_schema.html.erb +17 -0
- data/views/tuneup/_sql.html.erb +23 -0
- data/views/tuneup/_step.html.erb +15 -0
- data/views/tuneup/panel/_registered.html.erb +4 -0
- data/views/tuneup/panel/_unregistered.html.erb +14 -0
- metadata +146 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
module Fiveruns
|
2
|
+
module Tuneup
|
3
|
+
|
4
|
+
module AssetTags
|
5
|
+
|
6
|
+
def add_asset_tags_to(response)
|
7
|
+
return unless show_for?(response)
|
8
|
+
before, after = response.body.split(/<\/head>/i, 2)
|
9
|
+
if after
|
10
|
+
insertion = %(
|
11
|
+
<!-- START FIVERUNS TUNEUP ASSETS -->
|
12
|
+
<link rel='stylesheet' type='text/css' href='/stylesheets/tuneup/tuneup.css'/>
|
13
|
+
#{insert_prototype unless response.body.include?('prototype.js')}
|
14
|
+
<script type='text/javascript'>
|
15
|
+
var TuneUp = {};
|
16
|
+
TuneUp.frontend_url = "#{Fiveruns::Tuneup.frontend_url}";
|
17
|
+
</script>
|
18
|
+
<script type='text/javascript' src='/javascripts/tuneup/tuneup.js'></script>
|
19
|
+
<!-- END FIVERUNS TUNEUP ASSETS -->
|
20
|
+
)
|
21
|
+
response.headers["Content-Length"] += insertion.size
|
22
|
+
response.body.replace(before << insertion << '</head>' << after)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def show_for?(response)
|
27
|
+
return false unless response.body
|
28
|
+
return false unless response.headers['Status'] && response.headers['Status'].include?('200')
|
29
|
+
true
|
30
|
+
end
|
31
|
+
|
32
|
+
def insert_prototype
|
33
|
+
"<script type='text/javascript' src='/javascripts/tuneup/prototype.js'></script>"
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Fiveruns
|
2
|
+
module Tuneup
|
3
|
+
module Environment
|
4
|
+
|
5
|
+
def environment
|
6
|
+
{
|
7
|
+
'application_name' => application_name,
|
8
|
+
'rails_env' => rails_env,
|
9
|
+
'rails_version' => rails_version
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
def rails_env
|
14
|
+
RAILS_ENV || 'development'
|
15
|
+
end
|
16
|
+
|
17
|
+
def rails_version
|
18
|
+
::Rails::VERSION::STRING rescue 'unknown Rails version'
|
19
|
+
end
|
20
|
+
|
21
|
+
def application_name
|
22
|
+
app_name = RAILS_ROOT.split('/').last
|
23
|
+
return app_name unless app_name == 'current'
|
24
|
+
File.join(RAILS_ROOT, '..').split('/').last
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Fiveruns
|
2
|
+
module Tuneup
|
3
|
+
module Instrumentation
|
4
|
+
module ActionController
|
5
|
+
module Base
|
6
|
+
def self.included(base)
|
7
|
+
Fiveruns::Tuneup.instrument base, ClassMethods, InstanceMethods
|
8
|
+
end
|
9
|
+
module ClassMethods
|
10
|
+
def cache_page_with_fiveruns_tuneup(*args, &block)
|
11
|
+
Fiveruns::Tuneup.step "Cache page", :controller do
|
12
|
+
cache_page_without_fiveruns_tuneup(*args, &block)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
def expire_page_with_fiveruns_tuneup(*args, &block)
|
16
|
+
Fiveruns::Tuneup.step "Expire cached page", :controller do
|
17
|
+
expire_page_without_fiveruns_tuneup(*args, &block)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
module InstanceMethods
|
22
|
+
def perform_action_with_fiveruns_tuneup(*args, &block)
|
23
|
+
Fiveruns::Tuneup.run(self, request) do
|
24
|
+
action = (request.parameters['action'] || 'index').to_s
|
25
|
+
if Fiveruns::Tuneup.recording?
|
26
|
+
Fiveruns::Tuneup.instrument_filters(self)
|
27
|
+
Fiveruns::Tuneup.instrument_action_methods(self)
|
28
|
+
Fiveruns::Tuneup.instrument_custom_methods
|
29
|
+
end
|
30
|
+
result = Fiveruns::Tuneup.step "Perform #{action.capitalize} action in #{self.class.name}", :controller, false do
|
31
|
+
perform_action_without_fiveruns_tuneup(*args, &block)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
def process_with_fiveruns_tuneup(request, response, *args, &block)
|
36
|
+
result = process_without_fiveruns_tuneup(request, response, *args, &block)
|
37
|
+
if !request.xhr? && response.content_type == 'text/html'
|
38
|
+
Fiveruns::Tuneup.add_asset_tags_to(response)
|
39
|
+
end
|
40
|
+
result
|
41
|
+
end
|
42
|
+
|
43
|
+
def write_fragment_with_fiveruns_tuneup(*args, &block)
|
44
|
+
Fiveruns::Tuneup.step "Cache fragment", :controller do
|
45
|
+
write_fragment_without_fiveruns_tuneup(*args, &block)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
def expire_fragment_with_fiveruns_tuneup(*args, &block)
|
49
|
+
Fiveruns::Tuneup.step "Expire fragment cache", :controller do
|
50
|
+
expire_fragment_without_fiveruns_tuneup(*args, &block)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module Fiveruns
|
2
|
+
module Tuneup
|
3
|
+
module Instrumentation
|
4
|
+
module ActionView
|
5
|
+
module Base
|
6
|
+
|
7
|
+
BASIC_TEMPLATE_PATH = File.join(RAILS_ROOT, 'app', 'views')
|
8
|
+
|
9
|
+
def self.included(base)
|
10
|
+
Fiveruns::Tuneup.instrument base, InstanceMethods
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.normalize_path(path)
|
14
|
+
return path unless path
|
15
|
+
if path[0, BASIC_TEMPLATE_PATH.size] == BASIC_TEMPLATE_PATH
|
16
|
+
path[(BASIC_TEMPLATE_PATH.size + 1)..-1]
|
17
|
+
else
|
18
|
+
if (components = path.split(File::SEPARATOR)).size > 2
|
19
|
+
components[-2, 2].join(File::SEPARATOR)
|
20
|
+
else
|
21
|
+
components.join(File::SEPARATOR)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
module InstanceMethods
|
27
|
+
def render_file_with_fiveruns_tuneup(path, *args, &block)
|
28
|
+
name = Fiveruns::Tuneup::Instrumentation::ActionView::Base.normalize_path(path)
|
29
|
+
Fiveruns::Tuneup.step "Render file #{name}", :view do
|
30
|
+
render_file_without_fiveruns_tuneup(path, *args, &block)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
def update_page_with_fiveruns_tuneup(*args, &block)
|
34
|
+
path = block.to_s.split('/').last.split(':').first rescue ''
|
35
|
+
name = Fiveruns::Tuneup::Instrumentation::ActionView::Base.normalize_path(path)
|
36
|
+
Fiveruns::Tuneup.step "Render page update #{name}", :view do
|
37
|
+
update_page_without_fiveruns_tuneup(*args, &block)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
def render_with_fiveruns_tuneup(*args, &block)
|
41
|
+
record = true
|
42
|
+
options = args.first || {}
|
43
|
+
path = case options
|
44
|
+
when String
|
45
|
+
"Render #{options}"
|
46
|
+
when :update
|
47
|
+
name = block.to_s.split('/').last.split(':').first rescue ''
|
48
|
+
"Render page update #{name}"
|
49
|
+
when Hash
|
50
|
+
if options[:file]
|
51
|
+
"Render #{options[:file]}"
|
52
|
+
elsif options[:partial]
|
53
|
+
# Don't record this as it causes duplicate records
|
54
|
+
record = false
|
55
|
+
elsif options[:inline]
|
56
|
+
"Render inline"
|
57
|
+
elsif options[:text]
|
58
|
+
"Render text"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
path ||= 'Render'
|
62
|
+
|
63
|
+
if record
|
64
|
+
Fiveruns::Tuneup.step path, :view do
|
65
|
+
render_without_fiveruns_tuneup(*args, &block)
|
66
|
+
end
|
67
|
+
else
|
68
|
+
render_without_fiveruns_tuneup(*args, &block)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module Fiveruns
|
2
|
+
module Tuneup
|
3
|
+
module Instrumentation
|
4
|
+
module ActiveRecord
|
5
|
+
module Base
|
6
|
+
|
7
|
+
def self.record(model, name, raw_sql=nil, &operation)
|
8
|
+
sql = nil
|
9
|
+
Fiveruns::Tuneup.exclude do
|
10
|
+
model.silence do
|
11
|
+
sql = Fiveruns::Tuneup::Step::SQL.new(raw_sql, model.connection) if raw_sql
|
12
|
+
Fiveruns::Tuneup.add_schema_for(model.table_name, model.connection)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
Fiveruns::Tuneup.step(name, :model, true, sql, model.table_name, &operation)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.included(base)
|
19
|
+
Fiveruns::Tuneup.instrument base, InstanceMethods, ClassMethods
|
20
|
+
end
|
21
|
+
|
22
|
+
module ClassMethods
|
23
|
+
|
24
|
+
#
|
25
|
+
# FINDS
|
26
|
+
#
|
27
|
+
|
28
|
+
def find_with_fiveruns_tuneup(*args, &block)
|
29
|
+
Fiveruns::Tuneup::Instrumentation::ActiveRecord::Base.record self, "Find #{self.name}" do
|
30
|
+
find_without_fiveruns_tuneup(*args, &block)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
def find_by_sql_with_fiveruns_tuneup(conditions, &block)
|
34
|
+
Fiveruns::Tuneup::Instrumentation::ActiveRecord::Base.record self, "Find #{self.name} by SQL", sanitize_sql(conditions) do
|
35
|
+
find_by_sql_without_fiveruns_tuneup(conditions, &block)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
#
|
40
|
+
# CREATE
|
41
|
+
#
|
42
|
+
|
43
|
+
def create_with_fiveruns_tuneup(*args, &block)
|
44
|
+
Fiveruns::Tuneup::Instrumentation::ActiveRecord::Base.record self, "Create #{self.name}" do
|
45
|
+
create_without_fiveruns_tuneup(*args, &block)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
# UPDATES
|
51
|
+
#
|
52
|
+
|
53
|
+
def update_with_fiveruns_tuneup(*args, &block)
|
54
|
+
Fiveruns::Tuneup::Instrumentation::ActiveRecord::Base.record self, "Update #{self.name}" do
|
55
|
+
update_without_fiveruns_tuneup(*args, &block)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
def update_all_with_fiveruns_tuneup(*args, &block)
|
59
|
+
Fiveruns::Tuneup::Instrumentation::ActiveRecord::Base.record self, "Update #{self.name} (All)" do
|
60
|
+
update_all_without_fiveruns_tuneup(*args, &block)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
#
|
65
|
+
# DELETES
|
66
|
+
#
|
67
|
+
|
68
|
+
def destroy_with_fiveruns_tuneup(*args, &block)
|
69
|
+
Fiveruns::Tuneup::Instrumentation::ActiveRecord::Base.record self, "Destroy #{self.name}" do
|
70
|
+
destroy_without_fiveruns_tuneup(*args, &block)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
def destroy_all_with_fiveruns_tuneup(*args, &block)
|
74
|
+
Fiveruns::Tuneup::Instrumentation::ActiveRecord::Base.record self, "Destroy #{self.name} (All)" do
|
75
|
+
destroy_all_without_fiveruns_tuneup(*args, &block)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
def delete_with_fiveruns_tuneup(*args, &block)
|
79
|
+
Fiveruns::Tuneup::Instrumentation::ActiveRecord::Base.record self, "Delete #{self.name}" do
|
80
|
+
delete_without_fiveruns_tuneup(*args, &block)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
def delete_all_with_fiveruns_tuneup(*args, &block)
|
84
|
+
Fiveruns::Tuneup::Instrumentation::ActiveRecord::Base.record self, "Delete #{self.name} (All)" do
|
85
|
+
delete_all_without_fiveruns_tuneup(*args, &block)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
module InstanceMethods
|
90
|
+
|
91
|
+
#
|
92
|
+
# UPDATES
|
93
|
+
#
|
94
|
+
|
95
|
+
def update_with_fiveruns_tuneup(*args, &block)
|
96
|
+
Fiveruns::Tuneup::Instrumentation::ActiveRecord::Base.record self.class, "Update #{self.class.name}" do
|
97
|
+
update_without_fiveruns_tuneup(*args, &block)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
def save_with_fiveruns_tuneup(*args, &block)
|
101
|
+
Fiveruns::Tuneup::Instrumentation::ActiveRecord::Base.record self.class, "Save #{self.class.name}" do
|
102
|
+
save_without_fiveruns_tuneup(*args, &block)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
def save_with_fiveruns_tuneup!(*args, &block)
|
106
|
+
Fiveruns::Tuneup::Instrumentation::ActiveRecord::Base.record self.class, "Save #{self.class.name}" do
|
107
|
+
save_without_fiveruns_tuneup!(*args, &block)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
#
|
112
|
+
# DELETES
|
113
|
+
#
|
114
|
+
|
115
|
+
def destroy_with_fiveruns_tuneup(*args, &block)
|
116
|
+
Fiveruns::Tuneup::Instrumentation::ActiveRecord::Base.record self.class, "Destroy #{self.class.name}" do
|
117
|
+
destroy_without_fiveruns_tuneup(*args, &block)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Fiveruns
|
2
|
+
module Tuneup
|
3
|
+
module Instrumentation
|
4
|
+
module CGI
|
5
|
+
module Session
|
6
|
+
def self.included(base)
|
7
|
+
Fiveruns::Tuneup.instrument base, InstanceMethods
|
8
|
+
end
|
9
|
+
module InstanceMethods
|
10
|
+
def initialize_with_fiveruns_tuneup(*args, &block)
|
11
|
+
Fiveruns::Tuneup.step "Create session", :model do
|
12
|
+
initialize_without_fiveruns_tuneup(*args, &block)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
def close_with_fiveruns_tuneup(*args, &block)
|
16
|
+
Fiveruns::Tuneup.step "Close session", :model do
|
17
|
+
close_without_fiveruns_tuneup(*args, &block)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
def delete_with_fiveruns_tuneup(*args, &block)
|
21
|
+
Fiveruns::Tuneup.step "Delete session", :model do
|
22
|
+
delete_without_fiveruns_tuneup(*args, &block)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,172 @@
|
|
1
|
+
module Fiveruns
|
2
|
+
module Tuneup
|
3
|
+
module Instrumentation
|
4
|
+
module Utilities
|
5
|
+
|
6
|
+
def stack
|
7
|
+
@stack ||= []
|
8
|
+
end
|
9
|
+
|
10
|
+
def exclusion_stack
|
11
|
+
@exclusion_stack ||= [0]
|
12
|
+
end
|
13
|
+
|
14
|
+
def custom_methods
|
15
|
+
@custom_methods ||= {}
|
16
|
+
end
|
17
|
+
|
18
|
+
def add_custom_methods(target, *methods)
|
19
|
+
custom_methods[target] = [] unless custom_methods.key?(target)
|
20
|
+
custom_methods[target].push(*methods)
|
21
|
+
end
|
22
|
+
|
23
|
+
def stopwatch
|
24
|
+
start = Time.now.to_f
|
25
|
+
yield
|
26
|
+
(Time.now.to_f - start) * 1000
|
27
|
+
end
|
28
|
+
|
29
|
+
def exclude
|
30
|
+
result = nil
|
31
|
+
exclusion_stack[-1] += stopwatch { result = yield }
|
32
|
+
result
|
33
|
+
end
|
34
|
+
|
35
|
+
def step(name, layer=nil, link=true, sql=nil, table_name=nil, &block)
|
36
|
+
if recording?
|
37
|
+
result = nil
|
38
|
+
caller_line = caller.detect { |l| l.include?(RAILS_ROOT) && l !~ /tuneup|vendor\/rails/ } if link
|
39
|
+
file, line = caller_line ? caller_line.split(':')[0, 2] : [nil, nil]
|
40
|
+
line = line.to_i if line
|
41
|
+
returning ::Fiveruns::Tuneup::Step.new(name, layer, file, line, sql, &block) do |step|
|
42
|
+
step.table_name = table_name
|
43
|
+
stack.last << step
|
44
|
+
stack << step
|
45
|
+
handle_exclusions_in step do
|
46
|
+
step.time = stopwatch { result = yield(sql) }
|
47
|
+
end
|
48
|
+
stack.pop
|
49
|
+
end
|
50
|
+
result
|
51
|
+
else
|
52
|
+
yield(sql)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Handle removal of excluded time from total for this step, and
|
57
|
+
# bubble the value up for removal from the parent step
|
58
|
+
def handle_exclusions_in(step)
|
59
|
+
exclusion_stack << 0
|
60
|
+
yield # Must set +step.time+
|
61
|
+
time_to_exclude = exclusion_stack.pop
|
62
|
+
step.time -= time_to_exclude
|
63
|
+
exclusion_stack[-1] += time_to_exclude unless exclusion_stack.blank?
|
64
|
+
end
|
65
|
+
|
66
|
+
def instrument(target, *mods)
|
67
|
+
mods.each do |mod|
|
68
|
+
# Change target for 'ClassMethods' module
|
69
|
+
real_target = mod.name.demodulize == 'ClassMethods' ? (class << target; self; end) : target
|
70
|
+
real_target.__send__(:include, mod)
|
71
|
+
# Find all the instrumentation hooks and chain them in
|
72
|
+
mod.instance_methods.each do |meth|
|
73
|
+
name = meth.to_s.sub('_with_fiveruns_tuneup', '')
|
74
|
+
real_target.alias_method_chain(name, :fiveruns_tuneup) rescue nil
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def instrument_action_methods(controller)
|
80
|
+
klass = controller.class
|
81
|
+
actions_for(klass).each do |meth|
|
82
|
+
format = alias_format_for(meth)
|
83
|
+
next if controller.respond_to?(format % :with, true)
|
84
|
+
wrap(klass, format, meth, "Invoke #{meth} action", :controller)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def instrument_filters(controller)
|
89
|
+
klass = controller.class
|
90
|
+
filters_for(klass).each do |filter|
|
91
|
+
format = alias_format_for(filter.filter)
|
92
|
+
next if controller.respond_to?(format % :with, true)
|
93
|
+
wrap(klass, format, filter.filter, "#{filter.type.to_s.titleize} filter #{filter.filter}", :controller)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def instrument_custom_methods
|
98
|
+
custom_methods.each do |meth_target, meths|
|
99
|
+
lineage = meth_target.ancestors
|
100
|
+
layer = if lineage.include?(ActionController::Base)
|
101
|
+
:controller
|
102
|
+
elsif lineage.include?(ActiveRecord::Base)
|
103
|
+
:model
|
104
|
+
elsif lineage.include?(ActionView::Base)
|
105
|
+
:view
|
106
|
+
else
|
107
|
+
:other
|
108
|
+
end
|
109
|
+
meths.each do |meth|
|
110
|
+
format = alias_format_for(meth)
|
111
|
+
wrap(meth_target, format, meth, "Method #{meth}", layer)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
#######
|
117
|
+
private
|
118
|
+
#######
|
119
|
+
|
120
|
+
def wrap(klass, format, meth, name, layer)
|
121
|
+
text = <<-EOC
|
122
|
+
def #{format % :with}(*args, &block)
|
123
|
+
Fiveruns::Tuneup.step "#{name}", :#{layer} do
|
124
|
+
#{format % :without}(*args, &block)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
alias_method_chain :#{meth}, :fiveruns_tuneup
|
128
|
+
EOC
|
129
|
+
begin
|
130
|
+
klass.class_eval text
|
131
|
+
rescue SyntaxError => e
|
132
|
+
# XXX: Catch-all for reports of oddly-named methods affecting dynamically generated code
|
133
|
+
log :warn, %[Bad syntax wrapping #{klass}##{meth}, "#{name}"]
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def alias_format_for(name)
|
138
|
+
name.to_s =~ /^(.*?)(\?|!|=)$/ ? "#{$1}_%s_fiveruns_tuneup#{$2}" : "#{name}_%s_fiveruns_tuneup"
|
139
|
+
end
|
140
|
+
|
141
|
+
def actions_for(klass)
|
142
|
+
klass.action_methods.reject { |meth| meth.to_s.include?('fiveruns') }
|
143
|
+
end
|
144
|
+
|
145
|
+
def filters_for(klass)
|
146
|
+
klass.filter_chain.select { |f| f.filter.is_a?(Symbol) }
|
147
|
+
end
|
148
|
+
|
149
|
+
def install_instrumentation
|
150
|
+
instrumentation_path = File.dirname(__FILE__)
|
151
|
+
Dir[File.join(instrumentation_path, '/*/**/*.rb')].each do |filename|
|
152
|
+
constant_path = filename[(instrumentation_path.size + 1)..-4]
|
153
|
+
constant_name = path_to_constant_name(constant_path)
|
154
|
+
if (constant = constant_name.constantize rescue nil)
|
155
|
+
instrumentation = "Fiveruns::Tuneup::Instrumentation::#{constant_name}".constantize
|
156
|
+
constant.__send__(:include, instrumentation)
|
157
|
+
else
|
158
|
+
log :debug, "#{constant_name} not found; skipping instrumentation."
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def path_to_constant_name(path)
|
164
|
+
parts = path.split(File::SEPARATOR)
|
165
|
+
parts.map(&:camelize).join('::').sub('Cgi', 'CGI')
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|