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