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.

Files changed (120) hide show
  1. data/CHANGELOG +117 -49
  2. data/bin/mongrel_rpm +2 -2
  3. data/install.rb +42 -33
  4. data/lib/new_relic/agent.rb +149 -39
  5. data/lib/new_relic/agent/agent.rb +139 -122
  6. data/lib/new_relic/agent/busy_calculator.rb +91 -0
  7. data/lib/new_relic/agent/collection_helper.rb +11 -2
  8. data/lib/new_relic/agent/error_collector.rb +33 -27
  9. data/lib/new_relic/agent/instrumentation/active_record_instrumentation.rb +30 -26
  10. data/lib/new_relic/agent/instrumentation/authlogic.rb +8 -0
  11. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +316 -105
  12. data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +22 -0
  13. data/lib/new_relic/agent/instrumentation/memcache.rb +18 -12
  14. data/lib/new_relic/agent/instrumentation/merb/errors.rb +2 -1
  15. data/lib/new_relic/agent/instrumentation/metric_frame.rb +258 -0
  16. data/lib/new_relic/agent/instrumentation/net.rb +7 -11
  17. data/lib/new_relic/agent/instrumentation/passenger_instrumentation.rb +1 -1
  18. data/lib/new_relic/agent/instrumentation/rack.rb +109 -0
  19. data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +6 -5
  20. data/lib/new_relic/agent/instrumentation/rails/errors.rb +7 -7
  21. data/lib/new_relic/agent/instrumentation/sinatra.rb +46 -0
  22. data/lib/new_relic/agent/method_tracer.rb +305 -150
  23. data/lib/new_relic/agent/sampler.rb +34 -0
  24. data/lib/new_relic/agent/samplers/cpu_sampler.rb +11 -1
  25. data/lib/new_relic/agent/samplers/delayed_job_lock_sampler.rb +37 -0
  26. data/lib/new_relic/agent/samplers/memory_sampler.rb +22 -10
  27. data/lib/new_relic/agent/samplers/object_sampler.rb +24 -0
  28. data/lib/new_relic/agent/shim_agent.rb +10 -0
  29. data/lib/new_relic/agent/stats_engine.rb +16 -278
  30. data/lib/new_relic/agent/stats_engine/metric_stats.rb +118 -0
  31. data/lib/new_relic/agent/stats_engine/samplers.rb +81 -0
  32. data/lib/new_relic/agent/stats_engine/transactions.rb +149 -0
  33. data/lib/new_relic/agent/transaction_sampler.rb +73 -67
  34. data/lib/new_relic/agent/worker_loop.rb +69 -68
  35. data/lib/new_relic/commands/deployments.rb +4 -6
  36. data/lib/new_relic/control.rb +121 -60
  37. data/lib/new_relic/control/external.rb +13 -0
  38. data/lib/new_relic/control/merb.rb +2 -0
  39. data/lib/new_relic/control/rails.rb +16 -6
  40. data/lib/new_relic/control/ruby.rb +8 -5
  41. data/lib/new_relic/control/sinatra.rb +18 -0
  42. data/lib/new_relic/delayed_job_injection.rb +25 -0
  43. data/lib/new_relic/histogram.rb +89 -0
  44. data/lib/new_relic/local_environment.rb +64 -30
  45. data/lib/new_relic/metric_data.rb +15 -6
  46. data/lib/new_relic/metric_parser.rb +14 -1
  47. data/lib/new_relic/metric_parser/active_record.rb +14 -0
  48. data/lib/new_relic/metric_parser/controller.rb +5 -2
  49. data/lib/new_relic/metric_parser/external.rb +50 -0
  50. data/lib/new_relic/metric_parser/other_transaction.rb +15 -0
  51. data/lib/new_relic/metric_parser/web_frontend.rb +14 -0
  52. data/lib/new_relic/metric_spec.rb +39 -20
  53. data/lib/new_relic/metrics.rb +9 -7
  54. data/lib/new_relic/noticed_error.rb +6 -8
  55. data/lib/new_relic/rack/metric_app.rb +5 -4
  56. data/lib/new_relic/rack/{newrelic.ru → mongrel_rpm.ru} +4 -4
  57. data/lib/new_relic/rack/newrelic.yml +1 -0
  58. data/lib/new_relic/{rack.rb → rack_app.rb} +0 -0
  59. data/lib/new_relic/recipes.rb +1 -1
  60. data/lib/new_relic/stats.rb +40 -26
  61. data/lib/new_relic/transaction_analysis.rb +5 -2
  62. data/lib/new_relic/transaction_sample.rb +134 -55
  63. data/lib/new_relic/version.rb +27 -20
  64. data/lib/new_relic_api.rb +67 -47
  65. data/lib/newrelic_rpm.rb +5 -5
  66. data/lib/tasks/tests.rake +2 -0
  67. data/newrelic.yml +69 -29
  68. data/test/active_record_fixtures.rb +2 -2
  69. data/test/config/newrelic.yml +4 -7
  70. data/test/config/test_control.rb +1 -2
  71. data/test/new_relic/agent/active_record_instrumentation_test.rb +115 -31
  72. data/test/new_relic/agent/agent_controller_test.rb +274 -0
  73. data/test/new_relic/agent/agent_test_controller.rb +42 -6
  74. data/test/new_relic/agent/busy_calculator_test.rb +79 -0
  75. data/test/new_relic/agent/collection_helper_test.rb +10 -3
  76. data/test/new_relic/agent/error_collector_test.rb +35 -17
  77. data/test/new_relic/agent/method_tracer_test.rb +60 -20
  78. data/test/new_relic/agent/metric_data_test.rb +2 -2
  79. data/test/new_relic/agent/metric_frame_test.rb +51 -0
  80. data/test/new_relic/agent/net_instrumentation_test.rb +77 -0
  81. data/test/new_relic/agent/{agent_test.rb → rpm_agent_test.rb} +26 -5
  82. data/test/new_relic/agent/stats_engine/metric_stats_test.rb +79 -0
  83. data/test/new_relic/{samplers_test.rb → agent/stats_engine/samplers_test.rb} +23 -22
  84. data/test/new_relic/agent/{stats_engine_test.rb → stats_engine/stats_engine_test.rb} +19 -101
  85. data/test/new_relic/agent/task_instrumentation_test.rb +176 -0
  86. data/test/new_relic/agent/transaction_sample_builder_test.rb +2 -2
  87. data/test/new_relic/agent/transaction_sample_test.rb +53 -38
  88. data/test/new_relic/agent/transaction_sampler_test.rb +101 -33
  89. data/test/new_relic/agent/worker_loop_test.rb +16 -14
  90. data/test/new_relic/control_test.rb +26 -13
  91. data/test/new_relic/metric_parser_test.rb +31 -1
  92. data/test/new_relic/metric_spec_test.rb +2 -2
  93. data/test/new_relic/stats_test.rb +0 -8
  94. data/test/new_relic/version_number_test.rb +31 -1
  95. data/test/test_helper.rb +37 -1
  96. data/ui/controllers/newrelic_controller.rb +19 -11
  97. data/ui/helpers/google_pie_chart.rb +5 -11
  98. data/ui/helpers/newrelic_helper.rb +40 -35
  99. data/ui/views/layouts/newrelic_default.rhtml +7 -7
  100. data/ui/views/newrelic/_sample.rhtml +5 -1
  101. data/ui/views/newrelic/images/new-relic-rpm-desktop.gif +0 -0
  102. data/ui/views/newrelic/images/textmate.png +0 -0
  103. data/ui/views/newrelic/index.rhtml +13 -1
  104. data/ui/views/newrelic/show_sample.rhtml +5 -2
  105. data/ui/views/newrelic/stylesheets/style.css +54 -3
  106. metadata +65 -145
  107. data/Manifest +0 -143
  108. data/Rakefile +0 -22
  109. data/init.rb +0 -38
  110. data/lib/new_relic/agent/instrumentation/dispatcher_instrumentation.rb +0 -127
  111. data/lib/new_relic/agent/instrumentation/error_instrumentation.rb +0 -14
  112. data/lib/new_relic/agent/instrumentation/merb/dispatcher.rb +0 -13
  113. data/lib/new_relic/agent/instrumentation/rails/dispatcher.rb +0 -38
  114. data/lib/new_relic/agent/patch_const_missing.rb +0 -125
  115. data/lib/new_relic/agent/samplers/mongrel_sampler.rb +0 -22
  116. data/lib/new_relic/metric_parser/database.rb +0 -23
  117. data/newrelic_rpm.gemspec +0 -35
  118. data/test/new_relic/agent/classloader_patch_test.rb +0 -56
  119. data/test/new_relic/agent/controller_test.rb +0 -107
  120. 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
