system-metrics 0.1.0 → 0.2.0
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.
- 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
|