ngauthier-slow-actions 0.2.2

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/README.rdoc ADDED
@@ -0,0 +1,14 @@
1
+ = Slow Actions
2
+ Nick Gauthier (nick@smartlogicsolutions.com)
3
+
4
+ == Description
5
+ Reads a rails app's log file for slow actions
6
+
7
+ == Usage
8
+ ./bin/slow-actions.rb path/to/log/file
9
+
10
+ Or:
11
+
12
+ require 'slow_actions'
13
+ sap = SlowActionParser.new(file_path)
14
+ actions = sap.parse
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :minor: 2
3
+ :patch: 2
4
+ :major: 0
data/bin/slow-actions ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'slow_actions')
3
+ @sa = SlowActions.new
4
+ @sa.parse_file(ARGV[0])
5
+ puts @sa.print_actions
6
+ puts ""
7
+ puts @sa.print_controller_tree
8
+ puts ""
9
+ puts @sa.print_sessions
10
+
@@ -0,0 +1,124 @@
1
+ require File.join(File.dirname(__FILE__), 'slow_actions_parser')
2
+ require File.join(File.dirname(__FILE__), 'slow_actions_controller')
3
+ require File.join(File.dirname(__FILE__), 'slow_actions_action')
4
+ require File.join(File.dirname(__FILE__), 'slow_actions_session')
5
+
6
+ class SlowActions
7
+ def initialize
8
+ @log_entries = []
9
+ end
10
+
11
+ def parse_file(file_path)
12
+ parser = Parser.new(file_path)
13
+ @log_entries += parser.parse
14
+ process
15
+ end
16
+
17
+ def log_entries
18
+ return @log_entries
19
+ end
20
+
21
+ def print_actions
22
+ str = ""
23
+ str += " Cost Average Max\n"
24
+ actions.sort{|x,y| y.total_cost <=> x.total_cost}.each do |a|
25
+ str += "==#{a.controller.name}:#{a.name}==\n"
26
+ str += " Total: #{ftos a.total_cost}#{ftos a.total_avg}#{ftos a.total_max}\n"
27
+ str += " Render: #{ftos a.render_cost}#{ftos a.render_avg}#{ftos a.render_max}\n"
28
+ str += " DB: #{ftos a.db_cost}#{ftos a.db_avg}#{ftos a.db_max}\n"
29
+
30
+ end
31
+ return str
32
+ end
33
+
34
+ def print_controller_tree
35
+ str = ""
36
+ str += " Cost Average Max\n"
37
+ controllers.sort{|x,y| y.total_cost <=> x.total_cost}.each do |c|
38
+ str += "==#{c.name}==\n"
39
+ str += " Total: #{ftos c.total_cost}#{ftos c.total_avg}#{ftos c.total_max}\n"
40
+ str += " Render: #{ftos c.render_cost}#{ftos c.render_avg}#{ftos c.render_max}\n"
41
+ str += " DB: #{ftos c.db_cost}#{ftos c.db_avg}#{ftos c.db_max}\n"
42
+ c.actions.sort{|x,y| y.total_cost <=> x.total_cost}.each do |a|
43
+ str += " ==#{a.name}==\n"
44
+ str += " Total: #{ftos a.total_cost}#{ftos a.total_avg}#{ftos a.total_max}\n"
45
+ str += " Render: #{ftos a.render_cost}#{ftos a.render_avg}#{ftos a.render_max}\n"
46
+ str += " DB: #{ftos a.db_cost}#{ftos a.db_avg}#{ftos a.db_max}\n"
47
+ end
48
+ end
49
+ return str
50
+ end
51
+
52
+ def print_sessions
53
+ str = ""
54
+ str += " Cost Average Max\n"
55
+ sessions.sort{|x,y| y.total_cost <=> x.total_cost}.each do |s|
56
+ str += "==#{s.name}==\n"
57
+ str += " Total: #{ftos s.total_cost}#{ftos s.total_avg}#{ftos s.total_max}\n"
58
+ str += " Render: #{ftos s.render_cost}#{ftos s.render_avg}#{ftos s.render_max}\n"
59
+ str += " DB: #{ftos s.db_cost}#{ftos s.db_avg}#{ftos s.db_max}\n"
60
+ end
61
+ return str
62
+ end
63
+
64
+ def to_html
65
+ raise "Not Implemented"
66
+ end
67
+
68
+ def controllers
69
+ @controllers.values
70
+ end
71
+
72
+ def actions
73
+ @actions.values
74
+ end
75
+
76
+ def sessions
77
+ @sessions.values
78
+ end
79
+
80
+ private
81
+
82
+ def process
83
+ @controllers ||= {}
84
+ @actions ||= {}
85
+ @sessions ||= {}
86
+ @log_entries.each do |la|
87
+ next if la.processed
88
+ c = @controllers[la.controller]
89
+ if c.nil?
90
+ c = Controller.new(la.controller)
91
+ @controllers[la.controller] = c
92
+ end
93
+ c.add_entry(la)
94
+
95
+ a = @actions[la.action]
96
+ if a.nil?
97
+ a = Action.new(la.action, c)
98
+ @actions[la.action] = a
99
+ c.add_action(a)
100
+ end
101
+ a.add_entry(la)
102
+
103
+ s = @sessions[la.session]
104
+ if s.nil?
105
+ s = Session.new(la.session)
106
+ @sessions[la.session] = s
107
+ end
108
+ s.add_entry(la)
109
+ end
110
+
111
+ # now compute the times for each
112
+ @controllers.values.each{|c| c.compute_times}
113
+ @actions.values.each{|a| a.compute_times}
114
+ @sessions.values.each{|s| s.compute_times}
115
+ end
116
+
117
+ def ftos(float)
118
+ str = ((float*1000).to_i.to_f/1000).to_s
119
+ while str.size < 7
120
+ str += "0"
121
+ end
122
+ str += " "
123
+ end
124
+ end
@@ -0,0 +1,21 @@
1
+ require File.join(File.dirname(__FILE__), 'slow_actions_computation_module')
2
+ class SlowActions
3
+ private
4
+ class Action
5
+ include Computable
6
+ def initialize(name, controller)
7
+ @name = name
8
+ @controller = controller
9
+ @log_entries = []
10
+ end
11
+ attr_reader :name
12
+ attr_reader :controller
13
+
14
+ def add_entry(la)
15
+ @log_entries << la
16
+ la.action = self
17
+ end
18
+ attr_reader :log_entries
19
+
20
+ end
21
+ end
@@ -0,0 +1,41 @@
1
+ module Computable
2
+ attr_reader :render_avg, :db_avg, :total_avg
3
+ attr_reader :render_max, :db_max, :total_max
4
+ attr_reader :render_cost, :db_cost, :total_cost
5
+ attr_reader :error_avg
6
+
7
+ def compute_times
8
+ @render_avg = 0.0
9
+ @db_avg = 0.0
10
+ @total_avg = 0.0
11
+ @render_max = 0.0
12
+ @db_max = 0.0
13
+ @total_max = 0.0
14
+ @error_avg = 0.0
15
+
16
+ @log_entries.each do |la|
17
+ if la.error?
18
+ @error_avg += 1.0
19
+ next
20
+ end
21
+ @render_avg += la.rendering
22
+ @db_avg += la.db
23
+ @total_avg += la.duration
24
+ @render_max = la.rendering if la.rendering > @render_max
25
+ @db_max = la.db if la.db > @db_max
26
+ @total_max = la.duration if la.duration > @total_max
27
+ end
28
+
29
+ @render_avg /= @log_entries.size.to_f
30
+ @db_avg /= @log_entries.size.to_f
31
+ @total_avg /= @log_entries.size.to_f
32
+ @error_avg /= @log_entries.size.to_f
33
+
34
+ # using math.log allows us to smooth out the score between
35
+ # infrequent and very frequent actions. 0.1 is added for a
36
+ # non-0 result
37
+ @render_cost = @render_avg * Math.log(@log_entries.size+0.1)
38
+ @db_cost = @db_avg * Math.log(@log_entries.size+0.1)
39
+ @total_cost = @total_avg * Math.log(@log_entries.size+0.1)
40
+ end
41
+ end
@@ -0,0 +1,25 @@
1
+ require File.join(File.dirname(__FILE__), 'slow_actions_computation_module')
2
+ class SlowActions
3
+ private
4
+ class Controller
5
+ include Computable
6
+ def initialize(name)
7
+ @name = name
8
+ @log_entries = []
9
+ @actions = []
10
+ end
11
+ attr_reader :name
12
+
13
+ def add_entry(la)
14
+ @log_entries << la
15
+ la.controller = self
16
+ end
17
+ attr_reader :log_entries
18
+
19
+ def add_action(a)
20
+ @actions << a
21
+ end
22
+ attr_reader :actions
23
+
24
+ end
25
+ end
@@ -0,0 +1,27 @@
1
+ class SlowActions
2
+ private
3
+ class LogEntry
4
+ def initialize
5
+ self.processed = false
6
+ end
7
+ attr_accessor :controller
8
+ attr_accessor :action
9
+ attr_accessor :ip
10
+ attr_accessor :date
11
+ attr_accessor :time
12
+ attr_accessor :method
13
+ attr_accessor :session
14
+ attr_accessor :parameters
15
+ attr_accessor :duration
16
+ attr_accessor :rendering
17
+ attr_accessor :db
18
+ attr_accessor :error_text
19
+ attr_accessor :processed
20
+
21
+ def error?
22
+ return false if error_text.nil?
23
+ return false if error_text.empty?
24
+ return true
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,85 @@
1
+ require File.join(File.dirname(__FILE__), 'slow_actions_log_entry')
2
+ class SlowActions
3
+ private
4
+ class Parser
5
+
6
+ def initialize(file_path)
7
+ @file_path = file_path
8
+ raise "File not found: #{file_path}" unless File.exists? file_path
9
+ @file = File.new(file_path, 'r')
10
+ end
11
+
12
+ def parse
13
+ @log_entries = []
14
+ begin
15
+ while true
16
+ line = @file.readline
17
+ if line =~ /^Processing/
18
+ @log_entries << parse_log_entry(line)
19
+ end
20
+ end
21
+ rescue EOFError => ex
22
+ @file.close
23
+ end
24
+ return @log_entries
25
+ end
26
+
27
+ private
28
+
29
+ def parse_log_entry(line)
30
+ la = LogEntry.new
31
+ if line =~ /^Processing (\S+)#(\S+) \(for (\S+) at (\S+) (\S+)\) \[(\S+)\]$/
32
+ la.controller = $1
33
+ la.action = $2
34
+ la.ip = $3
35
+ la.date = $4
36
+ la.time = $5
37
+ la.method = $6
38
+ end
39
+ line = @file.readline
40
+ if line =~ /^\s+Session ID: (\S+)$/
41
+ la.session = $1
42
+ end
43
+ line = @file.readline
44
+ if line =~ /^\s+Parameters: (.*)$/
45
+ la.parameters = $1
46
+ end
47
+ line = @file.readline
48
+ if line == "\n"
49
+ error_text = parse_error
50
+ la.error_text = error_text
51
+ return la
52
+ end
53
+ while !(line =~ /^Completed/ and line != "\n")
54
+ line = @file.readline
55
+ end
56
+ if line =~ /^Completed in (\S+)/
57
+ la.duration = $1.to_f
58
+ end
59
+ if line =~ /Rendering: (\S+)/
60
+ la.rendering = $1.to_f
61
+ else
62
+ la.rendering = 0.0
63
+ end
64
+ if line =~ /DB: (\S+)/
65
+ la.db = $1.to_f
66
+ else
67
+ la.db = 0.0
68
+ end
69
+ return la
70
+ end
71
+
72
+ def parse_error
73
+ line = "\n"
74
+ while line == "\n"
75
+ line = @file.readline
76
+ end
77
+ error_txt = ""
78
+ while line != "\n"
79
+ line = @file.readline
80
+ error_txt += line
81
+ end
82
+ return error_txt
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,19 @@
1
+ require File.join(File.dirname(__FILE__), 'slow_actions_computation_module')
2
+ class SlowActions
3
+ private
4
+ class Session
5
+ include Computable
6
+ def initialize(name)
7
+ @name = name
8
+ @log_entries = []
9
+ end
10
+ attr_reader :name
11
+
12
+ def add_entry(la)
13
+ @log_entries << la
14
+ la.session = self
15
+ end
16
+ attr_reader :log_entries
17
+
18
+ end
19
+ end
@@ -0,0 +1,246 @@
1
+ Processing StaticPagesController#static_hunters_lodge (for 141.153.81.49 at 2009-02-23 22:09:43) [GET]
2
+ Session ID: 926fca1a3f54fdd0adc45c7406155306
3
+ Parameters: {"action"=>"static_hunters_lodge", "controller"=>"static_pages"}
4
+ Rendering template within layouts/application
5
+ Rendering static_pages/static_hunters_lodge
6
+ Completed in 0.06000 (16 reqs/sec) | Rendering: 0.04000 (66%) | DB: 0.00400 (6%) | 200 OK [http://play.scavengrnet.com/]
7
+
8
+
9
+ Processing SessionsController#new (for 141.153.81.49 at 2009-02-23 22:10:01) [GET]
10
+ Session ID: 926fca1a3f54fdd0adc45c7406155306
11
+ Parameters: {"action"=>"new", "controller"=>"sessions"}
12
+ Redirected to https://play.scavengrnet.com/login
13
+ Filter chain halted as [:ensure_proper_protocol] rendered_or_redirected.
14
+ Completed in 0.00010 (10000 reqs/sec) | DB: 0.00000 (0%) | 302 Found [http://play.scavengrnet.com/login]
15
+
16
+
17
+ Processing SessionsController#new (for 141.153.81.49 at 2009-02-23 22:10:02) [GET]
18
+ Session ID: 926fca1a3f54fdd0adc45c7406155306
19
+ Parameters: {"action"=>"new", "controller"=>"sessions"}
20
+ Rendering template within layouts/application
21
+ Rendering sessions/new
22
+ Completed in 0.02800 (35 reqs/sec) | Rendering: 0.01600 (57%) | DB: 0.00000 (0%) | 200 OK [https://play.scavengrnet.com/login]
23
+
24
+
25
+ Processing UsersController#index (for 76.120.186.153 at 2009-02-23 22:15:06) [GET]
26
+ Session ID: a0dfedb797521bb9f4749c76bef89d8d
27
+ Parameters: {"action"=>"index", "controller"=>"users"}
28
+ Redirected to https://play.scavengrnet.com/hunters_lodge
29
+ Filter chain halted as [:ensure_proper_protocol] rendered_or_redirected.
30
+ Completed in 0.00010 (10000 reqs/sec) | DB: 0.06400 (64002%) | 302 Found [http://play.scavengrnet.com/hunters_lodge]
31
+
32
+
33
+ Processing UsersController#index (for 76.120.186.153 at 2009-02-23 22:15:07) [GET]
34
+ Session ID: a0dfedb797521bb9f4749c76bef89d8d
35
+ Parameters: {"action"=>"index", "controller"=>"users"}
36
+ Redirected to https://play.scavengrnet.com/
37
+ Completed in 0.00010 (10000 reqs/sec) | DB: 0.25601 (256014%) | 302 Found [https://play.scavengrnet.com/hunters_lodge]
38
+
39
+
40
+ Processing StaticPagesController#static_hunters_lodge (for 76.120.186.153 at 2009-02-23 22:15:08) [GET]
41
+ Session ID: a0dfedb797521bb9f4749c76bef89d8d
42
+ Parameters: {"action"=>"static_hunters_lodge", "controller"=>"static_pages"}
43
+ Redirected to http://play.scavengrnet.com/
44
+ Filter chain halted as [:ensure_proper_protocol] rendered_or_redirected.
45
+ Completed in 0.00010 (10000 reqs/sec) | DB: 0.00000 (0%) | 302 Found [https://play.scavengrnet.com/]
46
+
47
+
48
+ Processing StaticPagesController#static_hunters_lodge (for 76.120.186.153 at 2009-02-23 22:15:08) [GET]
49
+ Session ID: a0dfedb797521bb9f4749c76bef89d8d
50
+ Parameters: {"action"=>"static_hunters_lodge", "controller"=>"static_pages"}
51
+ Rendering template within layouts/application
52
+ Rendering static_pages/static_hunters_lodge
53
+ Completed in 0.06000 (16 reqs/sec) | Rendering: 0.04400 (73%) | DB: 0.21601 (360%) | 200 OK [http://play.scavengrnet.com/]
54
+
55
+
56
+ Processing SessionsController#new (for 76.120.186.153 at 2009-02-23 22:15:19) [GET]
57
+ Session ID: a0dfedb797521bb9f4749c76bef89d8d
58
+ Parameters: {"action"=>"new", "controller"=>"sessions"}
59
+ Redirected to https://play.scavengrnet.com/login
60
+ Filter chain halted as [:ensure_proper_protocol] rendered_or_redirected.
61
+ Completed in 0.00010 (10000 reqs/sec) | DB: 0.00000 (0%) | 302 Found [http://play.scavengrnet.com/login]
62
+
63
+
64
+ Processing SessionsController#new (for 76.120.186.153 at 2009-02-23 22:15:19) [GET]
65
+ Session ID: a0dfedb797521bb9f4749c76bef89d8d
66
+ Parameters: {"action"=>"new", "controller"=>"sessions"}
67
+ Rendering template within layouts/application
68
+ Rendering sessions/new
69
+ Completed in 0.01200 (83 reqs/sec) | Rendering: 0.00800 (66%) | DB: 0.00000 (0%) | 200 OK [https://play.scavengrnet.com/login]
70
+
71
+
72
+ Processing SessionsController#create (for 76.120.186.153 at 2009-02-23 22:15:44) [POST]
73
+ Session ID: a0dfedb797521bb9f4749c76bef89d8d
74
+ Parameters: {"commit"=>"Log in", "authenticity_token"=>"d86bce53f5938a51f226742582ee28013d794fd8", "action"=>"create", "controller"=>"sessions", "password"=>"rossj", "email"=>"jrmcclain@comcast.net"}
75
+ Redirected to https://play.scavengrnet.com/hunters_lodge
76
+ Completed in 0.06400 (15 reqs/sec) | DB: 0.04800 (75%) | 302 Found [https://play.scavengrnet.com/session]
77
+
78
+
79
+ Processing UsersController#index (for 76.120.186.153 at 2009-02-23 22:15:44) [GET]
80
+ Session ID: a0dfedb797521bb9f4749c76bef89d8d
81
+ Parameters: {"action"=>"index", "controller"=>"users"}
82
+ Rendering template within layouts/application
83
+ Rendering users/index
84
+ Completed in 6.62038 (0 reqs/sec) | Rendering: 6.24036 (94%) | DB: 0.36402 (5%) | 200 OK [https://play.scavengrnet.com/hunters_lodge]
85
+
86
+
87
+ Processing UsersController#winning_history (for 76.120.186.153 at 2009-02-23 22:16:31) [GET]
88
+ Session ID: a0dfedb797521bb9f4749c76bef89d8d
89
+ Parameters: {"action"=>"winning_history", "id"=>"138", "controller"=>"users"}
90
+ Redirected to http://play.scavengrnet.com/users/138/winning_history
91
+ Filter chain halted as [:ensure_proper_protocol] rendered_or_redirected.
92
+ Completed in 0.00010 (10000 reqs/sec) | DB: 0.02400 (24000%) | 302 Found [https://play.scavengrnet.com/users/138/winning_history]
93
+
94
+
95
+ Processing UsersController#winning_history (for 76.120.186.153 at 2009-02-23 22:16:31) [GET]
96
+ Session ID: a0dfedb797521bb9f4749c76bef89d8d
97
+ Parameters: {"action"=>"winning_history", "id"=>"138", "controller"=>"users"}
98
+ Rendering template within layouts/application
99
+ Rendering users/winning_history
100
+ Completed in 0.10401 (9 reqs/sec) | Rendering: 0.03200 (30%) | DB: 0.34802 (334%) | 200 OK [http://play.scavengrnet.com/users/138/winning_history]
101
+
102
+
103
+ Processing UsersController#images (for 76.120.186.153 at 2009-02-23 22:16:32) [GET]
104
+ Session ID: a0dfedb797521bb9f4749c76bef89d8d
105
+ Parameters: {"format"=>"png", "action"=>"images", "id"=>"history-bottom", "controller"=>"users"}
106
+
107
+
108
+ ActionController::UnknownAction (No action responded to images):
109
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/filters.rb:579:in `call_filters'
110
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/filters.rb:572:in `perform_action_without_benchmark'
111
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue'
112
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/1.8/benchmark.rb:293:in `measure'
113
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue'
114
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/rescue.rb:201:in `perform_action_without_caching'
115
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/caching/sql_cache.rb:13:in `passenger_orig_perform_action'
116
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/activerecord-2.1.1/lib/active_record/connection_adapters/abstract/query_cache.rb:33:in `cache'
117
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/activerecord-2.1.1/lib/active_record/query_cache.rb:8:in `cache'
118
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/caching/sql_cache.rb:12:in `passenger_orig_perform_action'
119
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/railz/request_handler.rb:53:in `perform_action'
120
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/base.rb:529:in `send'
121
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/base.rb:529:in `process_without_filters'
122
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/filters.rb:568:in `process_without_session_management_support'
123
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/session_management.rb:130:in `process'
124
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/base.rb:389:in `process'
125
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/dispatcher.rb:149:in `handle_request'
126
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/dispatcher.rb:107:in `dispatch'
127
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/dispatcher.rb:104:in `synchronize'
128
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/dispatcher.rb:104:in `dispatch'
129
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/dispatcher.rb:120:in `dispatch_cgi'
130
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/dispatcher.rb:35:in `dispatch'
131
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/railz/request_handler.rb:38:in `process_request'
132
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_request_handler.rb:165:in `main_loop'
133
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/railz/application_spawner.rb:321:in `start_request_handler'
134
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/railz/application_spawner.rb:282:in `handle_spawn_application'
135
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/utils.rb:163:in `safe_fork'
136
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/utils.rb:161:in `fork'
137
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/utils.rb:161:in `safe_fork'
138
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/railz/application_spawner.rb:280:in `handle_spawn_application'
139
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/utils.rb:163:in `safe_fork'
140
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/utils.rb:161:in `fork'
141
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/utils.rb:161:in `safe_fork'
142
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/railz/application_spawner.rb:279:in `handle_spawn_application'
143
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_server.rb:317:in `__send__'
144
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_server.rb:317:in `main_loop'
145
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_server.rb:168:in `start_synchronously'
146
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_server.rb:135:in `start'
147
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_server.rb:112:in `fork'
148
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_server.rb:112:in `start'
149
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/railz/application_spawner.rb:179:in `start'
150
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/railz/framework_spawner.rb:270:in `handle_spawn_application'
151
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/railz/framework_spawner.rb:263:in `synchronize'
152
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/railz/framework_spawner.rb:263:in `handle_spawn_application'
153
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_server.rb:317:in `__send__'
154
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_server.rb:317:in `main_loop'
155
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_server.rb:168:in `start_synchronously'
156
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_server.rb:135:in `start'
157
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_server.rb:112:in `fork'
158
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_server.rb:112:in `start'
159
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/railz/framework_spawner.rb:87:in `start'
160
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/spawn_manager.rb:222:in `spawn_rails_application'
161
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/spawn_manager.rb:217:in `synchronize'
162
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/spawn_manager.rb:217:in `spawn_rails_application'
163
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/spawn_manager.rb:126:in `spawn_application'
164
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/spawn_manager.rb:251:in `handle_spawn_application'
165
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_server.rb:317:in `__send__'
166
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_server.rb:317:in `main_loop'
167
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_server.rb:168:in `start_synchronously'
168
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/bin/passenger-spawn-server:46
169
+
170
+
171
+
172
+ Processing UsersController#images (for 76.120.186.153 at 2009-02-23 22:16:32) [GET]
173
+ Session ID: a0dfedb797521bb9f4749c76bef89d8d
174
+ Parameters: {"format"=>"png", "action"=>"images", "id"=>"hunts-bottom", "controller"=>"users"}
175
+
176
+
177
+ ActionController::UnknownAction (No action responded to images):
178
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/filters.rb:579:in `call_filters'
179
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/filters.rb:572:in `perform_action_without_benchmark'
180
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue'
181
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/1.8/benchmark.rb:293:in `measure'
182
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/benchmarking.rb:68:in `perform_action_without_rescue'
183
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/rescue.rb:201:in `perform_action_without_caching'
184
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/caching/sql_cache.rb:13:in `passenger_orig_perform_action'
185
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/activerecord-2.1.1/lib/active_record/connection_adapters/abstract/query_cache.rb:33:in `cache'
186
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/activerecord-2.1.1/lib/active_record/query_cache.rb:8:in `cache'
187
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/caching/sql_cache.rb:12:in `passenger_orig_perform_action'
188
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/railz/request_handler.rb:53:in `perform_action'
189
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/base.rb:529:in `send'
190
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/base.rb:529:in `process_without_filters'
191
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/filters.rb:568:in `process_without_session_management_support'
192
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/session_management.rb:130:in `process'
193
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/base.rb:389:in `process'
194
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/dispatcher.rb:149:in `handle_request'
195
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/dispatcher.rb:107:in `dispatch'
196
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/dispatcher.rb:104:in `synchronize'
197
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/dispatcher.rb:104:in `dispatch'
198
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/dispatcher.rb:120:in `dispatch_cgi'
199
+ /opt/ruby-enterprise-1.8.6-20090113/lib/ruby/gems/1.8/gems/actionpack-2.1.1/lib/action_controller/dispatcher.rb:35:in `dispatch'
200
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/railz/request_handler.rb:38:in `process_request'
201
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_request_handler.rb:165:in `main_loop'
202
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/railz/application_spawner.rb:321:in `start_request_handler'
203
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/railz/application_spawner.rb:282:in `handle_spawn_application'
204
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/utils.rb:163:in `safe_fork'
205
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/utils.rb:161:in `fork'
206
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/utils.rb:161:in `safe_fork'
207
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/railz/application_spawner.rb:280:in `handle_spawn_application'
208
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/utils.rb:163:in `safe_fork'
209
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/utils.rb:161:in `fork'
210
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/utils.rb:161:in `safe_fork'
211
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/railz/application_spawner.rb:279:in `handle_spawn_application'
212
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_server.rb:317:in `__send__'
213
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_server.rb:317:in `main_loop'
214
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_server.rb:168:in `start_synchronously'
215
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_server.rb:135:in `start'
216
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_server.rb:112:in `fork'
217
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_server.rb:112:in `start'
218
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/railz/application_spawner.rb:179:in `start'
219
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/railz/framework_spawner.rb:270:in `handle_spawn_application'
220
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/railz/framework_spawner.rb:263:in `synchronize'
221
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/railz/framework_spawner.rb:263:in `handle_spawn_application'
222
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_server.rb:317:in `__send__'
223
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_server.rb:317:in `main_loop'
224
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_server.rb:168:in `start_synchronously'
225
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_server.rb:135:in `start'
226
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_server.rb:112:in `fork'
227
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_server.rb:112:in `start'
228
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/railz/framework_spawner.rb:87:in `start'
229
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/spawn_manager.rb:222:in `spawn_rails_application'
230
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/spawn_manager.rb:217:in `synchronize'
231
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/spawn_manager.rb:217:in `spawn_rails_application'
232
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/spawn_manager.rb:126:in `spawn_application'
233
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/spawn_manager.rb:251:in `handle_spawn_application'
234
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_server.rb:317:in `__send__'
235
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_server.rb:317:in `main_loop'
236
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/lib/passenger/abstract_server.rb:168:in `start_synchronously'
237
+ /opt/ruby/lib/ruby/gems/1.8/gems/passenger-2.0.6/bin/passenger-spawn-server:46
238
+
239
+
240
+
241
+ Processing QuestionViewsController#create (for 76.119.35.134 at 2009-02-24 01:30:39) [POST]
242
+ Session ID: 436d4f7cab8b7da618a96d28d79162af
243
+ Parameters: {"authenticity_token"=>"a3c2dbfb77d04c48ecf4f1f2660d540200c5cf3a", "action"=>"create", "controller"=>"question_views", "question_view"=>{"question_id"=>"996", "time"=>"483.6666666666667"}}
244
+ Completed in 0.02800 (35 reqs/sec) | Rendering: 0.00400 (14%) | DB: 0.02400 (85%) | 200 OK [http://play.scavengrnet.com/question_views]
245
+
246
+
@@ -0,0 +1,72 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class SlowActionsTest < Test::Unit::TestCase
4
+ def setup
5
+ @log_file = File.join(File.dirname(__FILE__), 'data', 'production.recent.log')
6
+ @sa = SlowActions.new
7
+ @sa.parse_file(@log_file)
8
+ end
9
+
10
+ def teardown
11
+
12
+ end
13
+
14
+ should "be able to read actions from a file" do
15
+ assert @sa.log_entries.size > 0, "No actions returned"
16
+ assert_equal 16, @sa.log_entries.size, "Wrong number of actions"
17
+ error_action = @sa.log_entries.detect{|la| la.error? }
18
+ assert_not_nil error_action, "There should be an error action"
19
+ end
20
+
21
+ should "have populated controllers" do
22
+ @sa.controllers.each do |c|
23
+ assert c.log_entries.size > 0
24
+ end
25
+ # Make sure each log entry belongs to a controller
26
+ @sa.log_entries.each do |la|
27
+ assert_not_nil @sa.controllers.detect{|c| c.log_entries.include?(la)}
28
+ # and only one controller claims it
29
+ assert_equal 1, @sa.controllers.select{|c| c.log_entries.include?(la)}.size
30
+ end
31
+ end
32
+
33
+ should "have populated actions" do
34
+ @sa.actions.each do |a|
35
+ assert a.log_entries.size > 0
36
+ end
37
+ # Make sure each log entry belongs to an action
38
+ @sa.log_entries.each do |la|
39
+ assert_not_nil @sa.actions.detect{|a| a.log_entries.include?(la)}
40
+ # and only one action claims it
41
+ assert_equal 1, @sa.actions.select{|a| a.log_entries.include?(la)}.size
42
+ end
43
+ end
44
+
45
+ should "have populated sessions" do
46
+ @sa.sessions.each do |a|
47
+ assert a.log_entries.size > 0
48
+ end
49
+ # Make sure each log entry belongs to a session
50
+ @sa.log_entries.each do |la|
51
+ assert_not_nil @sa.sessions.detect{|s| s.log_entries.include?(la)}
52
+ # and only one session claims it
53
+ assert_equal 1, @sa.sessions.select{|s| s.log_entries.include?(la)}.size
54
+ end
55
+ end
56
+
57
+ should "compute times" do
58
+ (@sa.controllers + @sa.actions + @sa.sessions).each do |obj|
59
+ # don't count them as faulty if they are all errors
60
+ next if obj.error_avg == 1
61
+ %w(total_avg total_max total_cost).each do |var|
62
+ assert obj.send(var) > 0, "#{obj.name} should have #{var} that is not 0"
63
+ end
64
+ end
65
+ end
66
+
67
+ should "render text without errors" do
68
+ @sa.print_actions
69
+ @sa.print_controller_tree
70
+ @sa.print_sessions
71
+ end
72
+ end
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+ require 'mocha'
5
+
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'slow_actions'
8
+
9
+ class Test::Unit::TestCase
10
+ end
metadata ADDED
@@ -0,0 +1,67 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ngauthier-slow-actions
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.2
5
+ platform: ruby
6
+ authors:
7
+ - Nick Gauthier
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-02-26 00:00:00 -08:00
13
+ default_executable: slow-actions
14
+ dependencies: []
15
+
16
+ description: TODO
17
+ email: nick@smartlogicsolutions.com
18
+ executables:
19
+ - slow-actions
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - VERSION.yml
26
+ - README.rdoc
27
+ - bin/slow-actions
28
+ - lib/slow_actions_controller.rb
29
+ - lib/slow_actions_action.rb
30
+ - lib/slow_actions_parser.rb
31
+ - lib/slow_actions_log_entry.rb
32
+ - lib/slow_actions.rb
33
+ - lib/slow_actions_session.rb
34
+ - lib/slow_actions_computation_module.rb
35
+ - test/test_helper.rb
36
+ - test/data
37
+ - test/data/production.recent.log
38
+ - test/slow_actions_test.rb
39
+ has_rdoc: true
40
+ homepage: http://github.com/ngauthier/slow-actions
41
+ post_install_message:
42
+ rdoc_options:
43
+ - --inline-source
44
+ - --charset=UTF-8
45
+ require_paths:
46
+ - lib
47
+ required_ruby_version: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ">="
50
+ - !ruby/object:Gem::Version
51
+ version: "0"
52
+ version:
53
+ required_rubygems_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: "0"
58
+ version:
59
+ requirements: []
60
+
61
+ rubyforge_project:
62
+ rubygems_version: 1.2.0
63
+ signing_key:
64
+ specification_version: 2
65
+ summary: TODO
66
+ test_files: []
67
+