oink 0.1.2 → 0.9.1

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.
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