newrelic_rpm 3.7.3.204 → 3.8.0.218

Sign up to get free protection for your applications and to get access to all the features.
Files changed (154) hide show
  1. data.tar.gz.sig +0 -0
  2. data/CHANGELOG +73 -0
  3. data/README.md +1 -1
  4. data/Rakefile +1 -5
  5. data/lib/new_relic/agent.rb +1 -0
  6. data/lib/new_relic/agent/agent.rb +47 -18
  7. data/lib/new_relic/agent/agent_logger.rb +11 -1
  8. data/lib/new_relic/agent/configuration/default_source.rb +85 -1
  9. data/lib/new_relic/agent/configuration/manager.rb +5 -1
  10. data/lib/new_relic/agent/datastores/mongo.rb +8 -3
  11. data/lib/new_relic/agent/harvester.rb +5 -1
  12. data/lib/new_relic/agent/instrumentation/action_controller_subscriber.rb +1 -0
  13. data/lib/new_relic/agent/instrumentation/active_merchant.rb +7 -3
  14. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +13 -3
  15. data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +7 -1
  16. data/lib/new_relic/agent/instrumentation/sidekiq.rb +3 -1
  17. data/lib/new_relic/agent/instrumentation/sinatra.rb +3 -1
  18. data/lib/new_relic/agent/new_relic_service.rb +8 -0
  19. data/lib/new_relic/agent/request_sampler.rb +1 -1
  20. data/lib/new_relic/agent/sampler.rb +22 -2
  21. data/lib/new_relic/agent/sampler_collection.rb +13 -1
  22. data/lib/new_relic/agent/samplers/cpu_sampler.rb +3 -1
  23. data/lib/new_relic/agent/samplers/delayed_job_sampler.rb +2 -1
  24. data/lib/new_relic/agent/samplers/memory_sampler.rb +2 -1
  25. data/lib/new_relic/agent/samplers/object_sampler.rb +1 -3
  26. data/lib/new_relic/agent/samplers/vm_sampler.rb +126 -0
  27. data/lib/new_relic/agent/stats.rb +0 -15
  28. data/lib/new_relic/agent/stats_engine/gc_profiler.rb +66 -75
  29. data/lib/new_relic/agent/stats_engine/stats_hash.rb +1 -1
  30. data/lib/new_relic/agent/supported_versions.rb +2 -2
  31. data/lib/new_relic/agent/transaction.rb +6 -3
  32. data/lib/new_relic/agent/vm/monotonic_gc_profiler.rb +17 -5
  33. data/lib/new_relic/agent/vm/mri_vm.rb +2 -1
  34. data/lib/new_relic/agent/vm/snapshot.rb +5 -1
  35. data/lib/new_relic/control/instance_methods.rb +8 -5
  36. data/lib/new_relic/control/instrumentation.rb +0 -9
  37. data/lib/new_relic/environment_report.rb +1 -1
  38. data/lib/new_relic/language_support.rb +4 -0
  39. data/lib/new_relic/local_environment.rb +39 -14
  40. data/lib/new_relic/noticed_error.rb +7 -4
  41. data/lib/new_relic/rack/browser_monitoring.rb +16 -3
  42. data/lib/new_relic/version.rb +2 -2
  43. data/newrelic_rpm.gemspec +1 -1
  44. data/test/agent_helper.rb +5 -3
  45. data/test/environments/lib/environments/runner.rb +8 -7
  46. data/test/environments/norails/Gemfile +1 -1
  47. data/test/environments/rails21/Gemfile +1 -0
  48. data/test/environments/rails22/Gemfile +1 -0
  49. data/test/environments/rails23/Gemfile +1 -0
  50. data/test/environments/rails30/Gemfile +4 -1
  51. data/test/environments/rails31/Gemfile +4 -1
  52. data/test/environments/rails32/Gemfile +3 -4
  53. data/test/environments/rails40/Gemfile +1 -1
  54. data/test/environments/rails41/Gemfile +1 -1
  55. data/test/flaky_proxy/lib/flaky_proxy/proxy.rb +1 -0
  56. data/test/multiverse/lib/multiverse/output_collector.rb +3 -1
  57. data/test/multiverse/lib/multiverse/runner.rb +2 -10
  58. data/test/multiverse/lib/multiverse/suite.rb +100 -30
  59. data/test/multiverse/suites/activemerchant/Envfile +16 -0
  60. data/test/multiverse/suites/activemerchant/activemerchant_test.rb +65 -0
  61. data/test/multiverse/suites/agent_only/custom_queue_time_test.rb +57 -0
  62. data/test/multiverse/suites/config_file_loading/config_file_loading_test.rb +1 -1
  63. data/test/multiverse/suites/mongo/Envfile +9 -1
  64. data/test/multiverse/suites/rails/Envfile +2 -2
  65. data/test/multiverse/suites/rails/app.rb +3 -0
  66. data/test/multiverse/suites/rails/bad_instrumentation_test.rb +0 -2
  67. data/test/multiverse/suites/rails/error_tracing_test.rb +1 -2
  68. data/test/multiverse/suites/rails/gc_instrumentation_test.rb +17 -8
  69. data/test/multiverse/suites/rails/ignore_test.rb +0 -2
  70. data/test/multiverse/suites/rails/mongrel_queue_depth_test.rb +0 -2
  71. data/test/multiverse/suites/rails/queue_time_test.rb +40 -11
  72. data/test/multiverse/suites/rails/request_statistics_test.rb +0 -3
  73. data/test/multiverse/suites/rails/view_instrumentation_test.rb +0 -2
  74. data/test/multiverse/suites/sidekiq/Envfile +7 -2
  75. data/test/multiverse/suites/sinatra/Envfile +1 -1
  76. data/test/multiverse/suites/sinatra/nested_middleware_test.rb +41 -0
  77. data/test/multiverse/suites/sinatra/sinatra_metric_explosion_test.rb +1 -1
  78. data/test/new_relic/agent/agent/connect_test.rb +32 -4
  79. data/test/new_relic/agent/agent/start_test.rb +9 -1
  80. data/test/new_relic/agent/agent_logger_test.rb +23 -2
  81. data/test/new_relic/agent/agent_test.rb +49 -7
  82. data/test/new_relic/agent/configuration/manager_test.rb +8 -0
  83. data/test/new_relic/agent/configuration/orphan_configuration_test.rb +7 -0
  84. data/test/new_relic/agent/cross_app_monitor_test.rb +5 -6
  85. data/test/new_relic/agent/harvester_test.rb +13 -8
  86. data/test/new_relic/agent/instrumentation/action_controller_subscriber_test.rb +28 -7
  87. data/test/new_relic/agent/instrumentation/controller_instrumentation_test.rb +32 -21
  88. data/test/new_relic/agent/new_relic_service_test.rb +14 -0
  89. data/test/new_relic/agent/request_sampler_test.rb +5 -3
  90. data/test/new_relic/agent/rpm_agent_test.rb +2 -3
  91. data/test/new_relic/agent/sampler_collection_test.rb +15 -5
  92. data/test/new_relic/agent/sampler_test.rb +43 -0
  93. data/test/new_relic/agent/{cpu_sampler_test.rb → samplers/cpu_sampler_test.rb} +1 -1
  94. data/test/new_relic/agent/samplers/vm_sampler_test.rb +349 -0
  95. data/test/new_relic/agent/stats_engine/gc_profiler_test.rb +165 -44
  96. data/test/new_relic/agent/stats_hash_test.rb +1 -1
  97. data/test/new_relic/agent/transaction_test.rb +14 -0
  98. data/test/new_relic/agent/vm/monotonic_gc_profiler_test.rb +5 -5
  99. data/test/new_relic/agent/vm/mri_vm_test.rb +7 -0
  100. data/test/new_relic/agent/vm/snapshot_test.rb +5 -0
  101. data/test/new_relic/agent_test.rb +2 -2
  102. data/test/new_relic/control/instance_methods_test.rb +30 -0
  103. data/test/new_relic/control_test.rb +43 -21
  104. data/test/new_relic/dispatcher_test.rb +5 -0
  105. data/test/new_relic/local_environment_test.rb +3 -26
  106. data/test/new_relic/multiverse_helpers.rb +5 -0
  107. data/test/new_relic/noticed_error_test.rb +7 -0
  108. data/test/new_relic/rack/browser_monitoring_test.rb +13 -14
  109. data/test/test_helper.rb +2 -1
  110. metadata +56 -68
  111. metadata.gz.sig +1 -1
  112. data/lib/new_relic/agent/instrumentation/puma.rb +0 -25
  113. data/lib/new_relic/agent/instrumentation/unicorn_instrumentation.rb +0 -26
  114. data/test/multiverse/script/run_one +0 -5
  115. data/test/rum/basic.result.html +0 -10
  116. data/test/rum/basic.source.html +0 -10
  117. data/test/rum/comments1.result.html +0 -24
  118. data/test/rum/comments1.source.html +0 -24
  119. data/test/rum/comments2.result.html +0 -24
  120. data/test/rum/comments2.source.html +0 -24
  121. data/test/rum/gt_in_quotes1.result.html +0 -27
  122. data/test/rum/gt_in_quotes1.source.html +0 -27
  123. data/test/rum/gt_in_quotes2.result.html +0 -24
  124. data/test/rum/gt_in_quotes2.source.html +0 -24
  125. data/test/rum/gt_in_quotes_mismatch.result.html +0 -24
  126. data/test/rum/gt_in_quotes_mismatch.source.html +0 -24
  127. data/test/rum/gt_in_single_quotes1.result.html +0 -25
  128. data/test/rum/gt_in_single_quotes1.source.html +0 -25
  129. data/test/rum/gt_in_single_quotes_mismatch.result.html +0 -25
  130. data/test/rum/gt_in_single_quotes_mismatch.source.html +0 -25
  131. data/test/rum/incomplete_non_meta_tags.result.html +0 -10
  132. data/test/rum/incomplete_non_meta_tags.source.html +0 -10
  133. data/test/rum/no_body.result.html +0 -21
  134. data/test/rum/no_body.source.html +0 -21
  135. data/test/rum/no_header.result.html +0 -7
  136. data/test/rum/no_header.source.html +0 -7
  137. data/test/rum/no_html_and_no_header.result.html +0 -3
  138. data/test/rum/no_html_and_no_header.source.html +0 -3
  139. data/test/rum/no_start_header.result.html +0 -9
  140. data/test/rum/no_start_header.source.html +0 -9
  141. data/test/rum/script1.result.html +0 -19
  142. data/test/rum/script1.source.html +0 -19
  143. data/test/rum/script2.result.html +0 -17
  144. data/test/rum/script2.source.html +0 -17
  145. data/test/rum/x_ua_meta_tag.result.html +0 -10
  146. data/test/rum/x_ua_meta_tag.source.html +0 -10
  147. data/test/rum/x_ua_meta_tag_multiline.result.html +0 -11
  148. data/test/rum/x_ua_meta_tag_multiline.source.html +0 -11
  149. data/test/rum/x_ua_meta_tag_spaces_around_equals.result.html +0 -10
  150. data/test/rum/x_ua_meta_tag_spaces_around_equals.source.html +0 -10
  151. data/test/rum/x_ua_meta_tag_with_others.result.html +0 -11
  152. data/test/rum/x_ua_meta_tag_with_others.source.html +0 -11
  153. data/test/rum/x_ua_meta_tag_with_spaces.result.html +0 -10
  154. data/test/rum/x_ua_meta_tag_with_spaces.source.html +0 -10
