oink 0.1.2 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +15 -29
- data/Rakefile +4 -6
- data/bin/oink +2 -2
- data/lib/oink.rb +1 -9
- data/lib/oink/cli.rb +71 -67
- data/lib/oink/instrumentation.rb +2 -0
- data/lib/oink/instrumentation/active_record.rb +63 -0
- data/lib/oink/instrumentation/memory_snapshot.rb +119 -0
- data/lib/oink/middleware.rb +48 -0
- data/lib/oink/rails/instance_type_counter.rb +8 -62
- data/lib/oink/rails/memory_usage_logger.rb +11 -33
- data/lib/oink/reports/active_record_instantiation_oinked_request.rb +13 -0
- data/lib/oink/reports/active_record_instantiation_report.rb +67 -0
- data/lib/oink/reports/base.rb +38 -0
- data/lib/oink/reports/memory_oinked_request.rb +13 -0
- data/lib/oink/reports/memory_usage_report.rb +71 -0
- data/lib/oink/reports/priority_queue.rb +41 -0
- data/lib/oink/reports/request.rb +20 -0
- data/lib/oink/utils/hash_utils.rb +9 -0
- data/spec/fakes/fake_application_controller.rb +30 -0
- data/spec/fakes/psuedo_output.rb +7 -0
- data/spec/helpers/database.rb +20 -0
- data/spec/{rails → oink/instrumentation}/instance_type_counter_spec.rb +11 -9
- data/spec/oink/instrumentation/memory_snapshot_spec.rb +84 -0
- data/spec/oink/middleware_spec.rb +73 -0
- data/spec/oink/rails/instance_type_counter_spec.rb +52 -0
- data/spec/oink/rails/memory_usage_logger_spec.rb +23 -0
- data/spec/oink/reports/active_record_instantiation_report_spec.rb +193 -0
- data/spec/oink/reports/memory_usage_report_spec.rb +267 -0
- data/spec/oink/reports/oinked_request_spec.rb +22 -0
- data/spec/oink/reports/priority_queue_spec.rb +74 -0
- data/spec/spec_helper.rb +10 -26
- metadata +158 -29
- data/lib/oink/active_record_instantiation_reporter.rb +0 -68
- data/lib/oink/base.rb +0 -40
- data/lib/oink/memory_usage_reporter.rb +0 -72
- data/lib/oink/oinked_request/oinked_ar_request.rb +0 -9
- data/lib/oink/oinked_request/oinked_memory_request.rb +0 -9
- data/lib/oink/oinked_request/oinked_request.rb +0 -16
- data/lib/oink/priority_queue.rb +0 -37
- data/spec/oink/active_record_instantiation_reporter_spec.rb +0 -191
- data/spec/oink/memory_usage_reporter_spec.rb +0 -265
- data/spec/oinked_request/oinked_request_spec.rb +0 -20
- data/spec/priority_queue/priority_queue_spec.rb +0 -75
- 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,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,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__) + "
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../../spec_helper")
|
2
2
|
|
3
|
-
describe Oink::
|
4
|
-
before
|
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
|