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
@@ -0,0 +1,20 @@
1
+ module Oink
2
+ module Reports
3
+ class Request
4
+ include Comparable
5
+
6
+ attr_accessor :action, :datetime, :log_lines, :oink_number
7
+
8
+ def initialize(action, datetime, log_lines, oink_number)
9
+ @action = action
10
+ @datetime = datetime
11
+ @log_lines = log_lines
12
+ @oink_number = oink_number
13
+ end
14
+
15
+ def <=>(other)
16
+ self.oink_number <=> other.oink_number
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,9 @@
1
+ module Oink
2
+ module HashUtils
3
+
4
+ def self.to_sorted_array(hsh)
5
+ hsh.sort{ |a, b| b[1] <=>a [1] }.collect { |k,v| "#{k}: #{v}" }
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,30 @@
1
+ class FakeApplicationController
2
+
3
+ def initialize(logger = Logger.new(StringIO.new))
4
+ @logger = logger
5
+ end
6
+
7
+ class << self
8
+ attr_accessor :around_filters
9
+
10
+ def around_filter method
11
+ (@around_filters ||= []) << method
12
+ end
13
+ end
14
+
15
+ def index
16
+ run_around_filters
17
+ end
18
+
19
+ def logger
20
+ @logger
21
+ end
22
+
23
+ protected
24
+ def run_around_filters
25
+ self.class.around_filters.each { |filter| self.send(filter) { perform_action } }
26
+ end
27
+
28
+ def perform_action
29
+ end
30
+ end
@@ -0,0 +1,7 @@
1
+ class PsuedoOutput < Array
2
+
3
+ def puts(line)
4
+ self << line
5
+ end
6
+
7
+ end
@@ -0,0 +1,20 @@
1
+ require 'active_record'
2
+
3
+ def setup_memory_database
4
+ ActiveRecord::Base.establish_connection(
5
+ :adapter => 'sqlite3',
6
+ :database => ':memory:'
7
+ )
8
+
9
+ ActiveRecord::Schema.define(:version => 1) do
10
+ create_table "pigs", :force => true do |t|
11
+ t.integer "pen_id"
12
+ t.string "name"
13
+ t.boolean "smells"
14
+ end
15
+
16
+ create_table "pens", :force => true do |t|
17
+ t.string "location"
18
+ end
19
+ end
20
+ end
@@ -1,36 +1,38 @@
1
- require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
1
+ require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
2
2
 
3
- describe Oink::OinkInstanceTypeCounterInstanceMethods do
4
- before :each do
3
+ describe Oink::Instrumentation::ActiveRecord do
4
+ before do
5
5
  ActiveRecord::Base.reset_instance_type_count
6
+ Pig.delete_all
7
+ Pen.delete_all
6
8
  end
7
-
9
+
8
10
  describe "hash" do
9
11
  it "should not count objects not instantiated" do
10
12
  ActiveRecord::Base.instantiated_hash["Pig"].should == nil
11
13
  end
12
-
14
+
13
15
  it "should include the objects instantiated" do
14
16
  Pig.create(:name => "Babe")
15
17
  Pig.first
16
18
  ActiveRecord::Base.instantiated_hash["Pig"].should == 2
17
19
  end
18
-
20
+
19
21
  it "should count instantiations for multiple classes" do
20
22
  Pig.create(:name => "Babe")
21
23
  Pen.create(:location => "Backyard")
22
24
  Pig.first
23
25
  ActiveRecord::Base.instantiated_hash["Pen"].should == 1
24
26
  end
25
-
27
+
26
28
  it "should report the total number of objects instantiated" do
27
29
  Pig.create(:name => "Babe")
28
30
  Pen.create(:location => "Backyard")
29
31
  Pig.first
30
32
  ActiveRecord::Base.total_objects_instantiated.should == 3
31
- end
33
+ end
32
34
  end
33
-
35
+
34
36
  describe "reset" do
35
37
  it "should reset the total count" do
36
38
  Pig.create(:name => "Babe")
