system-metrics 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +16 -1
- data/app/views/layouts/system_metrics/metrics.html.erb +4 -15
- data/app/views/system_metrics/metrics/_menu.html.erb +1 -1
- data/app/views/system_metrics/metrics/admin.html.erb +1 -1
- data/lib/system_metrics/engine.rb +3 -3
- data/lib/system_metrics/instrument/base.rb +1 -1
- data/lib/system_metrics/nested_event.rb +8 -1
- data/lib/system_metrics/store.rb +10 -15
- data/lib/system_metrics/version.rb +1 -1
- data/public/images/gradient.png +0 -0
- data/public/stylesheets/app.css +197 -3
- data/spec/spec_helper.rb +2 -0
- data/spec/support/db_setup.rb +3 -0
- data/spec/support/mock_app.rb +1 -3
- data/spec/support/notifications_support.rb +10 -0
- data/spec/system_metrics/collector_spec.rb +1 -2
- data/spec/system_metrics/config_spec.rb +16 -8
- data/spec/system_metrics/engine_spec.rb +53 -28
- data/spec/system_metrics/instrument/action_controller_spec.rb +51 -0
- data/spec/system_metrics/instrument/action_mailer_spec.rb +40 -0
- data/spec/system_metrics/instrument/action_view_spec.rb +40 -0
- data/spec/system_metrics/instrument/active_record_spec.rb +50 -0
- data/spec/system_metrics/instrument/base_spec.rb +38 -0
- data/spec/system_metrics/instrument/rack_spec.rb +28 -0
- data/spec/system_metrics/middleware_spec.rb +1 -3
- data/spec/system_metrics/nested_event_spec.rb +87 -0
- data/spec/system_metrics/store_spec.rb +49 -0
- data/spec/system_metrics_spec.rb +0 -1
- data/system-metrics.gemspec +1 -0
- metadata +30 -11
- data/public/stylesheets/base.css +0 -46
- data/public/stylesheets/footer.css +0 -6
- data/public/stylesheets/graphs.css +0 -9
- data/public/stylesheets/header.css +0 -52
- data/public/stylesheets/menu_bar.css +0 -7
- data/public/stylesheets/metric.css +0 -19
- data/public/stylesheets/payload.css +0 -4
- data/public/stylesheets/portlet.css +0 -11
- data/public/stylesheets/title_bar.css +0 -29
@@ -1,24 +1,32 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
-
require 'system_metrics/config'
|
3
2
|
|
4
3
|
describe SystemMetrics::Config do
|
5
|
-
it 'should be valid
|
6
|
-
config = SystemMetrics::Config.new
|
4
|
+
it 'should be valid by default' do
|
5
|
+
config = SystemMetrics::Config.new
|
7
6
|
config.should be_valid
|
8
7
|
end
|
9
8
|
|
10
|
-
it 'should be invalid
|
11
|
-
config = SystemMetrics::Config.new
|
9
|
+
it 'should be invalid with nil instruments' do
|
10
|
+
config = SystemMetrics::Config.new
|
11
|
+
config.instruments = nil
|
12
12
|
config.should_not be_valid
|
13
13
|
end
|
14
14
|
|
15
15
|
it 'should be invalid without a store' do
|
16
|
-
config = SystemMetrics::Config.new
|
16
|
+
config = SystemMetrics::Config.new
|
17
|
+
config.store = nil
|
17
18
|
config.should_not be_valid
|
18
19
|
end
|
19
20
|
|
20
|
-
it 'should be invalid
|
21
|
-
config = SystemMetrics::Config.new
|
21
|
+
it 'should be invalid with a nil path_exclude_patterns' do
|
22
|
+
config = SystemMetrics::Config.new
|
23
|
+
config.path_exclude_patterns = nil
|
24
|
+
config.should_not be_valid
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should be invalid with a nil notification_exclude_patterns' do
|
28
|
+
config = SystemMetrics::Config.new
|
29
|
+
config.notification_exclude_patterns = nil
|
22
30
|
config.should_not be_valid
|
23
31
|
end
|
24
32
|
end
|
@@ -1,50 +1,75 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
-
require 'system_metrics/engine'
|
3
2
|
|
4
3
|
describe SystemMetrics::Engine do
|
5
4
|
before(:each) do
|
6
5
|
@app = MockApp.new
|
7
6
|
@store = TestStore.new
|
8
|
-
@app.config.system_metrics
|
9
|
-
@app.config.system_metrics
|
7
|
+
@app.config.system_metrics = SystemMetrics::Config.new
|
8
|
+
@app.config.system_metrics.instruments << SystemMetrics::Instrument::Base.new(/xyz123/)
|
9
|
+
@app.config.system_metrics.store = @store
|
10
|
+
@engine = SystemMetrics::Engine.new
|
11
|
+
run_initializers(@engine)
|
10
12
|
end
|
11
13
|
|
12
|
-
it 'should
|
13
|
-
@
|
14
|
-
engine
|
15
|
-
|
16
|
-
|
17
|
-
collector = SystemMetrics::Collector.new(@store)
|
18
|
-
collector.collect do
|
19
|
-
ActiveSupport::Notifications.instrument 'sql.active_record'
|
20
|
-
ActiveSupport::Notifications.instrument 'render.action_view'
|
21
|
-
ActiveSupport::Notifications.instrument 'process.action_controller'
|
22
|
-
end
|
23
|
-
|
24
|
-
@store.should have(2).events
|
25
|
-
@store.events.map(&:name) =~ ['sql.active_record', 'render.action_view']
|
14
|
+
it 'should initialize the SystemMetrics configuration' do
|
15
|
+
@engine.smc.should_not be_nil
|
16
|
+
@engine.smc.should be_valid
|
17
|
+
@engine.collector.should_not be_nil
|
26
18
|
end
|
27
19
|
|
28
20
|
it 'should setup the SystemMetrics::Middleware' do
|
29
|
-
engine = SystemMetrics::Engine.new
|
30
|
-
run_initializers(engine)
|
31
|
-
|
32
21
|
middleware = @app.config.middleware.first
|
33
22
|
middleware[0].should == SystemMetrics::Middleware
|
34
23
|
middleware[1].should_not be_nil
|
35
24
|
middleware[2].should_not be_nil
|
36
25
|
end
|
37
26
|
|
38
|
-
|
39
|
-
|
40
|
-
|
27
|
+
describe '#process_event' do
|
28
|
+
it 'should collect events that do not have an instrument that handles them' do
|
29
|
+
event = ActiveSupport::Notifications::Event.new('unknown', Time.now - 5, Time.now, 'tid', {})
|
30
|
+
@engine.collector.collect { @engine.send(:process_event, event) }
|
31
|
+
@store.events.should include(event)
|
41
32
|
end
|
42
|
-
initializer.run @app
|
43
|
-
end
|
44
33
|
|
45
|
-
|
46
|
-
|
47
|
-
|
34
|
+
it 'should collect events that have an instrument that handles and does not ignore them' do
|
35
|
+
event = ActiveSupport::Notifications::Event.new('xyz123', Time.now - 5, Time.now, 'tid', {})
|
36
|
+
@engine.collector.collect { @engine.send(:process_event, event) }
|
37
|
+
@store.events.should include(event)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should not collect events whose instrument indicates that it should be ignored' do
|
41
|
+
class IgnoringInstrument
|
42
|
+
def handles?(event)
|
43
|
+
true
|
44
|
+
end
|
45
|
+
|
46
|
+
def ignore?(event)
|
47
|
+
true
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
@app.config.system_metrics.instruments << IgnoringInstrument.new
|
52
|
+
engine = SystemMetrics::Engine.new
|
53
|
+
run_initializers(engine)
|
54
|
+
event = ActiveSupport::Notifications::Event.new('abc123', Time.now - 5, Time.now, 'tid', {})
|
55
|
+
engine.collector.collect { @engine.send(:process_event, event) }
|
56
|
+
@store.events.should_not include(event)
|
48
57
|
end
|
49
58
|
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def run_initializer(engine, name)
|
63
|
+
initializer = engine.initializers.find do |initializer|
|
64
|
+
initializer.name == name
|
65
|
+
end
|
66
|
+
initializer.run @app
|
67
|
+
end
|
68
|
+
|
69
|
+
def run_initializers(engine)
|
70
|
+
['system_metrics.initialize', 'system_metrics.start_subscriber', 'system_metrics.add_middleware'].each do |name|
|
71
|
+
run_initializer(engine, name)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
50
75
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
|
3
|
+
describe SystemMetrics::Instrument::ActionController do
|
4
|
+
include NotificationsSupport
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@instrument = SystemMetrics::Instrument::ActionController.new
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#handle?' do
|
11
|
+
it 'should handle any event whose name ends with action_controller' do
|
12
|
+
@instrument.handles?(event(:name => 'process_action.action_controller')).should be_true
|
13
|
+
@instrument.handles?(event(:name => 'do_something.action_controller')).should be_true
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should not handle an event whose name does not end with action_controller' do
|
17
|
+
@instrument.handles?(event(:name => 'do_something.else')).should be_false
|
18
|
+
@instrument.handles?(event(:name => 'action_controller.process_action')).should be_false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#ignore?' do
|
23
|
+
it 'should ignore all events unless the name is process_action.action_controller' do
|
24
|
+
@instrument.ignore?(event(:name => 'process_action.action_controller')).should be_false
|
25
|
+
@instrument.ignore?(event(:name => 'start_processing.action_controller')).should be_true
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#prepare' do
|
30
|
+
it 'should add an endpoint entry to the payload' do
|
31
|
+
e = event(:payload => { :controller => 'User', :action => 'create' })
|
32
|
+
@instrument.prepare(e)
|
33
|
+
e.payload.should include(:end_point)
|
34
|
+
e.payload[:end_point].should == 'User#create'
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should remove all payload keys except :path, :method, :params, :db_runtime, :view_runtime, and :end_point' do
|
38
|
+
e = event(:payload => {
|
39
|
+
:controller => 'User',
|
40
|
+
:action => 'create',
|
41
|
+
:path => '/',
|
42
|
+
:method => 'GET',
|
43
|
+
:params => {},
|
44
|
+
:db_runtime => 10,
|
45
|
+
:view_runtime => 10
|
46
|
+
})
|
47
|
+
@instrument.prepare(e)
|
48
|
+
e.payload.keys.should =~ [:path, :method, :params, :db_runtime, :view_runtime, :end_point]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
|
3
|
+
describe SystemMetrics::Instrument::ActionMailer do
|
4
|
+
include NotificationsSupport
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@instrument = SystemMetrics::Instrument::ActionMailer.new
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#handle?' do
|
11
|
+
it 'should handle any event whose name ends with action_mailer' do
|
12
|
+
@instrument.handles?(event(:name => 'recieve.action_mailer')).should be_true
|
13
|
+
@instrument.handles?(event(:name => 'send.action_mailer')).should be_true
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should not handle an event whose name does not end with action_mailer' do
|
17
|
+
@instrument.handles?(event(:name => 'do_something.else')).should be_false
|
18
|
+
@instrument.handles?(event(:name => 'action_mailer.process_action')).should be_false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#ignore?' do
|
23
|
+
it 'should always return false' do
|
24
|
+
@instrument.ignore?(event(:name => 'process_action.action_mailer')).should be_false
|
25
|
+
@instrument.ignore?(event(:name => 'start_processing.action_controller')).should be_false
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#prepare' do
|
30
|
+
it 'should should keep all payload attributes except :mail' do
|
31
|
+
e = event(:payload => {
|
32
|
+
:controller => 'User',
|
33
|
+
:action => 'create',
|
34
|
+
:mail => 'big long message'
|
35
|
+
})
|
36
|
+
@instrument.prepare(e)
|
37
|
+
e.payload.keys.should =~ [:controller, :action]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
|
3
|
+
describe SystemMetrics::Instrument::ActionView do
|
4
|
+
include NotificationsSupport
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@instrument = SystemMetrics::Instrument::ActionView.new
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#handle?' do
|
11
|
+
it 'should handle any event whose name ends with action_view' do
|
12
|
+
@instrument.handles?(event(:name => 'recieve.action_view')).should be_true
|
13
|
+
@instrument.handles?(event(:name => 'send.action_view')).should be_true
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should not handle an event whose name does not end with action_view' do
|
17
|
+
@instrument.handles?(event(:name => 'do_something.else')).should be_false
|
18
|
+
@instrument.handles?(event(:name => 'action_view.process_action')).should be_false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#ignore?' do
|
23
|
+
it 'should always return false' do
|
24
|
+
@instrument.ignore?(event(:name => 'process_action.action_view')).should be_false
|
25
|
+
@instrument.ignore?(event(:name => 'start_processing.action_controller')).should be_false
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#prepare' do
|
30
|
+
it 'should try to replace any paths in payload values' do
|
31
|
+
@instrument.mapped_paths['/abc123'] = 'A'
|
32
|
+
e = event(:payload => {
|
33
|
+
:path => '/abc123/more/path',
|
34
|
+
:action => 'create'
|
35
|
+
})
|
36
|
+
@instrument.prepare(e)
|
37
|
+
e.payload.should == { :path => 'A/more/path', :action => 'create' }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
|
3
|
+
describe SystemMetrics::Instrument::ActiveRecord do
|
4
|
+
include NotificationsSupport
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@instrument = SystemMetrics::Instrument::ActiveRecord.new
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#handle?' do
|
11
|
+
it 'should handle any event whose name ends with active_record' do
|
12
|
+
@instrument.handles?(event(:name => 'sql.active_record')).should be_true
|
13
|
+
@instrument.handles?(event(:name => 'arel.active_record')).should be_true
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should not handle an event whose name does not end with active_record' do
|
17
|
+
@instrument.handles?(event(:name => 'do_something.else')).should be_false
|
18
|
+
@instrument.handles?(event(:name => 'active_record.sql')).should be_false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#ignore?' do
|
23
|
+
it 'should ignore all events whose payload[:sql] does not begin with SELECT, INSERT, UPDATE, or DELETE' do
|
24
|
+
e = event(:name => 'sql.active_record', :payload => { :sql => 'SELECT * from users' })
|
25
|
+
@instrument.ignore?(e).should be_false
|
26
|
+
e = event(:name => 'sql.active_record', :payload => { :sql => 'INSERT into users' })
|
27
|
+
@instrument.ignore?(e).should be_false
|
28
|
+
e = event(:name => 'sql.active_record', :payload => { :sql => 'UPDATE users' })
|
29
|
+
@instrument.ignore?(e).should be_false
|
30
|
+
e = event(:name => 'sql.active_record', :payload => { :sql => 'DELETE from users' })
|
31
|
+
@instrument.ignore?(e).should be_false
|
32
|
+
e = event(:name => 'sql.active_record', :payload => { :sql => 'DESCRIBE users' })
|
33
|
+
@instrument.ignore?(e).should be_true
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#prepare' do
|
38
|
+
it 'should replace all runs of multiple spaces and newlines in the payload[:sql] with a single space' do
|
39
|
+
e = event(:name => 'sql.active_record', :payload => { :sql => 'SELECT * from users' })
|
40
|
+
@instrument.prepare(e)
|
41
|
+
e.payload[:sql].should == 'SELECT * from users'
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should remove the :connection_id from the payload' do
|
45
|
+
e = event(:name => 'sql.active_record', :payload => { :sql => 'SELECT * from users', :connection_id => 27 })
|
46
|
+
@instrument.prepare(e)
|
47
|
+
e.payload.should_not include(:connection_id)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
|
3
|
+
describe SystemMetrics::Instrument::Base do
|
4
|
+
include NotificationsSupport
|
5
|
+
|
6
|
+
describe '#handle?' do
|
7
|
+
it 'should handle any event whose name matches the pattern passed to the constructor' do
|
8
|
+
instrument = SystemMetrics::Instrument::Base.new(/action_mailer$/)
|
9
|
+
instrument.handles?(event(:name => 'recieve.action_mailer')).should be_true
|
10
|
+
instrument = SystemMetrics::Instrument::Base.new(/action_controller$/)
|
11
|
+
instrument.handles?(event(:name => 'process_action.action_controller')).should be_true
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should not handle an event whose name does not match the pattern passed to the constructor' do
|
15
|
+
instrument = SystemMetrics::Instrument::Base.new(/action_mailer$/)
|
16
|
+
instrument.handles?(event(:name => 'action_mailer.receive')).should be_false
|
17
|
+
instrument = SystemMetrics::Instrument::Base.new(/action_controller$/)
|
18
|
+
instrument.handles?(event(:name => 'action_controller.go')).should be_false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#ignore?' do
|
23
|
+
it 'should always return false' do
|
24
|
+
instrument = SystemMetrics::Instrument::Base.new(/action_mailer$/)
|
25
|
+
instrument.ignore?(event(:name => 'process_action.action_mailer')).should be_false
|
26
|
+
instrument.ignore?(event(:name => 'start_processing.action_controller')).should be_false
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '#prune_path' do
|
31
|
+
it 'should allow path elements to be replaced' do
|
32
|
+
instrument = SystemMetrics::Instrument::Base.new(/action_mailer$/)
|
33
|
+
instrument.mapped_paths['/abc123'] = 'A'
|
34
|
+
instrument.prune_path('/abc123/more/path').should == 'A/more/path'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper'
|
2
|
+
|
3
|
+
describe SystemMetrics::Instrument::Rack do
|
4
|
+
include NotificationsSupport
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
@instrument = SystemMetrics::Instrument::Rack.new
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '#handle?' do
|
11
|
+
it 'should handle any event whose name is request.rack' do
|
12
|
+
@instrument.handles?(event(:name => 'request.rack')).should be_true
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should not handle an event whose name is not request.rack' do
|
16
|
+
@instrument.handles?(event(:name => 'response.rack')).should be_false
|
17
|
+
@instrument.handles?(event(:name => 'view.rack')).should be_false
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#ignore?' do
|
22
|
+
it 'should always return false' do
|
23
|
+
@instrument.ignore?(event(:name => 'request.rack')).should be_false
|
24
|
+
@instrument.ignore?(event(:name => 'start_processing.action_controller')).should be_false
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -1,6 +1,4 @@
|
|
1
1
|
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
-
require 'system_metrics/middleware'
|
3
|
-
require 'system_metrics/collector'
|
4
2
|
|
5
3
|
describe SystemMetrics::Middleware do
|
6
4
|
before(:each) do
|
@@ -8,7 +6,7 @@ describe SystemMetrics::Middleware do
|
|
8
6
|
@collector = SystemMetrics::Collector.new(@store)
|
9
7
|
end
|
10
8
|
|
11
|
-
it 'should invoke the collector for
|
9
|
+
it 'should invoke the collector for non-excluded paths' do
|
12
10
|
event = Object.new
|
13
11
|
blk = Proc.new { @collector.collect_event(event) }
|
14
12
|
middleware = SystemMetrics::Middleware.new(blk, @collector, [])
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe SystemMetrics::NestedEvent do
|
4
|
+
it "should provide a reader for started_at that pulls directly from the event's time property" do
|
5
|
+
time = Time.now
|
6
|
+
e = event(:start => time)
|
7
|
+
e.started_at.should == time
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should provide a reader for ended_at that pulls directly from the event's end property" do
|
11
|
+
time = Time.now
|
12
|
+
e = event(:end => time)
|
13
|
+
e.ended_at.should == time
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should contain child events' do
|
17
|
+
e = event
|
18
|
+
e.children << event()
|
19
|
+
e.should have(1).child
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '.arrange' do
|
23
|
+
it 'should arrange an array of events in a nested structure' do
|
24
|
+
parent = event(:start => Time.now - 10.seconds, :end => Time.now)
|
25
|
+
child = event(:start => Time.now - 9.seconds, :end => Time.now - 1.seconds)
|
26
|
+
grandchild = event(:start => Time.now - 8.seconds, :end => Time.now - 2.seconds)
|
27
|
+
|
28
|
+
root = SystemMetrics::NestedEvent.arrange([grandchild, child, parent])
|
29
|
+
root.should have(1).child
|
30
|
+
root.children[0].should == child
|
31
|
+
root.children[0].should have(1).child
|
32
|
+
root.children[0].children[0].should == grandchild
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#parent_of?' do
|
37
|
+
it 'should be a parent of another event if its start and end times contain the target event' do
|
38
|
+
parent = event(:start => Time.now - 10.seconds, :end => Time.now)
|
39
|
+
child = event(:start => Time.now - 6.seconds, :end => Time.now - 3.seconds)
|
40
|
+
parent.parent_of?(child).should be_true
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#child_of?' do
|
45
|
+
it 'should be a child of another event if its start and end times are within the parent event' do
|
46
|
+
parent = event(:start => Time.now - 10.seconds, :end => Time.now)
|
47
|
+
child = event(:start => Time.now - 6.seconds, :end => Time.now - 3.seconds)
|
48
|
+
child.child_of?(parent).should be_true
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe '#exclusive_duration' do
|
53
|
+
it 'should calculate the time spent within an event minus all the time spent in child events' do
|
54
|
+
now = Time.now
|
55
|
+
parent = event(:start => now - 10.seconds, :end => now)
|
56
|
+
child = event(:start => now - 9.seconds, :end => now - 1.seconds)
|
57
|
+
grandchild = event(:start => now - 8.seconds, :end => now - 2.seconds)
|
58
|
+
root = SystemMetrics::NestedEvent.arrange([grandchild, child, parent])
|
59
|
+
root.exclusive_duration.should be_within(100).of(2000)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe '#to_hash' do
|
64
|
+
it 'should return a hash with keys for :name, :action, :category, :started_at, :transaction_id, :payload, :duration, and :exclusive_duration' do
|
65
|
+
e = event
|
66
|
+
hash = event.to_hash
|
67
|
+
hash[:name].should == e.name
|
68
|
+
hash[:started_at].should be_within(1).of(e.started_at)
|
69
|
+
hash[:transaction_id].should == e.transaction_id
|
70
|
+
hash[:payload].should == e.payload
|
71
|
+
hash[:duration].should be_within(1).of(e.duration)
|
72
|
+
hash[:exclusive_duration].should be_within(1).of(e.exclusive_duration)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def event(options={})
|
79
|
+
SystemMetrics::NestedEvent.new(
|
80
|
+
options[:name] || 'sql.active_record',
|
81
|
+
options[:start] || (Time.now - 5.seconds),
|
82
|
+
options[:end] || Time.now,
|
83
|
+
options[:transaction_id] || 'tid',
|
84
|
+
options[:payload] || {}
|
85
|
+
)
|
86
|
+
end
|
87
|
+
end
|