oink 0.1.2 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/README.rdoc +15 -29
  2. data/Rakefile +4 -6
  3. data/bin/oink +2 -2
  4. data/lib/oink.rb +1 -9
  5. data/lib/oink/cli.rb +71 -67
  6. data/lib/oink/instrumentation.rb +2 -0
  7. data/lib/oink/instrumentation/active_record.rb +63 -0
  8. data/lib/oink/instrumentation/memory_snapshot.rb +119 -0
  9. data/lib/oink/middleware.rb +48 -0
  10. data/lib/oink/rails/instance_type_counter.rb +8 -62
  11. data/lib/oink/rails/memory_usage_logger.rb +11 -33
  12. data/lib/oink/reports/active_record_instantiation_oinked_request.rb +13 -0
  13. data/lib/oink/reports/active_record_instantiation_report.rb +67 -0
  14. data/lib/oink/reports/base.rb +38 -0
  15. data/lib/oink/reports/memory_oinked_request.rb +13 -0
  16. data/lib/oink/reports/memory_usage_report.rb +71 -0
  17. data/lib/oink/reports/priority_queue.rb +41 -0
  18. data/lib/oink/reports/request.rb +20 -0
  19. data/lib/oink/utils/hash_utils.rb +9 -0
  20. data/spec/fakes/fake_application_controller.rb +30 -0
  21. data/spec/fakes/psuedo_output.rb +7 -0
  22. data/spec/helpers/database.rb +20 -0
  23. data/spec/{rails → oink/instrumentation}/instance_type_counter_spec.rb +11 -9
  24. data/spec/oink/instrumentation/memory_snapshot_spec.rb +84 -0
  25. data/spec/oink/middleware_spec.rb +73 -0
  26. data/spec/oink/rails/instance_type_counter_spec.rb +52 -0
  27. data/spec/oink/rails/memory_usage_logger_spec.rb +23 -0
  28. data/spec/oink/reports/active_record_instantiation_report_spec.rb +193 -0
  29. data/spec/oink/reports/memory_usage_report_spec.rb +267 -0
  30. data/spec/oink/reports/oinked_request_spec.rb +22 -0
  31. data/spec/oink/reports/priority_queue_spec.rb +74 -0
  32. data/spec/spec_helper.rb +10 -26
  33. metadata +158 -29
  34. data/lib/oink/active_record_instantiation_reporter.rb +0 -68
  35. data/lib/oink/base.rb +0 -40
  36. data/lib/oink/memory_usage_reporter.rb +0 -72
  37. data/lib/oink/oinked_request/oinked_ar_request.rb +0 -9
  38. data/lib/oink/oinked_request/oinked_memory_request.rb +0 -9
  39. data/lib/oink/oinked_request/oinked_request.rb +0 -16
  40. data/lib/oink/priority_queue.rb +0 -37
  41. data/spec/oink/active_record_instantiation_reporter_spec.rb +0 -191
  42. data/spec/oink/memory_usage_reporter_spec.rb +0 -265
  43. data/spec/oinked_request/oinked_request_spec.rb +0 -20
  44. data/spec/priority_queue/priority_queue_spec.rb +0 -75
  45. data/spec/rails/memory_usage_logger_spec.rb +0 -87