@@ -0,0 +1,84 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
2
+
3
+ module Oink
4
+ module Instrumentation
5
+
6
+ describe StatmMemorySnapshot do
7
+
8
+ before do
9
+ StatmMemorySnapshot.unset_statm_page_size
10
+ end
11
+
12
+ it "returns memory when pagesize is 4096" do
13
+ pages = 6271
14
+ statm_file = "#{pages} 1157 411 1 0 763 0\n"
15
+ File.should_receive(:read).with("/proc/self/statm").and_return(statm_file)
16
+
17
+ system_call = mock(SystemCall, :stdout => "4096\n", :success? => true)
18
+ SystemCall.should_receive(:execute).with('getconf PAGESIZE').and_return(system_call)
19
+ StatmMemorySnapshot.new.memory.should == (pages * 4)
20
+ end
21
+
22
+ it "falls back to a 4096 if getconf PAGESIZE is not available" do
23
+ pages = 6271
24
+ statm_file = "#{pages} 1157 411 1 0 763 0\n"
25
+ File.should_receive(:read).with("/proc/self/statm").and_return(statm_file)
26
+ system_call = mock(SystemCall, :stdout => "", :success? => false)
27
+ SystemCall.should_receive(:execute).with('getconf PAGESIZE').and_return(system_call)
28
+ StatmMemorySnapshot.new.memory.should == (pages * 4)
29
+ end
30
+ end
31
+
32
+ describe SmapsMemorySnapshot do
33
+
34
+ it "returns a sum of the sizes in the /proc/$$/smaps file" do
35
+ proc_file = <<-STR
36
+ Header
37
+
38
+ Size: 25
39
+ Size: 13 trailing
40
+
41
+ leading Size: 4
42
+
43
+ Footer
44
+
45
+ STR
46
+ File.should_receive(:new).with("/proc/#{$$}/smaps").and_return(proc_file)
47
+ SmapsMemorySnapshot.new.memory.should == 42
48
+ end
49
+
50
+ end
51
+
52
+ describe ProcessStatusMemorySnapshot do
53
+ it "returns the result of a PS command" do
54
+ system_call = mock(SystemCall, :stdout => "915")
55
+ SystemCall.should_receive(:execute).with("ps -o vsz= -p #{$$}").and_return(system_call)
56
+ ProcessStatusMemorySnapshot.new.memory.should == 915
57
+ end
58
+
59
+ describe "#available?" do
60
+ it "returns true if ps succeeds" do
61
+ system_call = mock(SystemCall, :success? => true)
62
+ SystemCall.should_receive(:execute).with("ps -o vsz= -p #{$$}").and_return(system_call)
63
+ ProcessStatusMemorySnapshot.available?.should be_true
64
+ end
65
+ end
66
+ end
67
+
68
+ describe MemorySnapshot do
69
+ describe "#memory_snapshot_class" do
70
+ it "raises an Oink::MemoryDataUnavailableError if not strategies can be found" do
71
+ [WindowsMemorySnapshot, StatmMemorySnapshot, SmapsMemorySnapshot, ProcessStatusMemorySnapshot].each { |klass| klass.stub(:available? => false) }
72
+
73
+ lambda { MemorySnapshot.memory_snapshot_class }.should raise_error(MemoryDataUnavailableError)
74
+ end
75
+
76
+ it "returns the first available memory snapshot strategy" do
77
+ [WindowsMemorySnapshot, SmapsMemorySnapshot, ProcessStatusMemorySnapshot].each { |klass| klass.stub(:available? => false) }
78
+ StatmMemorySnapshot.stub(:available? => true)
79
+ MemorySnapshot.memory_snapshot_class.should == StatmMemorySnapshot
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,73 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
2
+ require "oink/middleware"
3
+ require 'rack/test'
4
+
5
+ describe Oink::Middleware do
6
+ include Rack::Test::Methods
7
+
8
+ class SampleApplication
9
+ def call(env)
10
+ case env['PATH_INFO']
11
+ when "/no_pigs"
12
+ when "/two_pigs"
13
+ Pig.create(:name => "Babe")
14
+ Pig.first
15
+ when "/two_pigs_in_a_pen"
16
+ Pig.create(:name => "Babe")
17
+ Pen.create(:location => "Backyard")
18
+ Pig.first
19
+ end
20
+ [200, {}, ""]
21
+ end
22
+ end
23
+
24
+ let(:app) { Oink::Middleware.new(SampleApplication.new) }
25
+
26
+ before do
27
+ @log_output = StringIO.new
28
+ Hodel3000CompliantLogger.stub(:new => Hodel3000CompliantLogger.new(@log_output))
29
+ Oink::Instrumentation::MemorySnapshot.stub(:memory => 4092)
30
+ Pig.delete_all
31
+ Pen.delete_all
32
+ end
33
+
34
+
35
+ context "support legacy rails log format in transition to oink's own log format" do
36
+ it "writes rails[pid] to the log even if the app isn't a rails app (for now)" do
37
+ get "/no_pigs"
38
+ @log_output.string.should include("rails[#{$$}]")
39
+ end
40
+
41
+ it "writes 'Completed in' after the request has completed" do
42
+ get "/no_pigs"
43
+ @log_output.string.should include("Completed in")
44
+ end
45
+
46
+ it "logs the action and controller" do
47
+ get "/no_pigs", {}, {'action_dispatch.request.parameters' => {'controller' => 'oinkoink', 'action' => 'piggie'}}
48
+ @log_output.string.should include("Processing oinkoink#piggie")
49
+ end
50
+ end
51
+
52
+ it "reports 0 totals" do
53
+ get "/no_pigs"
54
+ @log_output.string.should include("Instantiation Breakdown: Total: 0")
55
+ end
56
+
57
+ it "reports totals first even if it's a tie" do
58
+ get "/two_pigs"
59
+ @log_output.string.should include("Instantiation Breakdown: Total: 2 | Pig: 2")
60
+ end
61
+
62
+ it "reports pigs and pens instantiated" do
63
+ get "/two_pigs_in_a_pen"
64
+ @log_output.string.should include("Instantiation Breakdown: Total: 3 | Pig: 2 | Pen: 1")
65
+ end
66
+
67
+ it "logs memory usage" do
68
+ Oink::Instrumentation::MemorySnapshot.should_receive(:memory).and_return(4092)
69
+ get "/two_pigs_in_a_pen"
70
+ @log_output.string.should include("Memory usage: 4092 | PID: #{$$}")
71
+ end
72
+
73
+ end
@@ -0,0 +1,52 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
2
+
3
+ class ARCountApplicationController < FakeApplicationController
4
+ include Oink::InstanceTypeCounter
5
+
6
+ def no_pigs
7
+ run_around_filters
8
+ end
9
+
10
+ def two_pigs_in_a_pen
11
+ Pig.create!
12
+ Pig.create!
13
+ Pen.create!
14
+ run_around_filters
15
+ end
16
+
17
+ def two_pigs
18
+ Pig.create!
19
+ Pig.create!
20
+ run_around_filters
21
+ end
22
+
23
+ end
24
+
25
+ describe Oink::InstanceTypeCounter do
26
+
27
+ before do
28
+ Pig.delete_all
29
+ Pen.delete_all
30
+ end
31
+
32
+ let(:log_output) { StringIO.new }
33
+ let(:logger) { Logger.new(log_output) }
34
+
35
+ it "reports no AR objects instantiated" do
36
+ controller = ARCountApplicationController.new(logger)
37
+ controller.no_pigs
38
+ log_output.string.should include("Instantiation Breakdown: Total: 0")
39
+ end
40
+
41
+ it "reports AR objects instantiated by type" do
42
+ controller = ARCountApplicationController.new(logger)
43
+ controller.two_pigs_in_a_pen
44
+ log_output.string.should include("Instantiation Breakdown: Total: 3 | Pig: 2 | Pen: 1")
45
+ end
46
+
47
+ it "reports totals first even if its a tie" do
48
+ controller = ARCountApplicationController.new(logger)
49
+ controller.two_pigs
50
+ log_output.string.should include("Instantiation Breakdown: Total: 2 | Pig: 2")
51
+ end
52
+ end
@@ -0,0 +1,23 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
2
+
3
+ class MemoryLoggerApplicationController < FakeApplicationController
4
+ include Oink::MemoryUsageLogger
5
+ end
6
+
7
+ describe Oink::MemoryUsageLogger do
8
+ it "should return memory usage info from the snapshot" do
9
+ Oink::Instrumentation::MemorySnapshot.should_receive("memory").and_return(42)
10
+ log_output = StringIO.new
11
+ controller = MemoryLoggerApplicationController.new(Logger.new(log_output))
12
+ controller.index
13
+ log_output.string.should include("Memory usage: 42 | PID: #{$$}")
14
+ end
15
+
16
+ it "should log an error message if cannot find a memory snapshot strategy" do
17
+ Oink::Instrumentation::MemorySnapshot.should_receive("memory").and_raise(Oink::Instrumentation::MemoryDataUnavailableError)
18
+ controller = MemoryLoggerApplicationController.new
19
+ lambda {
20
+ controller.index
21
+ }.should_not raise_error
22
+ end
23
+ end
@@ -0,0 +1,193 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
2
+
3
+ module Oink::Reports
4
+ describe ActiveRecordInstantiationReport do
5
+
6
+ describe "short summary with frequent offenders" do
7
+
8
+ it "should report actions which exceed the threshold once" do
9
+ str = <<-STR
10
+ 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]
11
+ Feb 01 01:58:30 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 51 | User: 51
12
+ Feb 01 01:58:31 ey04-s00297 rails[4413]: Completed in
13
+ STR
14
+
15
+ io = StringIO.new(str)
16
+ output = PsuedoOutput.new
17
+ ActiveRecordInstantiationReport.new(io, 50).print(output)
18
+ output.should include("1, Users#show")
19
+ end
20
+
21
+ it "should not report actions which do not exceed the threshold" do
22
+ str = <<-STR
23
+ 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]
24
+ Feb 01 01:58:30 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 50 | User: 50
25
+ Feb 01 01:58:31 ey04-s00297 rails[4413]: Completed in
26
+ STR
27
+
28
+ io = StringIO.new(str)
29
+ output = PsuedoOutput.new
30
+ ActiveRecordInstantiationReport.new(io, 50).print(output)
31
+ output.should_not include("1, Users#show")
32
+ end
33
+
34
+ it "should report actions which exceed the threshold multiple times" do
35
+ str = <<-STR
36
+ 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]
37
+ Feb 01 01:58:30 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 51 | User: 51
38
+ Feb 01 01:58:31 ey04-s00297 rails[4413]: Completed in
39
+ 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]
40
+ Feb 01 01:58:30 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 51 | User: 51
41
+ Feb 01 01:58:31 ey04-s00297 rails[4413]: Completed in
42
+ STR
43
+
44
+ io = StringIO.new(str)
45
+ output = PsuedoOutput.new
46
+ ActiveRecordInstantiationReport.new(io, 50).print(output)
47
+ output.should include("2, Users#show")
48
+ end
49
+
50
+ it "should order actions by most exceeded" do
51
+ str = <<-STR
52
+ 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]
53
+ Feb 01 01:58:30 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 51 | User: 51
54
+ Feb 01 01:58:31 ey04-s00297 rails[4413]: Completed in
55
+ 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]
56
+ Feb 01 01:58:30 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 51 | User: 51
57
+ Feb 01 01:58:31 ey04-s00297 rails[4413]: Completed in
58
+ 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]
59
+ Feb 01 01:58:30 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 51 | User: 51
60
+ Feb 01 01:58:31 ey04-s00297 rails[4413]: Completed in
61
+ STR
62
+
63
+ io = StringIO.new(str)
64
+ output = PsuedoOutput.new
65
+ ActiveRecordInstantiationReport.new(io, 50).print(output)
66
+ output[-2].should == "2, Media#show"
67
+ output[-1].should == "1, Users#show"
68
+ end
69
+
70
+ it "should not be bothered by incomplete requests" do
71
+ str = <<-STR
72
+ 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]
73
+ Feb 01 01:58:30 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 24 | User: 24
74
+ Feb 01 01:58:31 ey04-s00297 rails[4413]: Completed in
75
+ 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]
76
+ 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]
77
+ Feb 01 01:58:30 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 51 | User: 51
78
+ Feb 01 01:58:31 ey04-s00297 rails[4413]: Completed in
79
+ STR
80
+
81
+ io = StringIO.new(str)
82
+ output = PsuedoOutput.new
83
+ ActiveRecordInstantiationReport.new(io, 50).print(output)
84
+ output.should include("1, Users#show")
85
+ end
86
+
87
+ end
88
+
89
+ describe "summary with top 10 offenses" do
90
+
91
+ it "should only report requests over threshold" do
92
+ str = <<-STR
93
+ 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]
94
+ Feb 01 01:58:30 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 51 | User: 51
95
+ Feb 01 01:58:31 ey04-s00297 rails[4413]: Completed in
96
+ STR
97
+
98
+ io = StringIO.new(str)
99
+ output = PsuedoOutput.new
100
+ ActiveRecordInstantiationReport.new(io, 50).print(output)
101
+ output.should include("1. Feb 01 01:58:31, 51, Users#show")
102
+ end
103
+
104
+ it "should not include requests which are not over threshold" do
105
+ str = <<-STR
106
+ 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]
107
+ Feb 01 01:58:30 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 50 | User: 50
108
+ Feb 01 01:58:31 ey04-s00297 rails[4413]: Completed in
109
+ STR
110
+
111
+ io = StringIO.new(str)
112
+ output = PsuedoOutput.new
113
+ ActiveRecordInstantiationReport.new(io, 50).print(output)
114
+ output.should_not include("1. Feb 01 01:58:31, 50, Users#show")
115
+ end
116
+
117
+ it "should order offenses from biggest to smallest" do
118
+ str = <<-STR
119
+ 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]
120
+ Feb 01 01:58:30 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 75 | User: 75
121
+ Feb 01 01:58:31 ey04-s00297 rails[4413]: Completed in
122
+ 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]
123
+ Feb 01 01:58:33 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 100 | User: 100
124
+ Feb 01 01:58:34 ey04-s00297 rails[4413]: Completed in
125
+ STR
126
+
127
+ io = StringIO.new(str)
128
+ output = PsuedoOutput.new
129
+ ActiveRecordInstantiationReport.new(io, 50).print(output)
130
+ output[4].should == "1. Feb 01 01:58:34, 100, MediaController#show"
131
+ output[5].should == "2. Feb 01 01:58:31, 75, DetailsController#show"
132
+ end
133
+
134
+ end
135
+
136
+ describe "verbose format" do
137
+ it "should print the full lines of actions exceeding the threshold" do
138
+ str = <<-STR
139
+ 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]
140
+ Feb 01 01:58:33 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 100 | User: 100
141
+ Feb 01 01:58:34 ey04-s00297 rails[4413]: Completed in
142
+ STR
143
+ io = StringIO.new(str)
144
+ output = PsuedoOutput.new
145
+ ActiveRecordInstantiationReport.new(io, 50, :format => :verbose).print(output)
146
+ output[3..5].should == str.split("\n")[0..2].map { |o| o.strip }
147
+ end
148
+
149
+ it "should handle actions which do not complete properly" do
150
+ str = <<-STR
151
+ 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]
152
+ Feb 01 01:58:30 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 24 | User: 24
153
+ Feb 01 01:58:31 ey04-s00297 rails[4413]: Completed in
154
+ 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]
155
+ 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]
156
+ Feb 01 01:58:30 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 51 | User: 51
157
+ Feb 01 01:58:31 ey04-s00297 rails[4413]: Completed in
158
+ STR
159
+
160
+ io = StringIO.new(str)
161
+ output = PsuedoOutput.new
162
+ ActiveRecordInstantiationReport.new(io, 50, :format => :verbose).print(output)
163
+ output[3..5].should == str.split("\n")[4..6].map { |o| o.strip }
164
+ end
165
+ end
166
+
167
+ describe "multiple io streams" do
168
+ it "should accept multiple files" do
169
+
170
+ str1 = <<-STR
171
+ 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]
172
+ Feb 01 01:58:33 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 100 | User: 100
173
+ Feb 01 01:58:34 ey04-s00297 rails[4413]: Completed in
174
+ STR
175
+
176
+ str2 = <<-STR
177
+ 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]
178
+ Feb 01 01:58:33 ey04-s00297 rails[4413]: Instantiation Breakdown: Total: 100 | User: 100
179
+ Feb 01 01:58:34 ey04-s00297 rails[4413]: Completed in
180
+ STR
181
+
182
+ io1 = StringIO.new(str1)
183
+ io2 = StringIO.new(str2)
184
+ output = PsuedoOutput.new
185
+ ActiveRecordInstantiationReport.new([io1, io2], 50).print(output)
186
+ output.should include("2, MediaController#show")
187
+ end
188
+
189
+ end
190
+
191
+
192
+ end
193
+ end