@@ -7,6 +7,11 @@ class NewRelic::Agent::Agent::StartTest < Minitest::Test
7
7
  require 'new_relic/agent/agent'
8
8
  include NewRelic::Agent::Agent::Start
9
9
 
10
+ def setup
11
+ @harvester = stub("dummy harvester")
12
+ @harvest_samplers = stub("dummy sampler collection")
13
+ end
14
+
10
15
  def test_already_started_positive
11
16
  dummy_logger = mock
12
17
  dummy_logger.expects(:error).with("Agent Started Already!")
@@ -51,7 +56,8 @@ class NewRelic::Agent::Agent::StartTest < Minitest::Test
51
56
  end
52
57
 
53
58
  def test_check_config_and_start_agent_normal
54
-
59
+ @harvester.expects(:mark_started)
60
+ @harvest_samplers.expects(:load_samplers)
55
61
  self.expects(:generate_environment_report)
56
62
  self.expects(:start_worker_thread)
57
63
  self.expects(:install_exit_handler)
@@ -61,6 +67,8 @@ class NewRelic::Agent::Agent::StartTest < Minitest::Test
61
67
  end
62
68
 
63
69
  def test_check_config_and_start_agent_sync
70
+ @harvester.expects(:mark_started)
71
+ @harvest_samplers.expects(:load_samplers)
64
72
  self.expects(:generate_environment_report)