@@ -1,68 +0,0 @@
1
- require "date"
2
- require "oink/base"
3
- require "oink/oinked_request/oinked_ar_request"
4
- require "oink/priority_queue"
5
-
6
- module Oink
7
-
8
- class ActiveRecordInstantiationReporter < Base
9
-
10
- def print(output)
11
- output.puts "---- OINK FOR ACTIVERECORD ----"
12
- output.puts "THRESHOLD: #{@threshold} Active Record objects per request\n"
13
-
14
- output.puts "\n-- REQUESTS --\n" if @format == :verbose
15
-
16
- @inputs.each do |input|
17
- input.each_line do |line|
18
- line = line.strip
19
-
20
- # Skip this line since we're only interested in the Hodel 3000 compliant lines
21
- next unless line =~ HODEL_LOG_FORMAT_REGEX
22
-
23
- if line =~ /rails\[(\d+)\]/
24
- pid = $1
25
- @pids[pid] ||= { :buffer => [], :ar_count => -1, :action => "", :request_finished => true }
26
- @pids[pid][:buffer] << line
27
- end
28
-
29
- if line =~ /Processing ((\w+)#(\w+)) /
30
-
31
- @pids[pid][:action] = $1
32
- unless @pids[pid][:request_finished]
33
- @pids[pid][:buffer] = [line]
34
- end
35
- @pids[pid][:request_finished] = false
36
-
37
- elsif line =~ /Instantiation Breakdown: Total: (\d+)/
38
-
39
- @pids[pid][:ar_count] = $1.to_i
40
-
41
- elsif line =~ /Completed in/
42
-
43
- if @pids[pid][:ar_count] > @threshold
44
- @bad_actions[@pids[pid][:action]] ||= 0
45
- @bad_actions[@pids[pid][:action]] = @bad_actions[@pids[pid][:action]] + 1
46
- date = HODEL_LOG_FORMAT_REGEX.match(line).captures[0]
47
- @bad_requests.push(OinkedARRequest.new(@pids[pid][:action], date, @pids[pid][:buffer], @pids[pid][:ar_count]))
48
- if @format == :verbose
49
- @pids[pid][:buffer].each { |b| output.puts b }
50
- output.puts "---------------------------------------------------------------------"
51
- end
52
- end
53
-
54
- @pids[pid][:request_finished] = true
55
- @pids[pid][:buffer] = []
56
- @pids[pid][:ar_count] = -1
57
-
58
- end # end elsif
59
- end # end each_line
60
- end # end each input
61
-
62
- print_summary(output)
63
-
64
- end
65
-
66
- end
67
-
68
- end
@@ -1,40 +0,0 @@
1
- module Oink
2
-
3
- class Base
4
-
5
- VERSION = '0.1.2'
6
- FORMATS = %w[verbose short-summary summary]
7
- FORMAT_ALIASES = { "v" => "verbose", "ss" => "short-summary", "s" => "summary" }
8
- HODEL_LOG_FORMAT_REGEX = /^(\w+ \d{2} \d{2}:\d{2}:\d{2})/
9
-
10
- def initialize(input, threshold, options = {})
11
- @inputs = Array(input)
12
- @threshold = threshold
13
- @format = options[:format] || :short_summary
14
-
15
- @pids = {}
16
- @bad_actions = {}
17
- @bad_requests = PriorityQueue.new(10)
18
- end
19
-
20
- protected
21
-
22
- def print_summary(output)
23
- output.puts "\n-- SUMMARY --\n"
24
- output.puts "Worst Requests:"
25
- @bad_requests.each_with_index do |offender, index|
26
- output.puts "#{index + 1}. #{offender.datetime}, #{offender.display_oink_number}, #{offender.action}"
27
- if @format == :summary
28
- offender.log_lines.each { |b| output.puts b }
29
- output.puts "---------------------------------------------------------------------"
30
- end
31
- end
32
- output.puts "\nWorst Actions:"
33
- @bad_actions.sort{|a,b| b[1]<=>a[1]}.each { |elem|
34
- output.puts "#{elem[1]}, #{elem[0]}"
35
- }
36
- end
37
-
38
- end
39
-
40
- end
@@ -1,72 +0,0 @@
1
- require "date"
2
- require "oink/base"
3
- require "oink/oinked_request/oinked_memory_request"
4
- require "oink/priority_queue"
5
-
6
- module Oink
7
-
8
- class MemoryUsageReporter < Base
9
- def print(output)
10
- output.puts "---- MEMORY THRESHOLD ----"
11
- output.puts "THRESHOLD: #{@threshold/1024} MB\n"
12
-
13
- output.puts "\n-- REQUESTS --\n" if @format == :verbose
14
-
15
- @inputs.each do |input|
16
- input.each_line do |line|
17
- line = line.strip
18
-
19
- # Skip this line since we're only interested in the Hodel 3000 compliant lines
20
- next unless line =~ HODEL_LOG_FORMAT_REGEX
21
-
22
- if line =~ /rails\[(\d+)\]/
23
- pid = $1
24
- @pids[pid] ||= { :buffer => [], :last_memory_reading => -1, :current_memory_reading => -1, :action => "", :request_finished => true }
25
- @pids[pid][:buffer] << line
26
- end
27
-
28
- if line =~ /Processing ((\w+)#(\w+)) /
29
-
30
- unless @pids[pid][:request_finished]
31
- @pids[pid][:last_memory_reading] = -1
32
- end
33
- @pids[pid][:action] = $1
34
- @pids[pid][:request_finished] = false
35
-
36
- elsif line =~ /Memory usage: (\d+) /
37
-
38
- memory_reading = $1.to_i
39
- @pids[pid][:current_memory_reading] = memory_reading
40
-
41
- elsif line =~ /Completed in/
42
-
43
- @pids[pid][:request_finished] = true
44
- unless @pids[pid][:current_memory_reading] == -1 || @pids[pid][:last_memory_reading] == -1
45
- memory_diff = @pids[pid][:current_memory_reading] - @pids[pid][:last_memory_reading]
46
- if memory_diff > @threshold
47
- @bad_actions[@pids[pid][:action]] ||= 0
48
- @bad_actions[@pids[pid][:action]] = @bad_actions[@pids[pid][:action]] + 1
49
- date = HODEL_LOG_FORMAT_REGEX.match(line).captures[0]
50
- @bad_requests.push(OinkedMemoryRequest.new(@pids[pid][:action], date, @pids[pid][:buffer], memory_diff))
51
- if @format == :verbose
52
- @pids[pid][:buffer].each { |b| output.puts b }
53
- output.puts "---------------------------------------------------------------------"
54
- end
55
- end
56
- end
57
-
58
- @pids[pid][:buffer] = []
59
- @pids[pid][:last_memory_reading] = @pids[pid][:current_memory_reading]
60
- @pids[pid][:current_memory_reading] = -1
61
-
62
- end # end elsif
63
- end # end each_line
64
- end # end each input
65
-
66
- print_summary(output)
67
-
68
- end
69
-
70
- end
71
-
72
- end
@@ -1,9 +0,0 @@
1
- require "oink/oinked_request/oinked_request"
2
-
3
- class OinkedARRequest < OinkedRequest
4
-
5
- def display_oink_number
6
- @oink_number
7
- end
8
-
9
- end
@@ -1,9 +0,0 @@
1
- require "oink/oinked_request/oinked_request"
2
-
3
- class OinkedMemoryRequest < OinkedRequest
4
-
5
- def display_oink_number
6
- "#{@oink_number} KB"
7
- end
8
-
9
- end
@@ -1,16 +0,0 @@
1
- class OinkedRequest
2
- include Comparable
3
-
4
- attr_accessor :action, :datetime, :log_lines, :oink_number
5
-
6
- def initialize(action, datetime, log_lines, oink_number)
7
- @action = action
8
- @datetime = datetime
9
- @log_lines = log_lines
10
- @oink_number = oink_number
11
- end
12
-
13
- def <=>(other)
14
- self.oink_number <=> other.oink_number
15
- end
16
- end
@@ -1,37 +0,0 @@
1
- class PriorityQueue
2
-
3
- include Enumerable
4
-
5
- def initialize(size)
6
- @size = size
7
- @queue = []
8
- end
9
-
10
- def push(item)
11
- if @queue.size < @size
12
- @queue << item
13
- elsif item > @queue.last
14
- @queue[@size - 1] = item
15
- end
16
- prioritize
17
- end
18
-
19
- def to_a
20
- @queue
21
- end
22
-
23
- def size
24
- @queue.size
25
- end
26
-
27
- def each
28
- @queue.each { |i| yield i }
29
- end
30
-
31
- protected
32
-
33
- def prioritize
34
- @queue.sort! { |a, b| b <=> a }
35
- end
36
-
37
- end
@@ -1,191 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
-
3
- describe Oink::ActiveRecordInstantiationReporter do
4
-
5
- describe "short summary with frequent offenders" do
6
-
7
- it "should report actions which exceed the threshold once" do
8
- str = <<-STR
9
- Feb 01 01:58:29 ey04-s00297 rails[4413]: Processing Users#show (for 92.84.151.171 at 2009-02-01 01:58:29) [GET]
10
- Feb 01 01:58:30 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 51 | User: 51
11
- Feb 01 01:58:31 ey04-s00297 rails[4413]: Completed in 984ms (View: 840, DB: 4) | 200 OK
12
- STR
13
-
14
- io = StringIO.new(str)
15
- output = PsuedoOutput.new
16
- Oink::ActiveRecordInstantiationReporter.new(io, 50).print(output)
17
- output.should include("1, Users#show")
18
- end
19
-
20
- it "should not report actions which do not exceed the threshold" do
21
- str = <<-STR
22
- Feb 01 01:58:29 ey04-s00297 rails[4413]: Processing Users#show (for 92.84.151.171 at 2009-02-01 01:58:29) [GET]
23
- Feb 01 01:58:30 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 50 | User: 50
24
- Feb 01 01:58:31 ey04-s00297 rails[4413]: Completed in 984ms (View: 840, DB: 4) | 200 OK
25
- STR
26
-
27
- io = StringIO.new(str)
28
- output = PsuedoOutput.new
29
- Oink::ActiveRecordInstantiationReporter.new(io, 50).print(output)
30
- output.should_not include("1, Users#show")
31
- end
32
-
33
- it "should report actions which exceed the threshold multiple times" do
34
- str = <<-STR
35
- Feb 01 01:58:29 ey04-s00297 rails[4413]: Processing Users#show (for 92.84.151.171 at 2009-02-01 01:58:29) [GET]
36
- Feb 01 01:58:30 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 51 | User: 51
37
- Feb 01 01:58:31 ey04-s00297 rails[4413]: Completed in 984ms (View: 840, DB: 4) | 200 OK
38
- Feb 01 01:58:29 ey04-s00297 rails[4413]: Processing Users#show (for 92.84.151.171 at 2009-02-01 01:58:29) [GET]
39
- Feb 01 01:58:30 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 51 | User: 51
40
- Feb 01 01:58:31 ey04-s00297 rails[4413]: Completed in 984ms (View: 840, DB: 4) | 200 OK
41
- STR
42
-
43
- io = StringIO.new(str)
44
- output = PsuedoOutput.new
45
- Oink::ActiveRecordInstantiationReporter.new(io, 50).print(output)
46
- output.should include("2, Users#show")
47
- end
48
-
49
- it "should order actions by most exceeded" do
50
- str = <<-STR
51
- Feb 01 01:58:29 ey04-s00297 rails[4413]: Processing Media#show (for 92.84.151.171 at 2009-02-01 01:58:29) [GET]
52
- Feb 01 01:58:30 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 51 | User: 51
53
- Feb 01 01:58:31 ey04-s00297 rails[4413]: Completed in 984ms (View: 840, DB: 4) | 200 OK
54
- Feb 01 01:58:29 ey04-s00297 rails[4413]: Processing Media#show (for 92.84.151.171 at 2009-02-01 01:58:29) [GET]
55
- Feb 01 01:58:30 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 51 | User: 51
56
- Feb 01 01:58:31 ey04-s00297 rails[4413]: Completed in 984ms (View: 840, DB: 4) | 200 OK
57
- Feb 01 01:58:29 ey04-s00297 rails[4413]: Processing Users#show (for 92.84.151.171 at 2009-02-01 01:58:29) [GET]
58
- Feb 01 01:58:30 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 51 | User: 51
59
- Feb 01 01:58:31 ey04-s00297 rails[4413]: Completed in 984ms (View: 840, DB: 4) | 200 OK
60
- STR
61
-
62
- io = StringIO.new(str)
63
- output = PsuedoOutput.new
64
- Oink::ActiveRecordInstantiationReporter.new(io, 50).print(output)
65
- output[-2].should == "2, Media#show"
66
- output[-1].should == "1, Users#show"
67
- end
68
-
69
- it "should not be bothered by incomplete requests" do
70
- str = <<-STR
71
- Feb 01 01:58:29 ey04-s00297 rails[4413]: Processing Media#show (for 92.84.151.171 at 2009-02-01 01:58:29) [GET]
72
- Feb 01 01:58:30 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 24 | User: 24
73
- Feb 01 01:58:31 ey04-s00297 rails[4413]: Completed in 984ms (View: 840, DB: 4) | 200 OK
74
- Feb 01 01:58:29 ey04-s00297 rails[4413]: Processing Media#show (for 92.84.151.171 at 2009-02-01 01:58:29) [GET]
75
- Feb 01 01:58:29 ey04-s00297 rails[4413]: Processing Users#show (for 92.84.151.171 at 2009-02-01 01:58:29) [GET]
76
- Feb 01 01:58:30 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 51 | User: 51
77
- Feb 01 01:58:31 ey04-s00297 rails[4413]: Completed in 984ms (View: 840, DB: 4) | 200 OK
78
- STR
79
-
80
- io = StringIO.new(str)
81
- output = PsuedoOutput.new
82
- Oink::ActiveRecordInstantiationReporter.new(io, 50).print(output)
83
- output.should include("1, Users#show")
84
- end
85
-
86
- end
87
-
88
- describe "summary with top 10 offenses" do
89
-
90
- it "should only report requests over threshold" do
91
- str = <<-STR
92
- Feb 01 01:58:29 ey04-s00297 rails[4413]: Processing Users#show (for 92.84.151.171 at 2009-02-01 01:58:29) [GET]
93
- Feb 01 01:58:30 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 51 | User: 51
94
- Feb 01 01:58:31 ey04-s00297 rails[4413]: Completed in 984ms (View: 840, DB: 4) | 200 OK
95
- STR
96
-
97
- io = StringIO.new(str)
98
- output = PsuedoOutput.new
99
- Oink::ActiveRecordInstantiationReporter.new(io, 50).print(output)
100
- output.should include("1. Feb 01 01:58:31, 51, Users#show")
101
- end
102
-
103
- it "should not include requests which are not over threshold" do
104
- str = <<-STR
105
- Feb 01 01:58:29 ey04-s00297 rails[4413]: Processing Users#show (for 92.84.151.171 at 2009-02-01 01:58:29) [GET]
106
- Feb 01 01:58:30 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 50 | User: 50
107
- Feb 01 01:58:31 ey04-s00297 rails[4413]: Completed in 984ms (View: 840, DB: 4) | 200 OK
108
- STR
109
-
110
- io = StringIO.new(str)
111
- output = PsuedoOutput.new
112
- Oink::ActiveRecordInstantiationReporter.new(io, 50).print(output)
113
- output.should_not include("1. Feb 01 01:58:31, 50, Users#show")
114
- end
115
-
116
- it "should order offenses from biggest to smallest" do
117
- str = <<-STR
118
- Feb 01 01:58:29 ey04-s00297 rails[4413]: Processing DetailsController#show (for 92.84.151.171 at 2009-02-01 01:58:29) [GET]
119
- Feb 01 01:58:30 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 75 | User: 75
120
- Feb 01 01:58:31 ey04-s00297 rails[4413]: Completed in 984ms (View: 840, DB: 4) | 200 OK
121
- Feb 01 01:58:32 ey04-s00297 rails[4413]: Processing MediaController#show (for 92.84.151.171 at 2009-02-01 01:58:29) [GET]
122
- Feb 01 01:58:33 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 100 | User: 100
123
- Feb 01 01:58:34 ey04-s00297 rails[4413]: Completed in 984ms (View: 840, DB: 4) | 200 OK
124
- STR
125
-
126
- io = StringIO.new(str)
127
- output = PsuedoOutput.new
128
- Oink::ActiveRecordInstantiationReporter.new(io, 50).print(output)
129
- output[4].should == "1. Feb 01 01:58:34, 100, MediaController#show"
130
- output[5].should == "2. Feb 01 01:58:31, 75, DetailsController#show"
131
- end
132
-
133
- end
134
-
135
- describe "verbose format" do
136
- it "should print the full lines of actions exceeding the threshold" do
137
- str = <<-STR
138
- Feb 01 01:58:32 ey04-s00297 rails[4413]: Processing MediaController#show (for 92.84.151.171 at 2009-02-01 01:58:29) [GET]
139
- Feb 01 01:58:33 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 100 | User: 100
140
- Feb 01 01:58:34 ey04-s00297 rails[4413]: Completed in 984ms (View: 840, DB: 4) | 200 OK
141
- STR
142
- io = StringIO.new(str)
143
- output = PsuedoOutput.new
144
- Oink::ActiveRecordInstantiationReporter.new(io, 50, :format => :verbose).print(output)
145
- output[3..5].should == str.split("\n")[0..2].map { |o| o.strip }
146
- end
147
-
148
- it "should handle actions which do not complete properly" do
149
- str = <<-STR
150
- Feb 01 01:58:29 ey04-s00297 rails[4413]: Processing Media#show (for 92.84.151.171 at 2009-02-01 01:58:29) [GET]
151
- Feb 01 01:58:30 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 24 | User: 24
152
- Feb 01 01:58:31 ey04-s00297 rails[4413]: Completed in 984ms (View: 840, DB: 4) | 200 OK
153
- Feb 01 01:58:29 ey04-s00297 rails[4413]: Processing Media#show (for 92.84.151.171 at 2009-02-01 01:58:29) [GET]
154
- Feb 01 01:58:29 ey04-s00297 rails[4413]: Processing Users#show (for 92.84.151.171 at 2009-02-01 01:58:29) [GET]
155
- Feb 01 01:58:30 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 51 | User: 51
156
- Feb 01 01:58:31 ey04-s00297 rails[4413]: Completed in 984ms (View: 840, DB: 4) | 200 OK
157
- STR
158
-
159
- io = StringIO.new(str)
160
- output = PsuedoOutput.new
161
- Oink::ActiveRecordInstantiationReporter.new(io, 50, :format => :verbose).print(output)
162
- output[3..5].should == str.split("\n")[4..6].map { |o| o.strip }
163
- end
164
- end
165
-
166
- describe "multiple io streams" do
167
- it "should accept multiple files" do
168
-
169
- str1 = <<-STR
170
- Feb 01 01:58:32 ey04-s00297 rails[4413]: Processing MediaController#show (for 92.84.151.171 at 2009-02-01 01:58:29) [GET]
171
- Feb 01 01:58:33 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 100 | User: 100
172
- Feb 01 01:58:34 ey04-s00297 rails[4413]: Completed in 984ms (View: 840, DB: 4) | 200 OK
173
- STR
174
-
175
- str2 = <<-STR
176
- Feb 01 01:58:32 ey04-s00297 rails[4413]: Processing MediaController#show (for 92.84.151.171 at 2009-02-01 01:58:29) [GET]
177
- Feb 01 01:58:33 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 100 | User: 100
178
- Feb 01 01:58:34 ey04-s00297 rails[4413]: Completed in 984ms (View: 840, DB: 4) | 200 OK
179
- STR
180
-
181
- io1 = StringIO.new(str1)
182
- io2 = StringIO.new(str2)
183
- output = PsuedoOutput.new
184
- Oink::ActiveRecordInstantiationReporter.new([io1, io2], 50).print(output)
185
- output.should include("2, MediaController#show")
186
- end
187
-
188
- end
189
-
190
-
191
- end