- assert_raise RuntimeError, /Unable to run command/ do
44
- NewRelic::Agent::Samplers::MemorySampler.new
45
- end
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 RuntimeError, /Unsupported platform/ do
56
+ assert_raise NewRelic::Agent::Sampler::Unsupported do
50
57
  NewRelic::Agent::Samplers::MemorySampler.new
51
58
  end
52
59
  end
53
- def test_mongrel
54
- NewRelic::Agent::Instrumentation::DispatcherInstrumentation::BusyCalculator.stubs('is_busy?'.to_sym).returns(false)
55
- mongrel = mock()
56
- NewRelic::Control.instance.local_env.stubs(:mongrel).returns(mongrel)
57
- list = mock()
58
- workers = mock()
59
- workers.stubs(:list).returns(list)
60
- list.stubs(:length).returns(3)
61
- mongrel.expects(:workers).returns(workers).at_least_once
62
- s = NewRelic::Agent::Samplers::MongrelSampler.new
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::StatsEngineTest < Test::Unit::TestCase
4
+ class NewRelic::Agent::StatsEngine::TransactionsTest < Test::Unit::TestCase
5
5
  def setup
6
6
  NewRelic::Agent.manual_start
7
- @engine = NewRelic::Agent.instance.stats_engine
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.transaction_name = 'orlando'
124
- self.class.trace_method_execution_with_scope('disney', true, false) { sleep 0.1 }
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.transaction_name = 'anaheim'
128
- self.class.trace_method_execution_with_scope('disney', true, false) { sleep 0.1 }
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.push_scope "scope"
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.05, "Expected between #{expected - 0.05} and #{expected + 0.05}, got #{actual}")
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