newrelic_rpm 2.9.9 → 2.10.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of newrelic_rpm might be problematic. Click here for more details.
- data/CHANGELOG +117 -49
- data/bin/mongrel_rpm +2 -2
- data/install.rb +42 -33
- data/lib/new_relic/agent.rb +149 -39
- data/lib/new_relic/agent/agent.rb +139 -122
- data/lib/new_relic/agent/busy_calculator.rb +91 -0
- data/lib/new_relic/agent/collection_helper.rb +11 -2
- data/lib/new_relic/agent/error_collector.rb +33 -27
- data/lib/new_relic/agent/instrumentation/active_record_instrumentation.rb +30 -26
- data/lib/new_relic/agent/instrumentation/authlogic.rb +8 -0
- data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +316 -105
- data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +22 -0
- data/lib/new_relic/agent/instrumentation/memcache.rb +18 -12
- data/lib/new_relic/agent/instrumentation/merb/errors.rb +2 -1
- data/lib/new_relic/agent/instrumentation/metric_frame.rb +258 -0
- data/lib/new_relic/agent/instrumentation/net.rb +7 -11
- data/lib/new_relic/agent/instrumentation/passenger_instrumentation.rb +1 -1
- data/lib/new_relic/agent/instrumentation/rack.rb +109 -0
- data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +6 -5
- data/lib/new_relic/agent/instrumentation/rails/errors.rb +7 -7
- data/lib/new_relic/agent/instrumentation/sinatra.rb +46 -0
- data/lib/new_relic/agent/method_tracer.rb +305 -150
- data/lib/new_relic/agent/sampler.rb +34 -0
- data/lib/new_relic/agent/samplers/cpu_sampler.rb +11 -1
- data/lib/new_relic/agent/samplers/delayed_job_lock_sampler.rb +37 -0
- data/lib/new_relic/agent/samplers/memory_sampler.rb +22 -10
- data/lib/new_relic/agent/samplers/object_sampler.rb +24 -0
- data/lib/new_relic/agent/shim_agent.rb +10 -0
- data/lib/new_relic/agent/stats_engine.rb +16 -278
- data/lib/new_relic/agent/stats_engine/metric_stats.rb +118 -0
- data/lib/new_relic/agent/stats_engine/samplers.rb +81 -0
- data/lib/new_relic/agent/stats_engine/transactions.rb +149 -0
- data/lib/new_relic/agent/transaction_sampler.rb +73 -67
- data/lib/new_relic/agent/worker_loop.rb +69 -68
- data/lib/new_relic/commands/deployments.rb +4 -6
- data/lib/new_relic/control.rb +121 -60
- data/lib/new_relic/control/external.rb +13 -0
- data/lib/new_relic/control/merb.rb +2 -0
- data/lib/new_relic/control/rails.rb +16 -6
- data/lib/new_relic/control/ruby.rb +8 -5
- data/lib/new_relic/control/sinatra.rb +18 -0
- data/lib/new_relic/delayed_job_injection.rb +25 -0
- data/lib/new_relic/histogram.rb +89 -0
- data/lib/new_relic/local_environment.rb +64 -30
- data/lib/new_relic/metric_data.rb +15 -6
- data/lib/new_relic/metric_parser.rb +14 -1
- data/lib/new_relic/metric_parser/active_record.rb +14 -0
- data/lib/new_relic/metric_parser/controller.rb +5 -2
- data/lib/new_relic/metric_parser/external.rb +50 -0
- data/lib/new_relic/metric_parser/other_transaction.rb +15 -0
- data/lib/new_relic/metric_parser/web_frontend.rb +14 -0
- data/lib/new_relic/metric_spec.rb +39 -20
- data/lib/new_relic/metrics.rb +9 -7
- data/lib/new_relic/noticed_error.rb +6 -8
- data/lib/new_relic/rack/metric_app.rb +5 -4
- data/lib/new_relic/rack/{newrelic.ru → mongrel_rpm.ru} +4 -4
- data/lib/new_relic/rack/newrelic.yml +1 -0
- data/lib/new_relic/{rack.rb → rack_app.rb} +0 -0
- data/lib/new_relic/recipes.rb +1 -1
- data/lib/new_relic/stats.rb +40 -26
- data/lib/new_relic/transaction_analysis.rb +5 -2
- data/lib/new_relic/transaction_sample.rb +134 -55
- data/lib/new_relic/version.rb +27 -20
- data/lib/new_relic_api.rb +67 -47
- data/lib/newrelic_rpm.rb +5 -5
- data/lib/tasks/tests.rake +2 -0
- data/newrelic.yml +69 -29
- data/test/active_record_fixtures.rb +2 -2
- data/test/config/newrelic.yml +4 -7
- data/test/config/test_control.rb +1 -2
- data/test/new_relic/agent/active_record_instrumentation_test.rb +115 -31
- data/test/new_relic/agent/agent_controller_test.rb +274 -0
- data/test/new_relic/agent/agent_test_controller.rb +42 -6
- data/test/new_relic/agent/busy_calculator_test.rb +79 -0
- data/test/new_relic/agent/collection_helper_test.rb +10 -3
- data/test/new_relic/agent/error_collector_test.rb +35 -17
- data/test/new_relic/agent/method_tracer_test.rb +60 -20
- data/test/new_relic/agent/metric_data_test.rb +2 -2
- data/test/new_relic/agent/metric_frame_test.rb +51 -0
- data/test/new_relic/agent/net_instrumentation_test.rb +77 -0
- data/test/new_relic/agent/{agent_test.rb → rpm_agent_test.rb} +26 -5
- data/test/new_relic/agent/stats_engine/metric_stats_test.rb +79 -0
- data/test/new_relic/{samplers_test.rb → agent/stats_engine/samplers_test.rb} +23 -22
- data/test/new_relic/agent/{stats_engine_test.rb → stats_engine/stats_engine_test.rb} +19 -101
- data/test/new_relic/agent/task_instrumentation_test.rb +176 -0
- data/test/new_relic/agent/transaction_sample_builder_test.rb +2 -2
- data/test/new_relic/agent/transaction_sample_test.rb +53 -38
- data/test/new_relic/agent/transaction_sampler_test.rb +101 -33
- data/test/new_relic/agent/worker_loop_test.rb +16 -14
- data/test/new_relic/control_test.rb +26 -13
- data/test/new_relic/metric_parser_test.rb +31 -1
- data/test/new_relic/metric_spec_test.rb +2 -2
- data/test/new_relic/stats_test.rb +0 -8
- data/test/new_relic/version_number_test.rb +31 -1
- data/test/test_helper.rb +37 -1
- data/ui/controllers/newrelic_controller.rb +19 -11
- data/ui/helpers/google_pie_chart.rb +5 -11
- data/ui/helpers/newrelic_helper.rb +40 -35
- data/ui/views/layouts/newrelic_default.rhtml +7 -7
- data/ui/views/newrelic/_sample.rhtml +5 -1
- data/ui/views/newrelic/images/new-relic-rpm-desktop.gif +0 -0
- data/ui/views/newrelic/images/textmate.png +0 -0
- data/ui/views/newrelic/index.rhtml +13 -1
- data/ui/views/newrelic/show_sample.rhtml +5 -2
- data/ui/views/newrelic/stylesheets/style.css +54 -3
- metadata +65 -145
- data/Manifest +0 -143
- data/Rakefile +0 -22
- data/init.rb +0 -38
- data/lib/new_relic/agent/instrumentation/dispatcher_instrumentation.rb +0 -127
- data/lib/new_relic/agent/instrumentation/error_instrumentation.rb +0 -14
- data/lib/new_relic/agent/instrumentation/merb/dispatcher.rb +0 -13
- data/lib/new_relic/agent/instrumentation/rails/dispatcher.rb +0 -38
- data/lib/new_relic/agent/patch_const_missing.rb +0 -125
- data/lib/new_relic/agent/samplers/mongrel_sampler.rb +0 -22
- data/lib/new_relic/metric_parser/database.rb +0 -23
- data/newrelic_rpm.gemspec +0 -35
- data/test/new_relic/agent/classloader_patch_test.rb +0 -56
- data/test/new_relic/agent/controller_test.rb +0 -107
- data/test/new_relic/agent/dispatcher_instrumentation_test.rb +0 -70
@@ -0,0 +1,79 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'..','..','..','test_helper'))
|
2
|
+
|
3
|
+
|
4
|
+
class NewRelic::Agent::MetricStatsTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
NewRelic::Agent.manual_start
|
7
|
+
@engine = NewRelic::Agent.instance.stats_engine
|
8
|
+
rescue => e
|
9
|
+
puts e
|
10
|
+
puts e.backtrace.join("\n")
|
11
|
+
end
|
12
|
+
def teardown
|
13
|
+
@engine.harvest_timeslice_data({},{})
|
14
|
+
end
|
15
|
+
def test_get_no_scope
|
16
|
+
s1 = @engine.get_stats "a"
|
17
|
+
s2 = @engine.get_stats "a"
|
18
|
+
s3 = @engine.get_stats "b"
|
19
|
+
|
20
|
+
assert_not_nil s1
|
21
|
+
assert_not_nil s2
|
22
|
+
assert_not_nil s3
|
23
|
+
|
24
|
+
assert s1 == s2
|
25
|
+
assert s1 != s3
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_harvest
|
29
|
+
s1 = @engine.get_stats "a"
|
30
|
+
s2 = @engine.get_stats "c"
|
31
|
+
|
32
|
+
s1.trace_call 10
|
33
|
+
s2.trace_call 1
|
34
|
+
s2.trace_call 3
|
35
|
+
|
36
|
+
assert @engine.get_stats("a").call_count == 1
|
37
|
+
assert @engine.get_stats("a").total_call_time == 10
|
38
|
+
|
39
|
+
assert @engine.get_stats("c").call_count == 2
|
40
|
+
assert @engine.get_stats("c").total_call_time == 4
|
41
|
+
|
42
|
+
metric_data = @engine.harvest_timeslice_data({}, {}).values
|
43
|
+
|
44
|
+
# after harvest, all the metrics should be reset
|
45
|
+
assert @engine.get_stats("a").call_count == 0
|
46
|
+
assert @engine.get_stats("a").total_call_time == 0
|
47
|
+
|
48
|
+
assert @engine.get_stats("c").call_count == 0
|
49
|
+
assert @engine.get_stats("c").total_call_time == 0
|
50
|
+
|
51
|
+
metric_data = metric_data.reverse if metric_data[0].metric_spec.name != "a"
|
52
|
+
|
53
|
+
assert metric_data[0].metric_spec.name == "a"
|
54
|
+
|
55
|
+
assert metric_data[0].stats.call_count == 1
|
56
|
+
assert metric_data[0].stats.total_call_time == 10
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_harvest_with_merge
|
60
|
+
s = @engine.get_stats "a"
|
61
|
+
s.trace_call 1
|
62
|
+
|
63
|
+
assert @engine.get_stats("a").call_count == 1
|
64
|
+
|
65
|
+
harvest = @engine.harvest_timeslice_data({}, {})
|
66
|
+
assert s.call_count == 0
|
67
|
+
s.trace_call 2
|
68
|
+
assert s.call_count == 1
|
69
|
+
|
70
|
+
# this calk should merge the contents of the previous harvest,
|
71
|
+
# so the stats for metric "a" should have 2 data points
|
72
|
+
harvest = @engine.harvest_timeslice_data(harvest, {})
|
73
|
+
stats = harvest.fetch(NewRelic::MetricSpec.new("a")).stats
|
74
|
+
assert stats.call_count == 2
|
75
|
+
assert stats.total_call_time == 3
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
@@ -1,10 +1,11 @@
|
|
1
|
-
require File.expand_path(File.join(File.dirname(__FILE__),'..', 'test_helper'))
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'..', '..','..','test_helper'))
|
2
2
|
require 'new_relic/agent/samplers/cpu_sampler'
|
3
3
|
|
4
|
-
class NewRelic::SamplersTest < Test::Unit::TestCase
|
4
|
+
class NewRelic::Agent::StatsEngine::SamplersTest < Test::Unit::TestCase
|
5
5
|
|
6
6
|
def setup
|
7
7
|
@stats_engine = NewRelic::Agent::StatsEngine.new
|
8
|
+
NewRelic::Agent.instance.stubs(:stats_engine).returns(@stats_engine)
|
8
9
|
end
|
9
10
|
def test_cpu
|
10
11
|
s = NewRelic::Agent::Samplers::CpuSampler.new
|
@@ -29,6 +30,7 @@ class NewRelic::SamplersTest < Test::Unit::TestCase
|
|
29
30
|
assert s.stats.total_call_time > 0.5, "cpu greater than 0.5 ms: #{s.stats.total_call_time}"
|
30
31
|
end
|
31
32
|
def test_memory__linux
|
33
|
+
return if RUBY_PLATFORM =~ /darwin/
|
32
34
|
NewRelic::Agent::Samplers::MemorySampler.any_instance.stubs(:platform).returns 'linux'
|
33
35
|
s = NewRelic::Agent::Samplers::MemorySampler.new
|
34
36
|
s.stats_engine = @stats_engine
|
@@ -39,33 +41,32 @@ class NewRelic::SamplersTest < Test::Unit::TestCase
|
|
39
41
|
assert s.stats.total_call_time > 0.5, "cpu greater than 0.5 ms: #{s.stats.total_call_time}"
|
40
42
|
end
|
41
43
|
def test_memory__solaris
|
44
|
+
return if defined? JRuby
|
42
45
|
NewRelic::Agent::Samplers::MemorySampler.any_instance.stubs(:platform).returns 'solaris'
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
+
NewRelic::Agent::Samplers::MemorySampler::ShellPS.any_instance.stubs(:get_memory).returns 999
|
47
|
+
s = NewRelic::Agent::Samplers::MemorySampler.new
|
48
|
+
s.stats_engine = @stats_engine
|
49
|
+
s.poll
|
50
|
+
assert_equal 1, s.stats.call_count
|
51
|
+
assert_equal 999, s.stats.total_call_time
|
46
52
|
end
|
47
53
|
def test_memory__windows
|
54
|
+
return if defined? JRuby
|
48
55
|
NewRelic::Agent::Samplers::MemorySampler.any_instance.stubs(:platform).returns 'win32'
|
49
|
-
assert_raise
|
56
|
+
assert_raise NewRelic::Agent::Sampler::Unsupported do
|
50
57
|
NewRelic::Agent::Samplers::MemorySampler.new
|
51
58
|
end
|
52
59
|
end
|
53
|
-
def
|
54
|
-
|
55
|
-
|
56
|
-
NewRelic::Control.instance.
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
s.stats_engine = @stats_engine
|
64
|
-
s.poll
|
65
|
-
s.poll
|
66
|
-
s.poll
|
67
|
-
assert_equal 3, s.queue_stats.call_count
|
68
|
-
assert_equal 3, s.queue_stats.average_call_time, "mongrel queue length"
|
60
|
+
def test_load_samplers
|
61
|
+
@stats_engine.expects(:add_harvest_sampler).once unless defined? JRuby
|
62
|
+
@stats_engine.expects(:add_sampler).never
|
63
|
+
NewRelic::Control.instance.load_samplers
|
64
|
+
sampler_count = 4
|
65
|
+
assert_equal sampler_count, NewRelic::Agent::Sampler.sampler_classes.size, NewRelic::Agent::Sampler.sampler_classes.inspect
|
66
|
+
end
|
67
|
+
def test_memory__is_supported
|
68
|
+
NewRelic::Agent::Samplers::MemorySampler.stubs(:platform).returns 'windows'
|
69
|
+
assert !NewRelic::Agent::Samplers::MemorySampler.supported_on_this_platform? || defined? JRuby
|
69
70
|
end
|
70
71
|
|
71
72
|
end
|
@@ -1,106 +1,17 @@
|
|
1
|
-
require File.expand_path(File.join(File.dirname(__FILE__),'..','..','test_helper'))
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'..','..','..', 'test_helper'))
|
2
2
|
|
3
3
|
|
4
|
-
class NewRelic::Agent::
|
4
|
+
class NewRelic::Agent::StatsEngine::TransactionsTest < Test::Unit::TestCase
|
5
5
|
def setup
|
6
6
|
NewRelic::Agent.manual_start
|
7
|
-
@engine = NewRelic::Agent.
|
7
|
+
@engine = NewRelic::Agent::StatsEngine.new
|
8
|
+
rescue => e
|
9
|
+
puts e
|
10
|
+
puts e.backtrace.join("\n")
|
8
11
|
end
|
9
12
|
def teardown
|
10
13
|
@engine.harvest_timeslice_data({},{})
|
11
14
|
end
|
12
|
-
def test_get_no_scope
|
13
|
-
s1 = @engine.get_stats "a"
|
14
|
-
s2 = @engine.get_stats "a"
|
15
|
-
s3 = @engine.get_stats "b"
|
16
|
-
|
17
|
-
assert_not_nil s1
|
18
|
-
assert_not_nil s2
|
19
|
-
assert_not_nil s3
|
20
|
-
|
21
|
-
assert s1 == s2
|
22
|
-
assert s1 != s3
|
23
|
-
end
|
24
|
-
|
25
|
-
# The default agent configuration when running tests does not
|
26
|
-
# install the samplers so this test just creates them and polls them
|
27
|
-
# just like the stats_engine does.
|
28
|
-
def test_samplers
|
29
|
-
|
30
|
-
samplers = []
|
31
|
-
cpu_sampler = NewRelic::Agent::Samplers::CpuSampler.new
|
32
|
-
samplers << cpu_sampler unless defined? Java
|
33
|
-
samplers << NewRelic::Agent::Samplers::MemorySampler.new
|
34
|
-
samplers.each { |s| s.stats_engine = @engine }
|
35
|
-
msg = ["Running sampler at #{Time.now}"]
|
36
|
-
@engine.instance_eval do
|
37
|
-
poll(samplers)
|
38
|
-
sleep 2
|
39
|
-
msg << "Polling again at #{Time.now}, last time polled=#{cpu_sampler.last_time}"
|
40
|
-
poll(samplers)
|
41
|
-
sleep 2
|
42
|
-
msg << "Polling again at #{Time.now}, last time polled=#{cpu_sampler.last_time}"
|
43
|
-
poll(samplers)
|
44
|
-
end
|
45
|
-
msg << "Last time polled: #{cpu_sampler.last_time}"
|
46
|
-
data = @engine.harvest_timeslice_data({},{})
|
47
|
-
cpu_user = data[NewRelic::MetricSpec.new('CPU/User Time')]
|
48
|
-
cpu_utilization = data[NewRelic::MetricSpec.new('CPU/User/Utilization')]
|
49
|
-
memory = data[NewRelic::MetricSpec.new('Memory/Physical')]
|
50
|
-
# might get 1, 2 or 3 stats depending on timing factors. short intervals are skipped.
|
51
|
-
assert_equal 2, cpu_user.stats.call_count, cpu_user.stats.inspect unless defined? Java
|
52
|
-
assert_equal 2, cpu_utilization.stats.call_count, msg.join("; ") unless defined? Java
|
53
|
-
assert_equal 3, memory.stats.call_count
|
54
|
-
end
|
55
|
-
def test_harvest
|
56
|
-
s1 = @engine.get_stats "a"
|
57
|
-
s2 = @engine.get_stats "c"
|
58
|
-
|
59
|
-
s1.trace_call 10
|
60
|
-
s2.trace_call 1
|
61
|
-
s2.trace_call 3
|
62
|
-
|
63
|
-
assert @engine.get_stats("a").call_count == 1
|
64
|
-
assert @engine.get_stats("a").total_call_time == 10
|
65
|
-
|
66
|
-
assert @engine.get_stats("c").call_count == 2
|
67
|
-
assert @engine.get_stats("c").total_call_time == 4
|
68
|
-
|
69
|
-
metric_data = @engine.harvest_timeslice_data({}, {}).values
|
70
|
-
|
71
|
-
# after harvest, all the metrics should be reset
|
72
|
-
assert @engine.get_stats("a").call_count == 0
|
73
|
-
assert @engine.get_stats("a").total_call_time == 0
|
74
|
-
|
75
|
-
assert @engine.get_stats("c").call_count == 0
|
76
|
-
assert @engine.get_stats("c").total_call_time == 0
|
77
|
-
|
78
|
-
metric_data = metric_data.reverse if metric_data[0].metric_spec.name != "a"
|
79
|
-
|
80
|
-
assert metric_data[0].metric_spec.name == "a"
|
81
|
-
|
82
|
-
assert metric_data[0].stats.call_count == 1
|
83
|
-
assert metric_data[0].stats.total_call_time == 10
|
84
|
-
end
|
85
|
-
|
86
|
-
def test_harvest_with_merge
|
87
|
-
s = @engine.get_stats "a"
|
88
|
-
s.trace_call 1
|
89
|
-
|
90
|
-
assert @engine.get_stats("a").call_count == 1
|
91
|
-
|
92
|
-
harvest = @engine.harvest_timeslice_data({}, {})
|
93
|
-
assert s.call_count == 0
|
94
|
-
s.trace_call 2
|
95
|
-
assert s.call_count == 1
|
96
|
-
|
97
|
-
# this calk should merge the contents of the previous harvest,
|
98
|
-
# so the stats for metric "a" should have 2 data points
|
99
|
-
harvest = @engine.harvest_timeslice_data(harvest, {})
|
100
|
-
stats = harvest.fetch(NewRelic::MetricSpec.new("a")).stats
|
101
|
-
assert stats.call_count == 2
|
102
|
-
assert stats.total_call_time == 3
|
103
|
-
end
|
104
15
|
|
105
16
|
def test_scope
|
106
17
|
@engine.push_scope "scope1"
|
@@ -120,12 +31,14 @@ class NewRelic::Agent::StatsEngineTest < Test::Unit::TestCase
|
|
120
31
|
end
|
121
32
|
|
122
33
|
def test_scope__overlap
|
123
|
-
@engine
|
124
|
-
|
34
|
+
NewRelic::Agent.instance.stubs(:stats_engine).returns(@engine)
|
35
|
+
|
36
|
+
@engine.scope_name = 'orlando'
|
37
|
+
self.class.trace_execution_scoped('disney', :deduct_call_time_from_parent => false) { sleep 0.1 }
|
125
38
|
orlando_disney = @engine.get_stats 'disney'
|
126
39
|
|
127
|
-
@engine.
|
128
|
-
self.class.
|
40
|
+
@engine.scope_name = 'anaheim'
|
41
|
+
self.class.trace_execution_scoped('disney', :deduct_call_time_from_parent => false) { sleep 0.1 }
|
129
42
|
anaheim_disney = @engine.get_stats 'disney'
|
130
43
|
|
131
44
|
disney = @engine.get_stats_no_scope "disney"
|
@@ -218,8 +131,13 @@ class NewRelic::Agent::StatsEngineTest < Test::Unit::TestCase
|
|
218
131
|
end
|
219
132
|
|
220
133
|
def test_simple_start_transaction
|
221
|
-
@engine.
|
134
|
+
assert @engine.peek_scope.nil?
|
135
|
+
scope = @engine.push_scope "scope"
|
222
136
|
@engine.start_transaction
|
137
|
+
assert !@engine.peek_scope.nil?
|
138
|
+
@engine.pop_scope scope, 0.01
|
139
|
+
assert @engine.peek_scope.nil?
|
140
|
+
@engine.end_transaction
|
223
141
|
assert @engine.peek_scope.nil?
|
224
142
|
end
|
225
143
|
|
@@ -259,7 +177,7 @@ class NewRelic::Agent::StatsEngineTest < Test::Unit::TestCase
|
|
259
177
|
|
260
178
|
private
|
261
179
|
def check_time_approximate(expected, actual)
|
262
|
-
assert((expected - actual).abs < 0.
|
180
|
+
assert((expected - actual).abs < 0.1, "Expected between #{expected - 0.1} and #{expected + 0.1}, got #{actual}")
|
263
181
|
end
|
264
182
|
|
265
183
|
end
|
@@ -0,0 +1,176 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__),'..','..','test_helper'))
|
2
|
+
|
3
|
+
class TaskInstrumentationTest < Test::Unit::TestCase
|
4
|
+
include NewRelic::Agent::Instrumentation::ControllerInstrumentation
|
5
|
+
attr_accessor :agent
|
6
|
+
def setup
|
7
|
+
super
|
8
|
+
NewRelic::Agent.manual_start
|
9
|
+
@agent = NewRelic::Agent.instance
|
10
|
+
@agent.transaction_sampler.send :clear_builder
|
11
|
+
@agent.transaction_sampler.reset!
|
12
|
+
@agent.stats_engine.clear_stats
|
13
|
+
end
|
14
|
+
def teardown
|
15
|
+
NewRelic::Agent.shutdown
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_run
|
20
|
+
run_task_inner 0
|
21
|
+
stat_names = %w[Controller/TaskInstrumentationTest/inner_task_0
|
22
|
+
HttpDispatcher
|
23
|
+
Apdex Apdex/TaskInstrumentationTest/inner_task_0].sort
|
24
|
+
expected_but_missing = stat_names - @agent.stats_engine.metrics
|
25
|
+
assert_equal 0, expected_but_missing.size, @agent.stats_engine.metrics.map { |n|
|
26
|
+
stat = @agent.stats_engine.get_stats_no_scope(n)
|
27
|
+
"#{'%-26s' % n}: #{stat.call_count} calls @ #{stat.average_call_time} sec/call"
|
28
|
+
}.join("\n ") + "\nmissing: #{expected_but_missing.inspect}"
|
29
|
+
assert_equal 0, @agent.stats_engine.get_stats_no_scope('Controller').call_count
|
30
|
+
assert_equal 1, @agent.stats_engine.get_stats_no_scope('Controller/TaskInstrumentationTest/inner_task_0').call_count
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_run_recursive
|
34
|
+
run_task_inner(3)
|
35
|
+
assert_equal 1, @agent.stats_engine.lookup_stats(
|
36
|
+
'Controller/TaskInstrumentationTest/inner_task_0',
|
37
|
+
'Controller/TaskInstrumentationTest/inner_task_1').call_count
|
38
|
+
assert_equal 1, @agent.stats_engine.lookup_stats(
|
39
|
+
'Controller/TaskInstrumentationTest/inner_task_1',
|
40
|
+
'Controller/TaskInstrumentationTest/inner_task_2').call_count
|
41
|
+
assert_equal 1, @agent.stats_engine.lookup_stats(
|
42
|
+
'Controller/TaskInstrumentationTest/inner_task_2',
|
43
|
+
'Controller/TaskInstrumentationTest/inner_task_3').call_count
|
44
|
+
assert_equal 1, @agent.stats_engine.get_stats_no_scope('Controller/TaskInstrumentationTest/inner_task_0').call_count
|
45
|
+
assert_equal 1, @agent.stats_engine.get_stats_no_scope('Controller/TaskInstrumentationTest/inner_task_1').call_count
|
46
|
+
assert_equal 1, @agent.stats_engine.get_stats_no_scope('Controller/TaskInstrumentationTest/inner_task_2').call_count
|
47
|
+
assert_equal 1, @agent.stats_engine.get_stats_no_scope('Controller/TaskInstrumentationTest/inner_task_3').call_count
|
48
|
+
assert_equal 0, @agent.stats_engine.get_stats_no_scope('Controller').call_count
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_run_nested
|
52
|
+
run_task_outer(3)
|
53
|
+
@agent.stats_engine.metrics.sort.each do |n|
|
54
|
+
stat = @agent.stats_engine.get_stats_no_scope(n)
|
55
|
+
# puts "#{'%-26s' % n}: #{stat.call_count} calls @ #{stat.average_call_time} sec/call"
|
56
|
+
end
|
57
|
+
assert_equal 1, @agent.stats_engine.get_stats_no_scope('Controller/TaskInstrumentationTest/outer_task').call_count
|
58
|
+
assert_equal 2, @agent.stats_engine.get_stats_no_scope('Controller/TaskInstrumentationTest/inner_task_0').call_count
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_reentrancy
|
62
|
+
assert_equal 0, NewRelic::Agent::BusyCalculator.busy_count
|
63
|
+
run_task_inner(1)
|
64
|
+
assert_equal 1, @agent.stats_engine.get_stats_no_scope('Controller/TaskInstrumentationTest/inner_task_0').call_count
|
65
|
+
assert_equal 1, @agent.stats_engine.get_stats_no_scope('Controller/TaskInstrumentationTest/inner_task_1').call_count
|
66
|
+
compare_metrics %w[
|
67
|
+
Controller/TaskInstrumentationTest/inner_task_0:Controller/TaskInstrumentationTest/inner_task_1
|
68
|
+
Controller/TaskInstrumentationTest/inner_task_0
|
69
|
+
Controller/TaskInstrumentationTest/inner_task_1
|
70
|
+
], @agent.stats_engine.metrics.grep(/^Controller/)
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_transaction
|
74
|
+
assert_equal 0, @agent.transaction_sampler.scope_depth, "existing unfinished sample"
|
75
|
+
assert_nil @agent.transaction_sampler.last_sample
|
76
|
+
assert_equal @agent.transaction_sampler, @agent.stats_engine.instance_variable_get("@transaction_sampler")
|
77
|
+
run_task_outer(10)
|
78
|
+
assert_equal 0, @agent.transaction_sampler.scope_depth, "existing unfinished sample"
|
79
|
+
@agent.stats_engine.metrics.sort.each do |n|
|
80
|
+
stat = @agent.stats_engine.get_stats_no_scope(n)
|
81
|
+
# puts "#{'%-26s' % n}: #{stat.call_count} calls @ #{stat.average_call_time} sec/call"
|
82
|
+
end
|
83
|
+
assert_equal 1, @agent.stats_engine.get_stats_no_scope('Controller/TaskInstrumentationTest/outer_task').call_count
|
84
|
+
assert_equal 0, @agent.stats_engine.get_stats_no_scope('Controller').call_count
|
85
|
+
assert_equal 2, @agent.stats_engine.get_stats_no_scope('Controller/TaskInstrumentationTest/inner_task_0').call_count
|
86
|
+
assert_equal 0, @agent.transaction_sampler.scope_depth, "existing unfinished sample"
|
87
|
+
sample = @agent.transaction_sampler.last_sample
|
88
|
+
assert_not_nil sample
|
89
|
+
assert_not_nil sample.params[:cpu_time], "cpu time nil: \n#{sample}"
|
90
|
+
assert sample.params[:cpu_time] >= 0, "cpu time: #{sample.params[:cpu_time]},\n#{sample}"
|
91
|
+
assert_equal '10', sample.params[:request_params][:level]
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_abort
|
95
|
+
@acct = 'Redrocks'
|
96
|
+
perform_action_with_newrelic_trace(:name => 'hello', :force => true, :params => { :account => @acct}) do
|
97
|
+
RAILS_DEFAULT_LOGGER.info "Hello world"
|
98
|
+
NewRelic::Agent.abort_transaction!
|
99
|
+
end
|
100
|
+
# We record the controller metric still, but abort any transaction recording.
|
101
|
+
assert_equal 1, @agent.stats_engine.get_stats_no_scope('Controller/TaskInstrumentationTest/hello').call_count
|
102
|
+
assert_nil @agent.transaction_sampler.last_sample
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_block
|
106
|
+
assert_equal @agent, NewRelic::Agent.instance
|
107
|
+
@acct = 'Redrocks'
|
108
|
+
perform_action_with_newrelic_trace(:name => 'hello', :force => true, :params => { :account => @acct}) do
|
109
|
+
RAILS_DEFAULT_LOGGER.info "Hello world"
|
110
|
+
end
|
111
|
+
@agent.stats_engine.metrics.sort.each do |n|
|
112
|
+
stat = @agent.stats_engine.get_stats_no_scope(n)
|
113
|
+
#puts "#{'%-26s' % n}: #{stat.call_count} calls @ #{stat.average_call_time} sec/call"
|
114
|
+
end
|
115
|
+
assert_equal @agent, NewRelic::Agent.instance
|
116
|
+
assert_equal 1, @agent.stats_engine.get_stats_no_scope('Controller/TaskInstrumentationTest/hello').call_count
|
117
|
+
sample = @agent.transaction_sampler.last_sample
|
118
|
+
assert_not_nil sample
|
119
|
+
assert_equal 'Redrocks', sample.params[:request_params][:account]
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
def test_error_handling
|
124
|
+
@agent.error_collector.ignore_error_filter
|
125
|
+
@agent.error_collector.harvest_errors([])
|
126
|
+
@agent.error_collector.expects(:notice_error).once
|
127
|
+
assert_equal @agent.error_collector, NewRelic::Agent.instance.error_collector
|
128
|
+
assert_raise RuntimeError do
|
129
|
+
run_task_exception
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def test_instrument_bg
|
134
|
+
run_background_job
|
135
|
+
stat_names = %w[OtherTransaction/Background/TaskInstrumentationTest/run_background_job
|
136
|
+
OtherTransaction/Background/all
|
137
|
+
OtherTransaction/all].sort
|
138
|
+
|
139
|
+
expected_but_missing = stat_names - @agent.stats_engine.metrics
|
140
|
+
assert_equal 0, expected_but_missing.size, @agent.stats_engine.metrics.map { |n|
|
141
|
+
stat = @agent.stats_engine.get_stats_no_scope(n)
|
142
|
+
"#{'%-26s' % n}: #{stat.call_count} calls @ #{stat.average_call_time} sec/call"
|
143
|
+
}.join("\n ") + "\nmissing: #{expected_but_missing.inspect}"
|
144
|
+
assert_equal 1, @agent.stats_engine.get_stats_no_scope('OtherTransaction/all').call_count
|
145
|
+
assert_equal 1, @agent.stats_engine.get_stats_no_scope('OtherTransaction/Background/all').call_count
|
146
|
+
end
|
147
|
+
private
|
148
|
+
|
149
|
+
def run_task_inner(n)
|
150
|
+
sleep 0.1
|
151
|
+
return if n == 0
|
152
|
+
assert_equal 1, NewRelic::Agent::BusyCalculator.busy_count
|
153
|
+
run_task_inner(n-1)
|
154
|
+
end
|
155
|
+
|
156
|
+
def run_task_outer(n=0)
|
157
|
+
assert_equal 1, NewRelic::Agent::BusyCalculator.busy_count
|
158
|
+
run_task_inner(n)
|
159
|
+
run_task_inner(n)
|
160
|
+
end
|
161
|
+
|
162
|
+
def run_task_exception
|
163
|
+
assert_equal 1, NewRelic::Agent::BusyCalculator.busy_count
|
164
|
+
raise "This is an error"
|
165
|
+
end
|
166
|
+
|
167
|
+
def run_background_job
|
168
|
+
"This is a background job"
|
169
|
+
end
|
170
|
+
|
171
|
+
add_transaction_tracer :run_task_exception
|
172
|
+
add_transaction_tracer :run_task_inner, :name => 'inner_task_#{args[0]}'
|
173
|
+
add_transaction_tracer :run_task_outer, :name => 'outer_task', :params => '{ :level => args[0] }'
|
174
|
+
# Eventually we need th change this to :category => :task
|
175
|
+
add_transaction_tracer :run_background_job, :category => 'OtherTransaction/Background'
|
176
|
+
end
|