65
73
  self.expects(:connect_in_foreground)
66
74
  self.expects(:start_worker_thread)
@@ -228,6 +228,27 @@ class AgentLoggerTest < Minitest::Test
228
228
  /INFO : Debugging backtrace:\n.*wiggle\s+wobble\s+topple/)
229
229
  end
230
230
 
231
+ def recursion_is_an_antipattern
232
+ recursion_is_an_antipattern
233
+ end
234
+
235
+ def test_log_exception_gets_backtrace_for_system_stack_error
236
+ # This facility compensates for poor SystemStackError traces on MRI.
237
+ # JRuby and Rubinius raise errors with good backtraces, so skip this test.
238
+ return if jruby? || rubinius?
239
+
240
+ logger = create_basic_logger
241
+
242
+ begin
243
+ recursion_is_an_antipattern
244
+ rescue SystemStackError => e
245
+ logger.log_exception(:error, e)
246
+ end
247
+
248
+ assert_logged(/ERROR : /,
249
+ /ERROR : Debugging backtrace:\n.*#{__method__}/)
250
+ end
251
+
231
252
  def test_logs_to_stdout_if_fails_on_file
232
253
  Logger::LogDevice.any_instance.stubs(:open).raises(Errno::EACCES)
233
254
 
@@ -289,9 +310,9 @@ class AgentLoggerTest < Minitest::Test
289
310
  end
290
311
 
291
312
  def assert_logged(*args)
292
- assert_equal(args.length, logged_lines.length)
313
+ assert_equal(args.length, logged_lines.length, "Unexpected log length #{logged_lines}")
293
314
  logged_lines.each_with_index do |line, index|
294
- assert_match(args[index], line)
315
+ assert_match(args[index], line, "Missing match for #{args[index]}")
295
316
  end
296
317
  end
297
318
  end
@@ -15,6 +15,13 @@ module NewRelic
15
15
  @agent.service = default_service
16
16
  @agent.agent_command_router.stubs(:new_relic_service).returns(@agent.service)
17
17
  @agent.stubs(:start_worker_thread)
18
+
19
+ @config = { :license_key => "a" * 40 }
20
+ NewRelic::Agent.config.apply_config(@config)
21
+ end
22
+
23
+ def teardown
24
+ NewRelic::Agent.config.remove_config(@config)
18
25
  end
19
26
 
20
27
  def test_after_fork_reporting_to_channel
@@ -27,9 +34,11 @@ module NewRelic
27
34
  end
28
35
 
29
36
  def test_after_fork_reporting_to_channel_should_not_collect_environment_report
30
- @agent.stubs(:connected?).returns(true)
31
- @agent.expects(:generate_environment_report).never
32
- @agent.after_fork(:report_to_channel => 123)
37
+ with_config(:monitor_mode => true) do
38
+ @agent.stubs(:connected?).returns(true)
39
+ @agent.expects(:generate_environment_report).never
40
+ @agent.after_fork(:report_to_channel => 123)
41
+ end
33
42
  end
34
43
 
35
44
  def test_after_fork_should_close_pipe_if_parent_not_connected
@@ -70,6 +79,24 @@ module NewRelic
70
79
  end
71
80
  end
72
81
 
82
+ def test_after_fork_should_mark_as_started
83
+ with_config(:monitor_mode => true) do
84
+ refute @agent.started?
85
+ @agent.after_fork
86
+ assert @agent.started?
87
+ end
88
+ end
89
+
90
+ def test_after_fork_should_prevent_further_thread_restart_attempts
91
+ with_config(:monitor_mode => true) do
92
+ # Disconnecting will tell us not to restart the thread
93
+ @agent.disconnect
94
+ @agent.after_fork
95
+
96
+ refute @agent.harvester.needs_restart?
97
+ end
98
+ end
99
+
73
100
  def test_transmit_data_should_emit_before_harvest_event
74
101
  got_it = false
75
102
  @agent.events.subscribe(:before_harvest) { got_it = true }
@@ -273,12 +300,28 @@ module NewRelic
273
300
  @agent.send(:connect, :force_reconnect => true)
274
301
  end
275
302
 
303
+ def test_connect_settings
304
+ settings = @agent.connect_settings
305
+ assert settings.include?(:pid)
306
+ assert settings.include?(:host)
307
+ assert settings.include?(:app_name)
308
+ assert settings.include?(:language)
309
+ assert settings.include?(:agent_version)
310
+ assert settings.include?(:environment)
311
+ assert settings.include?(:settings)
312
+ end
313
+
314
+ def test_connect_settings_checks_environment_report_can_marshal
315
+ @agent.service.stubs(:valid_to_marshal?).returns(false)
316
+ assert_equal [], @agent.connect_settings[:environment]
317
+ end
318
+
276
319
  def test_defer_start_if_resque_dispatcher_and_channel_manager_isnt_started_and_forkable
277
320
  NewRelic::LanguageSupport.stubs(:can_fork?).returns(true)
278
321
  NewRelic::Agent::PipeChannelManager.listener.stubs(:started?).returns(false)
279
322
 
280
323
  # :send_data_on_exit setting to avoid setting an at_exit
281
- with_config( :send_data_on_exit => false, :dispatcher => :resque ) do
324
+ with_config( :monitor_mode => true, :send_data_on_exit => false, :dispatcher => :resque ) do
282
325
  @agent.start
283
326
  end
284
327
 
@@ -288,8 +331,7 @@ module NewRelic
288
331
  def test_doesnt_defer_start_if_resque_dispatcher_and_channel_manager_started
289
332
  NewRelic::Agent::PipeChannelManager.listener.stubs(:started?).returns(true)
290
333
 
291
- # :send_data_on_exit setting to avoid setting an at_exit
292
- with_config( :send_data_on_exit => false, :dispatcher => :resque ) do
334
+ with_config( :monitor_mode => true, :send_data_on_exit => false, :dispatcher => :resque ) do
293
335
  @agent.start
294
336
  end
295
337
 
@@ -301,7 +343,7 @@ module NewRelic
301
343
  NewRelic::Agent::PipeChannelManager.listener.stubs(:started?).returns(false)
302
344
 
303
345
  # :send_data_on_exit setting to avoid setting an at_exit
304
- with_config( :send_data_on_exit => false, :dispatcher => :resque ) do
346
+ with_config( :monitor_mode => true, :send_data_on_exit => false, :dispatcher => :resque ) do
305
347
  @agent.start
306
348
  end
307
349
 
@@ -257,6 +257,14 @@ module NewRelic::Agent::Configuration
257
257
  @manager.remove_config(config)
258
258
  end
259
259
 
260
+ def test_config_stack_index_for
261
+ assert_equal 0, @manager.config_stack_index_for(EnvironmentSource)
262
+ assert_equal 1, @manager.config_stack_index_for(DefaultSource)
263
+ assert_equal nil, @manager.config_stack_index_for(ManualSource)
264
+ assert_equal nil, @manager.config_stack_index_for(ServerSource)
265
+ assert_equal nil, @manager.config_stack_index_for(YamlSource)
266
+ end
267
+
260
268
  class TestSource < ::Hash
261
269
  def test_config_accessor
262
270
  'some value'
@@ -57,6 +57,13 @@ class OrphanedConfigTest < Minitest::Test
57
57
  end
58
58
  end
59
59
 
60
+ # Remove any config keys that are annotated with the 'dynamic_name' setting
61
+ # This indicates that the names of these keys are constructed dynamically at
62
+ # runtime, so we don't expect any explicit references to them in code.
63
+ @default_keys.delete_if do |key_name|
64
+ NewRelic::Agent::Configuration::DEFAULTS[key_name][:dynamic_name]
65
+ end
66
+
60
67
  assert_empty @default_keys
61
68
  end
62
69
 
@@ -29,6 +29,7 @@ module NewRelic::Agent
29
29
 
30
30
  def setup
31
31
  NewRelic::Agent.reset_config
32
+ NewRelic::Agent.instance.stats_engine.clear_stats
32
33
  NewRelic::Agent.instance.events.clear
33
34
  @response = {}
34
35
 
@@ -164,19 +165,17 @@ module NewRelic::Agent
164
165
  def test_writes_metric
165
166
  with_default_timings
166
167
 
167
- expected_metric_name = "ClientApplication/#{REQUEST_CROSS_APP_ID}/all"
168
- NewRelic::Agent.instance.stats_engine.expects(:record_metrics). \
169
- with(expected_metric_name, APP_TIME)
170
-
171
168
  when_request_runs
169
+
170
+ assert_metrics_recorded(["ClientApplication/#{REQUEST_CROSS_APP_ID}/all"])
172
171
  end
173
172
 
174
173
  def test_doesnt_write_metric_if_id_blank
175
174
  with_default_timings
176
175
 
177
- NewRelic::Agent.instance.stats_engine.expects(:record_metrics).never
178
-
179
176
  when_request_runs(for_id(''))
177
+
178
+ assert_metrics_recorded_exclusive([])
180
179
  end
181
180
 
182
181
  def test_setting_response_headers_freezes_transaction_name
@@ -10,11 +10,16 @@ module NewRelic
10
10
  class HarvesterTest < Minitest::Test
11
11
 
12
12
  attr_reader :harvester
13
+
13
14
  def setup
14
15
  @after_forker = stub_everything
15
16
  @harvester = Harvester.new(nil, @after_forker)
16
17
  end
17
18
 
19
+ def test_doesnt_mark_started_process_on_initialize
20
+ assert_nil harvester.starting_pid
21
+ end
22
+
18
23
  def test_marks_started_in_process
19
24
  pretend_started_in_another_process
20
25
 
@@ -34,27 +39,27 @@ module NewRelic
34
39
  end
35
40
  end
36
41
 
37
- def test_doesnt_call_to_restart_by_default
42
+ def test_calls_to_restart_by_default
38
43
  pretend_started_in_another_process
39
- @after_forker.expects(:after_fork).never
44
+ @after_forker.expects(:after_fork).once
40
45
 
41
46
  harvester.on_transaction
42
47
  end
43
48
 
44
- def test_doesnt_call_to_restart_if_explicitly_disabled
49
+ def test_calls_to_restart_if_explicitly_enabled
45
50
  pretend_started_in_another_process
46
- @after_forker.expects(:after_fork).never
51
+ @after_forker.expects(:after_fork).once
47
52
 
48
- with_config(:restart_thread_in_children => false) do
53
+ with_config(:restart_thread_in_children => true) do
49
54
  harvester.on_transaction
50
55
  end
51
56
  end
52
57
 
53
- def test_calls_to_restart
58
+ def test_doesnt_call_to_restart_if_explicitly_disabled
54
59
  pretend_started_in_another_process
55
- @after_forker.expects(:after_fork).once
60
+ @after_forker.expects(:after_fork).never
56
61
 
57
- with_config(:restart_thread_in_children => true) do
62
+ with_config(:restart_thread_in_children => false) do
58
63
  harvester.on_transaction
59
64
  end
60
65
  end
@@ -204,25 +204,46 @@ class NewRelic::Agent::Instrumentation::ActionControllerSubscriberTest < Minites
204
204
  end
205
205
 
206
206
  def test_record_queue_time_metrics
207
- t0 = Time.now
208
- Time.stubs(:now).returns(t0)
207
+ t0 = freeze_time
209
208
  env = { 'HTTP_X_REQUEST_START' => (t0 - 5).to_f.to_s }
210
209
  NewRelic::Agent.instance.events.notify(:before_call, env)
211
210
 
212
- Time.stubs(:now).returns(t0, t0 + 2)
213
211
  @subscriber.start('process_action.action_controller', :id, @entry_payload)
212
+ advance_time(2)
214
213
  @subscriber.finish('process_action.action_controller', :id, @exit_payload)
215
214
 
216
- metric = @stats_engine.lookup_stats('WebFrontend/QueueTime')
217
- assert_equal 1, metric.call_count
218
- assert_in_delta(5.0, metric.total_call_time, 0.1)
215
+ assert_metrics_recorded(
216
+ 'WebFrontend/QueueTime' => {
217
+ :call_count => 1,
218
+ :total_call_time => 5.0
219
+ }
220
+ )
219
221
  end
220
222
 
221
223
  def test_dont_record_queue_time_if_no_header
222
224
  @subscriber.start('process_action.action_controller', :id, @entry_payload)
223
225
  @subscriber.finish('process_action.action_controller', :id, @exit_payload)
224
226
 
225
- assert_nil @stats_engine.lookup_stats('WebFrontend/QueueTime')
227
+ assert_metrics_not_recorded('WebFrontend/QueueTime')
228
+ end
229
+
230
+ def test_dont_record_queue_time_in_nested_transaction
231
+ t0 = freeze_time
232
+
233
+ env = { 'HTTP_X_REQUEST_START' => (t0 - 5).to_f.to_s }
234
+ NewRelic::Agent.instance.events.notify(:before_call, env)
235
+
236
+ @subscriber.start('process_action.action_controller', :id, @entry_payload)
237
+ @subscriber.start('process_action.action_controller', :id, @entry_payload)
238
+ @subscriber.finish('process_action.action_controller', :id, @exit_payload)
239
+ @subscriber.finish('process_action.action_controller', :id, @exit_payload)
240
+
241
+ assert_metrics_recorded(
242
+ 'WebFrontend/QueueTime' => {
243
+ :call_count => 1,
244
+ :total_call_time => 5.0
245
+ }
246
+ )
226
247
  end
227
248
 
228
249
  def test_records_request_params_in_txn
@@ -23,36 +23,47 @@ class NewRelic::Agent::Instrumentation::ControllerInstrumentationTest < Minitest
23
23
 
24
24
  def setup
25
25
  @object = TestObject.new
26
+ @dummy_headers = { :request => 'headers' }
26
27
  @txn_namer = NewRelic::Agent::Instrumentation:: \
27
28
  ControllerInstrumentation::TransactionNamer.new(@object)
28
29
  end
29
30
 
30
- def test_detect_upstream_wait_basic
31
- start_time = Time.now
32
- # should return the start time above by default
33
- @object.expects(:newrelic_request_headers).returns({:request => 'headers'}).twice
34
- NewRelic::Agent::Instrumentation::QueueTime.expects(:parse_frontend_timestamp) \
35
- .with({:request => 'headers'}, start_time).returns(start_time)
36
- assert_equal(start_time, @object.send(:_detect_upstream_wait, start_time))
31
+ def test_detect_upstream_wait_returns_transaction_start_time_if_nothing_from_headers
32
+ @object.stubs(:newrelic_request_headers).returns(@dummy_headers)
33
+ in_transaction do |txn|
34
+ NewRelic::Agent::Instrumentation::QueueTime.expects(:parse_frontend_timestamp) \
35
+ .with(@dummy_headers, txn.start_time).returns(txn.start_time)
36
+ assert_equal(txn.start_time, @object.send(:_detect_upstream_wait, txn))
37
+ end
37
38
  end
38
39
 
39
- def test_detect_upstream_wait_with_upstream
40
- start_time = Time.now
41
- runs_at = start_time + 1
42
- @object = TestObject.new
43
- @object.expects(:newrelic_request_headers).returns(true).twice
44
- NewRelic::Agent::Instrumentation::QueueTime.expects(:parse_frontend_timestamp) \
45
- .with(true, runs_at).returns(start_time)
46
- assert_equal(start_time, @object.send(:_detect_upstream_wait, runs_at))
40
+ def test_detect_upstream_wait_returns_parsed_timestamp_from_headers
41
+ @object.stubs(:newrelic_request_headers).returns(@dummy_headers)
42
+ in_transaction do |txn|
43
+ earlier_time = txn.start_time - 1
44
+ NewRelic::Agent::Instrumentation::QueueTime.expects(:parse_frontend_timestamp) \
45
+ .with(@dummy_headers, txn.start_time).returns(earlier_time)
46
+ assert_equal(earlier_time, @object.send(:_detect_upstream_wait, txn))
47
+ end
47
48
  end
48
49
 
49
50
  def test_detect_upstream_wait_swallows_errors
50
- start_time = Time.now
51
- # should return the start time above when an error is raised
52
- @object.expects(:newrelic_request_headers).returns({:request => 'headers'}).twice
53
- NewRelic::Agent::Instrumentation::QueueTime.expects(:parse_frontend_timestamp) \
54
- .with({:request => 'headers'}, start_time).raises("an error")
55
- assert_equal(start_time, @object.send(:_detect_upstream_wait, start_time))
51
+ @object.stubs(:newrelic_request_headers).returns(@dummy_headers)
52
+ in_transaction do |txn|
53
+ NewRelic::Agent::Instrumentation::QueueTime.expects(:parse_frontend_timestamp) \
54
+ .with(@dummy_headers, txn.start_time).raises("an error")
55
+ assert_equal(txn.start_time, @object.send(:_detect_upstream_wait, txn))
56
+ end
57
+ end
58
+
59
+ def test_detect_upsteam_wait_does_not_parse_timestamp_in_nested_transaction
60
+ @object.stubs(:newrelic_request_headers).returns(@dummy_headers)
61
+ in_transaction do |outer|
62
+ in_transaction do |inner|
63
+ NewRelic::Agent::Instrumentation::QueueTime.expects(:parse_frontend_timestamp).never
64
+ assert_equal(inner.start_time, @object.send(:_detect_upstream_wait, inner))
65
+ end
66
+ end
56
67
  end
57
68
 
58
69
  def test_transaction_name_calls_newrelic_metric_path
@@ -589,6 +589,20 @@ class NewRelicServiceTest < Minitest::Test
589
589
  assert_equal(spec1, metric_data.metric_spec)
590
590
  end
591
591
 
592
+ def test_valid_to_marshal
593
+ assert @service.valid_to_marshal?({})
594
+ end
595
+
596
+ def test_not_valid_to_marshal
597
+ @service.marshaller.stubs(:dump).raises(StandardError.new("Failed to marshal"))
598
+ refute @service.valid_to_marshal?({})
599
+ end
600
+
601
+ def test_not_valid_to_marshal_with_system_stack_error
602
+ @service.marshaller.stubs(:dump).raises(SystemStackError.new)
603
+ refute @service.valid_to_marshal?({})
604
+ end
605
+
592
606
  def build_stats_hash(items={})
593
607
  hash = NewRelic::Agent::StatsHash.new
594
608
  items.each do |key, value|
@@ -90,7 +90,7 @@ class NewRelic::Agent::RequestSamplerTest < Minitest::Test
90
90
  stats_hash.record(NewRelic::MetricSpec.new('WebFrontend/QueueTime'), 13)
91
91
  stats_hash.record(NewRelic::MetricSpec.new('External/allWeb'), 14)
92
92
  stats_hash.record(NewRelic::MetricSpec.new('Datastore/all'), 15)
93
- stats_hash.record(NewRelic::MetricSpec.new("GC/cumulative"), 16)
93
+ stats_hash.record(NewRelic::MetricSpec.new("GC/Transaction/all"), 16)
94
94
  stats_hash.record(NewRelic::MetricSpec.new('Memcache/allWeb'), 17)
95
95
 
96
96
  with_sampler_config do
@@ -111,7 +111,8 @@ class NewRelic::Agent::RequestSamplerTest < Minitest::Test
111
111
  stats_hash = NewRelic::Agent::StatsHash.new
112
112
  stats_hash.record(NewRelic::MetricSpec.new('External/allOther'), 12)
113
113
  stats_hash.record(NewRelic::MetricSpec.new('Datastore/all'), 13)
114
- stats_hash.record(NewRelic::MetricSpec.new('Memcache/allOther'), 14)
114
+ stats_hash.record(NewRelic::MetricSpec.new("GC/Transaction/all"), 14)
115
+ stats_hash.record(NewRelic::MetricSpec.new('Memcache/allOther'), 15)
115
116
 
116
117
  with_sampler_config do
117
118
  generate_request('name', :metrics => stats_hash)
@@ -119,7 +120,8 @@ class NewRelic::Agent::RequestSamplerTest < Minitest::Test
119
120
  event_data = single_sample[EVENT_DATA_INDEX]
120
121
  assert_equal 12, event_data["externalDuration"]
121
122
  assert_equal 13, event_data["databaseDuration"]
122
- assert_equal 14, event_data["memcacheDuration"]
123
+ assert_equal 14, event_data["gcCumulative"]
124
+ assert_equal 15, event_data["memcacheDuration"]
123
125
 
124
126
  assert_equal 1, event_data["databaseCallCount"]
125
127
  assert_equal 1, event_data["externalCallCount"]