newrelic_rpm 3.6.0.83 → 3.6.1.85.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. data/CHANGELOG +27 -0
  2. data/Gemfile +2 -7
  3. data/README.md +1 -1
  4. data/lib/new_relic/agent/agent.rb +3 -2
  5. data/lib/new_relic/agent/autostart.rb +56 -0
  6. data/lib/new_relic/agent/browser_monitoring.rb +19 -14
  7. data/lib/new_relic/agent/configuration/defaults.rb +12 -2
  8. data/lib/new_relic/agent/configuration/environment_source.rb +4 -1
  9. data/lib/new_relic/agent/cross_app_monitor.rb +2 -1
  10. data/lib/new_relic/agent/cross_app_tracing.rb +19 -10
  11. data/lib/new_relic/agent/error_collector.rb +5 -4
  12. data/lib/new_relic/agent/instrumentation/action_controller_subscriber.rb +204 -0
  13. data/lib/new_relic/agent/instrumentation/action_view_subscriber.rb +88 -0
  14. data/lib/new_relic/agent/instrumentation/active_record.rb +1 -1
  15. data/lib/new_relic/agent/instrumentation/active_record_helper.rb +1 -1
  16. data/lib/new_relic/agent/instrumentation/active_record_subscriber.rb +84 -0
  17. data/lib/new_relic/agent/instrumentation/browser_monitoring_timings.rb +3 -2
  18. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +104 -87
  19. data/lib/new_relic/agent/instrumentation/evented_subscriber.rb +91 -0
  20. data/lib/new_relic/agent/instrumentation/memcache.rb +4 -4
  21. data/lib/new_relic/agent/instrumentation/merb/errors.rb +4 -4
  22. data/lib/new_relic/agent/instrumentation/rack.rb +1 -1
  23. data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +20 -20
  24. data/lib/new_relic/agent/instrumentation/rails/errors.rb +5 -5
  25. data/lib/new_relic/agent/instrumentation/rails3/errors.rb +3 -3
  26. data/lib/new_relic/agent/instrumentation/rails4/action_controller.rb +3 -25
  27. data/lib/new_relic/agent/instrumentation/rails4/action_view.rb +2 -115
  28. data/lib/new_relic/agent/instrumentation/rails4/active_record.rb +2 -82
  29. data/lib/new_relic/agent/instrumentation/rails4/errors.rb +3 -4
  30. data/lib/new_relic/agent/method_tracer.rb +93 -56
  31. data/lib/new_relic/agent/null_logger.rb +6 -0
  32. data/lib/new_relic/agent/samplers/cpu_sampler.rb +9 -4
  33. data/lib/new_relic/agent/sql_sampler.rb +10 -6
  34. data/lib/new_relic/agent/stats_engine/metric_stats.rb +19 -3
  35. data/lib/new_relic/agent/stats_engine/transactions.rb +53 -34
  36. data/lib/new_relic/agent/system_info.rb +54 -0
  37. data/lib/new_relic/agent/thread.rb +2 -2
  38. data/lib/new_relic/agent/transaction/pop.rb +52 -0
  39. data/lib/new_relic/agent/transaction.rb +388 -0
  40. data/lib/new_relic/agent/transaction_info.rb +5 -13
  41. data/lib/new_relic/agent/transaction_sample_builder.rb +13 -20
  42. data/lib/new_relic/agent/transaction_sampler.rb +13 -15
  43. data/lib/new_relic/agent/uri_util.rb +35 -0
  44. data/lib/new_relic/agent.rb +54 -11
  45. data/lib/new_relic/build.rb +2 -2
  46. data/lib/new_relic/control/frameworks/rails.rb +0 -1
  47. data/lib/new_relic/control/frameworks/rails3.rb +2 -0
  48. data/lib/new_relic/control/frameworks/rails4.rb +0 -4
  49. data/lib/new_relic/control/instance_methods.rb +5 -19
  50. data/lib/new_relic/control/server_methods.rb +2 -0
  51. data/lib/new_relic/environment_report.rb +4 -34
  52. data/lib/new_relic/latest_changes.rb +1 -1
  53. data/lib/new_relic/local_environment.rb +0 -6
  54. data/lib/new_relic/metric_spec.rb +2 -2
  55. data/lib/new_relic/rack/error_collector.rb +6 -4
  56. data/lib/new_relic/transaction_sample.rb +7 -1
  57. data/lib/new_relic/version.rb +1 -1
  58. data/lib/newrelic_rpm.rb +2 -2
  59. data/newrelic.yml +20 -20
  60. data/test/config/test_control.rb +2 -2
  61. data/test/multiverse/suites/agent_only/audit_log_test.rb +1 -1
  62. data/test/multiverse/suites/agent_only/cross_application_tracing_test.rb +0 -2
  63. data/test/multiverse/suites/agent_only/logging_test.rb +1 -1
  64. data/test/multiverse/suites/agent_only/marshaling_test.rb +5 -3
  65. data/test/multiverse/suites/agent_only/rename_rule_test.rb +2 -0
  66. data/test/multiverse/suites/agent_only/set_transaction_name_test.rb +96 -0
  67. data/test/multiverse/suites/agent_only/testing_app.rb +1 -0
  68. data/test/multiverse/suites/rails/error_tracing_test.rb +17 -29
  69. data/test/multiverse/suites/rails/queue_time_test.rb +8 -2
  70. data/test/multiverse/suites/rails/view_instrumentation_test.rb +6 -3
  71. data/test/multiverse/suites/resque/instrumentation_test.rb +1 -1
  72. data/test/multiverse/suites/sinatra/sinatra_error_tracing_test.rb +8 -0
  73. data/test/new_relic/agent/agent/connect_test.rb +2 -1
  74. data/test/new_relic/agent/agent/start_test.rb +0 -10
  75. data/test/new_relic/agent/agent_logger_test.rb +15 -0
  76. data/test/new_relic/agent/agent_test_controller.rb +6 -2
  77. data/test/new_relic/agent/agent_test_controller_test.rb +20 -69
  78. data/test/new_relic/agent/autostart_test.rb +67 -0
  79. data/test/new_relic/agent/browser_monitoring_test.rb +60 -38
  80. data/test/new_relic/agent/configuration/environment_source_test.rb +19 -17
  81. data/test/new_relic/agent/cross_app_monitor_test.rb +8 -0
  82. data/test/new_relic/agent/error_collector/notice_error_test.rb +0 -5
  83. data/test/new_relic/agent/error_collector_test.rb +8 -9
  84. data/test/new_relic/agent/instrumentation/action_controller_subscriber_test.rb +228 -0
  85. data/test/new_relic/agent/instrumentation/action_view_subscriber_test.rb +18 -34
  86. data/test/new_relic/agent/instrumentation/active_record_instrumentation_test.rb +5 -5
  87. data/test/new_relic/agent/instrumentation/active_record_subscriber_test.rb +8 -9
  88. data/test/new_relic/agent/instrumentation/browser_monitoring_timings_test.rb +1 -1
  89. data/test/new_relic/agent/instrumentation/controller_instrumentation_test.rb +24 -38
  90. data/test/new_relic/agent/instrumentation/net_instrumentation_test.rb +126 -178
  91. data/test/new_relic/agent/instrumentation/rack_test.rb +1 -1
  92. data/test/new_relic/agent/instrumentation/task_instrumentation_test.rb +135 -151
  93. data/test/new_relic/agent/method_tracer/instance_methods/trace_execution_scoped_test.rb +153 -81
  94. data/test/new_relic/agent/method_tracer_test.rb +42 -33
  95. data/test/new_relic/agent/mock_scope_listener.rb +4 -4
  96. data/test/new_relic/agent/pipe_channel_manager_test.rb +4 -2
  97. data/test/new_relic/agent/rpm_agent_test.rb +86 -89
  98. data/test/new_relic/agent/sql_sampler_test.rb +18 -19
  99. data/test/new_relic/agent/stats_engine/gc_profiler_test.rb +5 -8
  100. data/test/new_relic/agent/stats_engine/metric_stats_test.rb +20 -8
  101. data/test/new_relic/agent/stats_engine/samplers_test.rb +31 -14
  102. data/test/new_relic/agent/stats_engine_test.rb +53 -60
  103. data/test/new_relic/agent/thread_test.rb +7 -7
  104. data/test/new_relic/agent/transaction/pop_test.rb +96 -0
  105. data/test/new_relic/agent/transaction_info_test.rb +6 -17
  106. data/test/new_relic/agent/transaction_sample_builder_test.rb +10 -18
  107. data/test/new_relic/agent/transaction_sampler_test.rb +80 -75
  108. data/test/new_relic/agent/{instrumentation/metric_frame_test.rb → transaction_test.rb} +76 -42
  109. data/test/new_relic/agent/uri_util_test.rb +75 -0
  110. data/test/new_relic/agent_test.rb +115 -9
  111. data/test/test_helper.rb +138 -9
  112. data.tar.gz.sig +0 -0
  113. metadata +37 -74
  114. metadata.gz.sig +0 -0
  115. data/lib/new_relic/agent/instrumentation/metric_frame/pop.rb +0 -84
  116. data/lib/new_relic/agent/instrumentation/metric_frame.rb +0 -353
  117. data/test/new_relic/agent/instrumentation/metric_frame/pop_test.rb +0 -175
  118. data/test/test_contexts.rb +0 -34
@@ -29,13 +29,11 @@ class NewRelic::Agent::BrowserMonitoringTest < Test::Unit::TestCase
29
29
  NewRelic::Agent.instance.instance_eval do
30
30
  @beacon_configuration = NewRelic::Agent::BeaconConfiguration.new
31
31
  end
32
+ end
32
33
 
33
34
  def teardown
34
- Thread.current[:last_metric_frame] = nil
35
35
  NewRelic::Agent::TransactionInfo.clear
36
36
  NewRelic::Agent.config.remove_config(@config)
37
- end
38
-
39
37
  mocha_teardown
40
38
  end
41
39
 
@@ -208,9 +206,11 @@ var e=document.createElement("script");'
208
206
  end
209
207
 
210
208
  def test_browser_monitoring_transaction_name_basic
211
- mock = mock('transaction sample')
209
+ mock = stub_everything('transaction info')
212
210
  NewRelic::Agent::TransactionInfo.set(mock)
213
- mock.stubs(:transaction_name).returns('a transaction name')
211
+ txn = NewRelic::Agent::Transaction.new
212
+ txn.name = 'a transaction name'
213
+ mock.stubs(:transaction).returns(txn)
214
214
 
215
215
  assert_equal('a transaction name', browser_monitoring_transaction_name, "should take the value from the thread local")
216
216
  end
@@ -219,7 +219,7 @@ var e=document.createElement("script");'
219
219
  mock = mock('transaction sample')
220
220
  NewRelic::Agent::TransactionInfo.set(mock)
221
221
 
222
- mock.stubs(:transaction_name).returns('')
222
+ mock.stubs(:transaction).returns(stub(:name => ''))
223
223
  assert_equal('', browser_monitoring_transaction_name, "should take the value even when it is empty")
224
224
  end
225
225
 
@@ -266,49 +266,59 @@ var e=document.createElement("script");'
266
266
  end
267
267
 
268
268
  def test_browser_monitoring_queue_time_zero
269
- frame = Thread.current[:last_metric_frame] = mock('metric frame')
270
- frame.expects(:queue_time).returns(0.0)
271
- assert_equal(0.0, browser_monitoring_queue_time, 'should return zero when there is zero queue time')
269
+ in_transaction do
270
+ NewRelic::Agent::Transaction.current.expects(:queue_time).returns(0.0)
271
+ assert_equal(0.0, browser_monitoring_queue_time,
272
+ 'should return zero when there is zero queue time')
273
+ end
272
274
  end
273
275
 
274
276
  def test_browser_monitoring_queue_time_ducks
275
- frame = Thread.current[:last_metric_frame] = mock('metric frame')
276
- frame.expects(:queue_time).returns('a duck')
277
- assert_equal(0.0, browser_monitoring_queue_time, 'should return zero when there is an incorrect queue time')
277
+ in_transaction do
278
+ NewRelic::Agent::Transaction.current.expects(:queue_time) \
279
+ .returns('a duck')
280
+ assert_equal(0.0, browser_monitoring_queue_time,
281
+ 'should return zero when there is an incorrect queue time')
282
+ end
278
283
  end
279
284
 
280
285
  def test_browser_monitoring_queue_time_nonzero
281
- frame = Thread.current[:last_metric_frame] = mock('metric frame')
282
- frame.expects(:queue_time).returns(3.00002)
283
- assert_equal(3000, browser_monitoring_queue_time, 'should return a rounded time')
286
+ in_transaction do
287
+ NewRelic::Agent::Transaction.current.expects(:queue_time) \
288
+ .returns(3.00002)
289
+ assert_equal(3000, browser_monitoring_queue_time,
290
+ 'should return a rounded time')
291
+ end
284
292
  end
285
293
 
286
294
  def test_footer_js_string_basic
287
295
  # mocking this because JRuby thinks that Time.now - Time.now
288
296
  # always takes at least 1ms
289
297
  self.expects(:browser_monitoring_app_time).returns(0)
290
- frame = Thread.current[:last_metric_frame] = mock('metric frame')
291
- user_attributes = {:user => "user", :account => "account", :product => "product"}
292
- frame.expects(:user_attributes).returns(user_attributes).at_least_once
293
- frame.expects(:queue_time).returns(0)
294
-
295
- sample = mock('transaction info')
296
- NewRelic::Agent::TransactionInfo.set(sample)
297
-
298
- sample.stubs(:start_time).returns(Time.at(100))
299
- sample.stubs(:guid).returns('ABC')
300
- sample.stubs(:transaction_name).returns('most recent transaction')
301
- sample.stubs(:include_guid?).returns(true)
302
- sample.stubs(:duration).returns(12.0)
303
- sample.stubs(:token).returns('0123456789ABCDEF')
304
-
305
- self.expects(:obfuscate).with(NewRelic::Agent.instance.beacon_configuration, 'most recent transaction').returns('most recent transaction')
306
- self.expects(:obfuscate).with(NewRelic::Agent.instance.beacon_configuration, 'user').returns('user')
307
- self.expects(:obfuscate).with(NewRelic::Agent.instance.beacon_configuration, 'account').returns('account')
308
- self.expects(:obfuscate).with(NewRelic::Agent.instance.beacon_configuration, 'product').returns('product')
309
-
310
- value = footer_js_string(NewRelic::Agent.instance.beacon_configuration)
311
- assert_equal(%'<script type="text/javascript">if (!NREUMQ.f) { NREUMQ.f=function() {\nNREUMQ.push(["load",new Date().getTime()]);\nvar e=document.createElement("script");\ne.type="text/javascript";\ne.src=(("http:"===document.location.protocol)?"http:":"https:") + "//" +\n "this_is_my_file";\ndocument.body.appendChild(e);\nif(NREUMQ.a)NREUMQ.a();\n};\nNREUMQ.a=window.onload;window.onload=NREUMQ.f;\n};\nNREUMQ.push(["nrfj","beacon","browserKey","5, 6","most recent transaction",0,0,new Date().getTime(),"ABC","0123456789ABCDEF","user","account","product"]);</script>', value, "should return the javascript given some default values")
298
+ in_transaction do
299
+ txn = NewRelic::Agent::Transaction.current
300
+ user_attributes = {:user => "user", :account => "account", :product => "product"}
301
+ txn.expects(:user_attributes).returns(user_attributes).at_least_once
302
+ txn.expects(:queue_time).returns(0)
303
+ txn.name = 'most recent transaction'
304
+
305
+ sample = stub_everything('transaction info',
306
+ :start_time => Time.at(100),
307
+ :guid => 'ABC',
308
+ :transaction => txn,
309
+ :include_guid? => true,
310
+ :duration => 12.0,
311
+ :token => '0123456789ABCDEF')
312
+ NewRelic::Agent::TransactionInfo.set(sample)
313
+
314
+ self.expects(:obfuscate).with(NewRelic::Agent.instance.beacon_configuration, 'most recent transaction').returns('most recent transaction')
315
+ self.expects(:obfuscate).with(NewRelic::Agent.instance.beacon_configuration, 'user').returns('user')
316
+ self.expects(:obfuscate).with(NewRelic::Agent.instance.beacon_configuration, 'account').returns('account')
317
+ self.expects(:obfuscate).with(NewRelic::Agent.instance.beacon_configuration, 'product').returns('product')
318
+
319
+ value = footer_js_string(NewRelic::Agent.instance.beacon_configuration)
320
+ assert_equal(%'<script type="text/javascript">if (!NREUMQ.f) { NREUMQ.f=function() {\nNREUMQ.push(["load",new Date().getTime()]);\nvar e=document.createElement("script");\ne.type="text/javascript";\ne.src=(("http:"===document.location.protocol)?"http:":"https:") + "//" +\n "this_is_my_file";\ndocument.body.appendChild(e);\nif(NREUMQ.a)NREUMQ.a();\n};\nNREUMQ.a=window.onload;window.onload=NREUMQ.f;\n};\nNREUMQ.push(["nrfj","beacon","browserKey","5, 6","most recent transaction",0,0,new Date().getTime(),"ABC","0123456789ABCDEF","user","account","product"]);</script>', value, "should return the javascript given some default values")
321
+ end
312
322
  end
313
323
 
314
324
  def test_html_safe_if_needed_unsafed
@@ -386,10 +396,22 @@ var e=document.createElement("script");'
386
396
  assert_equal expected_payload, response['X-NewRelic-App-Server-Metrics'].strip
387
397
  end
388
398
 
399
+ def test_freezes_transaction_name_when_footer_is_written
400
+ with_config(:license_key => 'a' * 13) do
401
+ in_transaction do
402
+ assert !NewRelic::Agent::Transaction.current.name_frozen?
403
+ browser_timing_footer
404
+ assert NewRelic::Agent::Transaction.current.name_frozen?
405
+ end
406
+ end
407
+ end
408
+
389
409
  def mobile_transaction(request=nil)
390
410
  request ||= Rack::Request.new('X-NewRelic-Mobile-Trace' => 'true')
391
411
  response = Rack::Response.new
392
- txn_data = OpenStruct.new(:transaction_name => 'a transaction name',
412
+ txn = NewRelic::Agent::Transaction.new
413
+ txn.name = 'a transaction name'
414
+ txn_data = OpenStruct.new(:transaction => txn,
393
415
  :start_time => 5,
394
416
  :force_persist_sample? => false)
395
417
  NewRelic::Agent::TransactionInfo.set(txn_data)
@@ -34,24 +34,26 @@ module NewRelic::Agent::Configuration
34
34
  assert_applied_symbol 'NEWRELIC_FRAMEWORK', 'framework'
35
35
  end
36
36
 
37
- def test_environment_booleans_truths_are_applied
38
- ENV['NEWRELIC_ENABLE'] = 'true'
39
- assert EnvironmentSource.new[:agent_enabled]
40
- ENV['NEWRELIC_ENABLE'] = 'on'
41
- assert EnvironmentSource.new[:agent_enabled]
42
- ENV['NEWRELIC_ENABLE'] = 'yes'
43
- assert EnvironmentSource.new[:agent_enabled]
44
- ENV.delete('NEWRELIC_ENABLE')
45
- end
37
+ %w| NEWRELIC_ENABLE NEWRELIC_ENABLED NEW_RELIC_ENABLE NEW_RELIC_ENABLED |.each do |var|
38
+ define_method("test_environment_booleans_truths_are_applied_to_#{var}") do
39
+ ENV[var] = 'true'
40
+ assert EnvironmentSource.new[:agent_enabled]
41
+ ENV[var] = 'on'
42
+ assert EnvironmentSource.new[:agent_enabled]
43
+ ENV[var] = 'yes'
44
+ assert EnvironmentSource.new[:agent_enabled]
45
+ ENV.delete(var)
46
+ end
46
47
 
47
- def test_environment_booleans_falsehoods_are_applied
48
- ENV['NEWRELIC_ENABLE'] = 'false'
49
- assert !EnvironmentSource.new[:agent_enabled]
50
- ENV['NEWRELIC_ENABLE'] = 'off'
51
- assert !EnvironmentSource.new[:agent_enabled]
52
- ENV['NEWRELIC_ENABLE'] = 'no'
53
- assert !EnvironmentSource.new[:agent_enabled]
54
- ENV.delete('NEWRELIC_ENABLE')
48
+ define_method("test_environment_booleans_falsehoods_are_applied_to_#{var}") do
49
+ ENV[var] = 'false'
50
+ assert !EnvironmentSource.new[:agent_enabled]
51
+ ENV[var] = 'off'
52
+ assert !EnvironmentSource.new[:agent_enabled]
53
+ ENV[var] = 'no'
54
+ assert !EnvironmentSource.new[:agent_enabled]
55
+ ENV.delete(var)
56
+ end
55
57
  end
56
58
 
57
59
  def test_set_log_config_from_environment
@@ -198,6 +198,14 @@ module NewRelic::Agent
198
198
  assert_equal str, decoded
199
199
  end
200
200
 
201
+ def test_setting_response_headers_freezes_transaction_name
202
+ in_transaction do
203
+ assert !NewRelic::Agent::Transaction.current.name_frozen?
204
+ when_request_runs
205
+ assert NewRelic::Agent::Transaction.current.name_frozen?
206
+ end
207
+ end
208
+
201
209
  #
202
210
  # Helpers
203
211
  #
@@ -175,10 +175,6 @@ class NewRelic::Agent::ErrorCollector::NoticeErrorTest < Test::Unit::TestCase
175
175
  error = nil
176
176
  with_error_collector_config(:'error_collector.enabled' => true) do |error_collector|
177
177
  error_collector.expects(:error_is_ignored?).with(error).returns(false)
178
- # we increment it for the case that someone calls
179
- # NewRelic::Agent.notice_error(foo) # foo is nil
180
- # (which is probably not a good idea but is the existing api)
181
- error_collector.expects(:increment_error_count!)
182
178
  assert error_collector.should_exit_notice_error?(error)
183
179
  end
184
180
  end
@@ -195,7 +191,6 @@ class NewRelic::Agent::ErrorCollector::NoticeErrorTest < Test::Unit::TestCase
195
191
  error = mocked_error
196
192
  with_error_collector_config(:'error_collector.enabled' => true) do |error_collector|
197
193
  error_collector.expects(:error_is_ignored?).with(error).returns(false)
198
- error_collector.expects(:increment_error_count!)
199
194
  assert !error_collector.should_exit_notice_error?(error)
200
195
  end
201
196
  end
@@ -197,13 +197,12 @@ class NewRelic::Agent::ErrorCollectorTest < Test::Unit::TestCase
197
197
  end
198
198
 
199
199
  def test_increment_error_count_record_summary_and_txn_metric
200
- txn_info = NewRelic::Agent::TransactionInfo.new
201
- txn_info.transaction_name = 'Controller/class/method'
202
- NewRelic::Agent::TransactionInfo.stubs(:get).returns(txn_info)
203
-
204
200
  stats_engine = NewRelic::Agent.instance.stats_engine
205
201
  stats_engine.reset_stats
206
- @error_collector.increment_error_count!(StandardError.new('Boo'))
202
+
203
+ @error_collector.increment_error_count!(StandardError.new('Boo'),
204
+ :metric => 'Controller/class/method')
205
+
207
206
  assert_equal(1, stats_engine.get_stats('Errors/all').call_count,
208
207
  'Missing Errors/all metric')
209
208
  assert_equal(1, stats_engine.get_stats('Errors/Controller/class/method').call_count,
@@ -211,12 +210,12 @@ class NewRelic::Agent::ErrorCollectorTest < Test::Unit::TestCase
211
210
  end
212
211
 
213
212
  def test_doesnt_increment_error_count_on_transaction_if_nameless
214
- txn_info = NewRelic::Agent::TransactionInfo.new
215
- NewRelic::Agent::TransactionInfo.stubs(:get).returns(txn_info)
216
-
217
213
  stats_engine = NewRelic::Agent.instance.stats_engine
218
214
  stats_engine.reset_stats
219
- @error_collector.increment_error_count!(StandardError.new('Boo'))
215
+
216
+ @error_collector.increment_error_count!(StandardError.new('Boo'),
217
+ :metric => '(unknown)')
218
+
220
219
  assert_equal(0, stats_engine.get_stats('Errors/(unknown)').call_count)
221
220
  end
222
221
 
@@ -0,0 +1,228 @@
1
+ # encoding: utf-8
2
+ # This file is distributed under New Relic's license terms.
3
+ # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
+ require File.expand_path(File.join(File.dirname(__FILE__),'..','..','..','test_helper'))
5
+ require 'new_relic/agent/instrumentation/action_controller_subscriber'
6
+
7
+ class NewRelic::Agent::Instrumentation::ActionControllerSubscriberTest < Test::Unit::TestCase
8
+ class TestController
9
+ include NewRelic::Agent::Instrumentation::ControllerInstrumentation
10
+
11
+ def self.controller_path
12
+ 'test'
13
+ end
14
+
15
+ def action_name
16
+ 'test'
17
+ end
18
+
19
+ newrelic_ignore :only => :ignored_action
20
+ newrelic_ignore_apdex :only => :ignored_apdex
21
+ newrelic_ignore_enduser :only => :ignored_enduser
22
+ end
23
+
24
+ def setup
25
+ @subscriber = NewRelic::Agent::Instrumentation::ActionControllerSubscriber.new
26
+ NewRelic::Agent.instance.stats_engine.clear_stats
27
+ @entry_payload = {
28
+ :controller => TestController.to_s,
29
+ :action => 'index',
30
+ :format => :html,
31
+ :method => 'GET',
32
+ :path => '/tests',
33
+ :params => { :controller => 'test_controller', :action => 'index' },
34
+ }
35
+ @exit_payload = @entry_payload.merge(:status => 200, :view_runtime => 5.0,
36
+ :db_runtime => 0.5 )
37
+ @stats_engine = NewRelic::Agent.instance.stats_engine
38
+ @stats_engine.clear_stats
39
+ NewRelic::Agent.manual_start
40
+ end
41
+
42
+ def teardown
43
+ NewRelic::Agent.shutdown
44
+ @stats_engine.clear_stats
45
+ end
46
+
47
+ def test_record_controller_metrics
48
+ t0 = Time.now
49
+ Time.stubs(:now).returns(t0, t0 + 2)
50
+
51
+ @subscriber.start('process_action.action_controller', :id, @entry_payload)
52
+ @subscriber.finish('process_action.action_controller', :id, @exit_payload)
53
+
54
+ assert_equal 1, @stats_engine.lookup_stats('Controller/test/index').call_count
55
+ assert_equal 1, @stats_engine.lookup_stats('HttpDispatcher').call_count
56
+ assert_equal 2.0, @stats_engine.lookup_stats('Controller/test/index').total_call_time
57
+ assert_equal 2.0, @stats_engine.lookup_stats('HttpDispatcher').total_call_time
58
+ end
59
+
60
+ def test_record_apdex_metrics
61
+ t0 = Time.now
62
+ Time.stubs(:now).returns(t0, t0 + 1.5)
63
+
64
+ @subscriber.start('process_action.action_controller', :id, @entry_payload)
65
+ @subscriber.finish('process_action.action_controller', :id, @exit_payload)
66
+
67
+ apdex_metric = @stats_engine.lookup_stats('Apdex/test/index')
68
+ apdex_rollup_metric = @stats_engine.lookup_stats('Apdex')
69
+ assert_equal 0, apdex_metric.apdex_f
70
+ assert_equal 0, apdex_rollup_metric.apdex_f
71
+ assert_equal 1, apdex_metric.apdex_t
72
+ assert_equal 1, apdex_rollup_metric.apdex_t
73
+ assert_equal 0, apdex_metric.apdex_s
74
+ assert_equal 0, apdex_rollup_metric.apdex_s
75
+ end
76
+
77
+ def test_records_scoped_metrics_for_evented_child_txn
78
+ @subscriber.start('process_action.action_controller', :id, @entry_payload)
79
+ @subscriber.start('process_action.action_controller', :id, @entry_payload \
80
+ .merge(:action => 'child', :path => '/child'))
81
+ @subscriber.finish('process_action.action_controller', :id, @exit_payload \
82
+ .merge(:action => 'child', :path => '/child'))
83
+ @subscriber.finish('process_action.action_controller', :id, @exit_payload)
84
+
85
+ assert_equal(1, @stats_engine.lookup_stats('Controller/test/child',
86
+ 'Controller/test/index').call_count)
87
+ end
88
+
89
+ def test_records_scoped_metrics_for_traced_child_txn
90
+ controller = TestController.new
91
+ controller.perform_action_with_newrelic_trace(:category => :controller,
92
+ :name => 'index',
93
+ :class_name => 'test') do
94
+ @subscriber.start('process_action.action_controller', :id, @entry_payload \
95
+ .merge(:action => 'child', :path => '/child'))
96
+ @subscriber.finish('process_action.action_controller', :id, @exit_payload \
97
+ .merge(:action => 'child', :path => '/child'))
98
+ end
99
+
100
+ assert_equal 1, @stats_engine.lookup_stats('Controller/test/child',
101
+ 'Controller/test/index').call_count
102
+ end
103
+
104
+ def test_record_nothing_for_ignored_action
105
+ @entry_payload[:action] = 'ignored_action'
106
+ @exit_payload[:action] = 'ignored_action'
107
+ @subscriber.start('process_action.action_controller', :id, @entry_payload)
108
+ @subscriber.finish('process_action.action_controller', :id, @exit_payload)
109
+
110
+ assert_nil @stats_engine.lookup_stats('Controller/test/ignored_action')
111
+ assert_nil @stats_engine.lookup_stats('Apdex/test/ignored_action')
112
+ assert_nil @stats_engine.lookup_stats('Apdex')
113
+ assert_nil @stats_engine.lookup_stats('HttpDispatcher')
114
+ end
115
+
116
+ def test_record_no_apdex_metric_for_ignored_apdex_action
117
+ @entry_payload[:action] = 'ignored_apdex'
118
+ @exit_payload[:action] = 'ignored_apdex'
119
+ @subscriber.start('process_action.action_controller', :id, @entry_payload)
120
+ @subscriber.finish('process_action.action_controller', :id, @exit_payload)
121
+
122
+ assert @stats_engine.lookup_stats('Controller/test/ignored_apdex')
123
+ assert_nil @stats_engine.lookup_stats('Apdex/test/ignored_apdex')
124
+ assert_nil @stats_engine.lookup_stats('Apdex')
125
+ assert @stats_engine.lookup_stats('HttpDispatcher')
126
+ end
127
+
128
+ def test_ignore_end_user
129
+ @entry_payload[:action] = 'ignored_enduser'
130
+ @exit_payload[:action] = 'ignored_enduser'
131
+ @subscriber.start('process_action.action_controller', :id, @entry_payload)
132
+ @subscriber.finish('process_action.action_controller', :id, @exit_payload)
133
+
134
+ assert NewRelic::Agent::TransactionInfo.get.ignore_end_user?
135
+ end
136
+
137
+ def test_record_busy_time
138
+ @subscriber.start('process_action.action_controller', :id, @entry_payload)
139
+ @subscriber.finish('process_action.action_controller', :id, @exit_payload)
140
+ NewRelic::Agent::BusyCalculator.harvest_busy
141
+
142
+ assert_equal 1, @stats_engine.lookup_stats('Instance/Busy').call_count
143
+ end
144
+
145
+ def test_creates_transaction
146
+ NewRelic::Agent.instance.transaction_sampler.reset!
147
+ @subscriber.start('process_action.action_controller', :id, @entry_payload)
148
+ @subscriber.finish('process_action.action_controller', :id, @exit_payload)
149
+
150
+ assert_equal('Controller/test/index',
151
+ NewRelic::Agent.instance.transaction_sampler \
152
+ .last_sample.params[:path])
153
+ assert_equal('Controller/test/index',
154
+ NewRelic::Agent.instance.transaction_sampler \
155
+ .last_sample.root_segment.called_segments[0].metric_name)
156
+ end
157
+
158
+ def test_applies_txn_name_rules
159
+ rule = NewRelic::Agent::RulesEngine::Rule.new('match_expression' => 'test',
160
+ 'replacement' => 'taste')
161
+ NewRelic::Agent.instance.transaction_rules << rule
162
+ @subscriber.start('process_action.action_controller', :id, @entry_payload)
163
+ @subscriber.finish('process_action.action_controller', :id, @exit_payload)
164
+
165
+ assert NewRelic::Agent.instance.stats_engine \
166
+ .lookup_stats('Controller/taste/index')
167
+ assert_nil NewRelic::Agent.instance.stats_engine \
168
+ .lookup_stats('Controller/test/index')
169
+ ensure
170
+ NewRelic::Agent.instance.instance_variable_set(:@transaction_rules,
171
+ NewRelic::Agent::RulesEngine.new)
172
+ end
173
+
174
+ def test_record_queue_time_metrics
175
+ t0 = Time.now
176
+ Time.stubs(:now).returns(t0)
177
+ env = { 'HTTP_X_REQUEST_START' => (t0 - 5).to_f.to_s }
178
+ NewRelic::Agent.instance.events.notify(:before_call, env)
179
+
180
+ Time.stubs(:now).returns(t0, t0 + 2)
181
+ @subscriber.start('process_action.action_controller', :id, @entry_payload)
182
+ @subscriber.finish('process_action.action_controller', :id, @exit_payload)
183
+
184
+ metric = @stats_engine.lookup_stats('WebFrontend/QueueTime')
185
+ assert_equal 1, metric.call_count
186
+ assert_in_delta(5.0, metric.total_call_time, 0.1)
187
+ end
188
+
189
+ def test_dont_record_queue_time_if_no_header
190
+ @subscriber.start('process_action.action_controller', :id, @entry_payload)
191
+ @subscriber.finish('process_action.action_controller', :id, @exit_payload)
192
+
193
+ assert_nil @stats_engine.lookup_stats('WebFrontend/QueueTime')
194
+ end
195
+
196
+ def test_records_request_params_in_txn
197
+ NewRelic::Agent.instance.transaction_sampler.reset!
198
+ @entry_payload[:params]['number'] = '666'
199
+ @subscriber.start('process_action.action_controller', :id, @entry_payload)
200
+ @subscriber.finish('process_action.action_controller', :id, @exit_payload)
201
+
202
+ assert_equal('666',
203
+ NewRelic::Agent.instance.transaction_sampler \
204
+ .last_sample.params[:request_params]['number'])
205
+ end
206
+
207
+ def test_records_filtered_request_params_in_txn
208
+ NewRelic::Agent.instance.transaction_sampler.reset!
209
+ @entry_payload[:params]['password'] = 'secret'
210
+ @subscriber.start('process_action.action_controller', :id, @entry_payload)
211
+ @subscriber.finish('process_action.action_controller', :id, @exit_payload)
212
+
213
+ assert_equal('[FILTERED]',
214
+ NewRelic::Agent.instance.transaction_sampler \
215
+ .last_sample.params[:request_params]['password'])
216
+ end
217
+
218
+ def test_records_custom_parameters_in_txn
219
+ NewRelic::Agent.instance.transaction_sampler.reset!
220
+ @subscriber.start('process_action.action_controller', :id, @entry_payload)
221
+ NewRelic::Agent.add_custom_parameters('number' => '666')
222
+ @subscriber.finish('process_action.action_controller', :id, @exit_payload)
223
+
224
+ assert_equal('666',
225
+ NewRelic::Agent.instance.transaction_sampler \
226
+ .last_sample.params[:custom_params]['number'])
227
+ end
228
+ end if ::Rails::VERSION::MAJOR.to_i >= 4
@@ -2,7 +2,7 @@
2
2
  # This file is distributed under New Relic's license terms.
3
3
  # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
4
  require File.expand_path(File.join(File.dirname(__FILE__),'..','..','..','test_helper'))
5
- require 'new_relic/agent/instrumentation/rails4/action_view'
5
+ require 'new_relic/agent/instrumentation/action_view_subscriber'
6
6
 
7
7
  class NewRelic::Agent::Instrumentation::ActionViewSubscriberTest < Test::Unit::TestCase
8
8
  def setup
@@ -128,22 +128,19 @@ class NewRelic::Agent::Instrumentation::ActionViewSubscriberTest < Test::Unit::T
128
128
 
129
129
  def test_records_scoped_metric
130
130
  params = { :identifier => '/root/app/views/model/index.html.erb' }
131
- t0 = Time.now
132
- Time.stubs(:now).returns(t0, t0, t0 + 2, t0 + 2)
133
- @stats_engine.start_transaction('test_txn')
134
131
 
135
- @subscriber.start('render_template.action_view', :id, params)
136
- @subscriber.start('!render_template.action_view', :id,
137
- :virtual_path => 'model/index')
138
- @subscriber.finish('!render_template.action_view', :id,
139
- :virtual_path => 'model/index')
140
- @subscriber.finish('render_template.action_view', :id, params)
132
+ in_transaction('test_txn') do
133
+ @subscriber.start('render_template.action_view', :id, params)
134
+ @subscriber.start('!render_template.action_view', :id,
135
+ :virtual_path => 'model/index')
136
+ @subscriber.finish('!render_template.action_view', :id,
137
+ :virtual_path => 'model/index')
138
+ @subscriber.finish('render_template.action_view', :id, params)
139
+ end
141
140
 
142
141
  metric = @stats_engine.lookup_stats('View/model/index.html.erb/Rendering',
143
142
  'test_txn')
144
143
  assert_equal(1, metric.call_count)
145
- assert_equal(2.0, metric.total_call_time)
146
-
147
144
  end
148
145
 
149
146
  def test_records_nothing_if_tracing_disabled
@@ -161,7 +158,7 @@ class NewRelic::Agent::Instrumentation::ActionViewSubscriberTest < Test::Unit::T
161
158
  def test_creates_txn_segment_for_simple_render
162
159
  params = { :identifier => '/root/app/views/model/index.html.erb' }
163
160
 
164
- sampler = in_transaction do
161
+ in_transaction do
165
162
  @subscriber.start('render_template.action_view', :id, params)
166
163
  @subscriber.start('!render_template.action_view', :id,
167
164
  :virtual_path => 'model/index')
@@ -171,6 +168,7 @@ class NewRelic::Agent::Instrumentation::ActionViewSubscriberTest < Test::Unit::T
171
168
  end
172
169
 
173
170
  last_segment = nil
171
+ sampler = NewRelic::Agent.instance.transaction_sampler
174
172
  sampler.last_sample.root_segment.each_segment{|s| last_segment = s }
175
173
  NewRelic::Agent.shutdown
176
174
 
@@ -179,7 +177,7 @@ class NewRelic::Agent::Instrumentation::ActionViewSubscriberTest < Test::Unit::T
179
177
  end
180
178
 
181
179
  def test_creates_nested_partial_segment_within_render_segment
182
- sampler = in_transaction do
180
+ in_transaction do
183
181
  @subscriber.start('render_template.action_view', :id,
184
182
  :identifier => 'model/index.html.erb')
185
183
  @subscriber.start('!render_template.action_view', :id,
@@ -193,12 +191,13 @@ class NewRelic::Agent::Instrumentation::ActionViewSubscriberTest < Test::Unit::T
193
191
  @subscriber.finish('render_partial.action_view', :id,
194
192
  :identifier => '/root/app/views/model/_list.html.erb')
195
193
  @subscriber.finish('!render_template.action_view', :id,
196
- :virtual_path => 'model/index')
194
+ :virtual_path => 'model/index')
197
195
  @subscriber.finish('render_template.action_view', :id,
198
196
  :identifier => 'model/index.html.erb')
199
197
  end
200
198
 
201
- template_segment = sampler.last_sample.root_segment.called_segments[0].called_segments[0]
199
+ sampler = NewRelic::Agent.instance.transaction_sampler
200
+ template_segment = sampler.last_sample.root_segment.called_segments[0]
202
201
  partial_segment = template_segment.called_segments[0]
203
202
 
204
203
  assert_equal('View/model/index.html.erb/Rendering',
@@ -208,7 +207,7 @@ class NewRelic::Agent::Instrumentation::ActionViewSubscriberTest < Test::Unit::T
208
207
  end
209
208
 
210
209
  def test_creates_nodes_for_each_in_a_collection_event
211
- sampler = in_transaction do
210
+ in_transaction do
212
211
  @subscriber.start('render_collection.action_view', :id,
213
212
  :identifier => '/root/app/views/model/_list.html.erb',
214
213
  :count => 3)
@@ -229,26 +228,11 @@ class NewRelic::Agent::Instrumentation::ActionViewSubscriberTest < Test::Unit::T
229
228
  :count => 3)
230
229
  end
231
230
 
232
- template_segment = sampler.last_sample.root_segment.called_segments[0]
233
- partial_segments = template_segment.called_segments
231
+ sampler = NewRelic::Agent.instance.transaction_sampler
232
+ partial_segments = sampler.last_sample.root_segment.called_segments
234
233
 
235
234
  assert_equal 3, partial_segments.size
236
235
  assert_equal('View/model/_list.html.erb/Partial',
237
236
  partial_segments[0].metric_name)
238
237
  end
239
-
240
- def in_transaction
241
- NewRelic::Agent.manual_start
242
- NewRelic::Agent.instance.stats_engine.start_transaction('test')
243
- sampler = NewRelic::Agent.instance.transaction_sampler
244
- sampler.notice_first_scope_push(Time.now.to_f)
245
- sampler.notice_transaction('/path', '/path', {})
246
- sampler.notice_push_scope('Controller/sandwiches/index')
247
- yield
248
- sampler.notice_pop_scope('Controller/sandwiches/index')
249
- sampler.notice_scope_empty
250
- sampler
251
- ensure
252
- NewRelic::Agent.shutdown
253
- end
254
238
  end if ::Rails::VERSION::MAJOR.to_i >= 4
@@ -68,7 +68,7 @@ class NewRelic::Agent::Instrumentation::ActiveRecordInstrumentationTest < Test::
68
68
 
69
69
  ActiveRecordFixtures::Order.create :id => 0, :name => 'jeff'
70
70
 
71
- find_metric = "ActiveRecord/ActiveRecordFixtures::Order/find"
71
+ find_metric = "ActiveRecord/ActiveRecordFixtures::Order/find"
72
72
 
73
73
  assert_calls_metrics(find_metric) do
74
74
  ActiveRecordFixtures::Order.exists?(["name=?", 'jeff'])
@@ -211,7 +211,7 @@ class NewRelic::Agent::Instrumentation::ActiveRecordInstrumentationTest < Test::
211
211
  end
212
212
 
213
213
  def test_join_metrics_sqlite
214
- return if (defined?(Rails) && Rails.respond_to?(:version) && Rails.version.to_i == 3)
214
+ return if (defined?(Rails) && Rails::VERSION::MAJOR.to_i == 3)
215
215
  return if defined?(JRuby)
216
216
  return unless isSqlite?
217
217
 
@@ -249,7 +249,7 @@ class NewRelic::Agent::Instrumentation::ActiveRecordInstrumentationTest < Test::
249
249
  end
250
250
 
251
251
  def test_join_metrics_standard
252
- return if (defined?(Rails) && Rails.respond_to?(:version) && Rails.version.to_i >= 3)
252
+ return if (defined?(Rails) && Rails::VERSION::MAJOR.to_i >= 3)
253
253
  return if defined?(JRuby) || isSqlite?
254
254
 
255
255
  expected_metrics = %W[
@@ -290,7 +290,7 @@ class NewRelic::Agent::Instrumentation::ActiveRecordInstrumentationTest < Test::
290
290
  end
291
291
 
292
292
  def test_direct_sql
293
- assert_nil NewRelic::Agent::Instrumentation::MetricFrame.current
293
+ assert_nil NewRelic::Agent::Transaction.current
294
294
  assert_nil NewRelic::Agent.instance.stats_engine.scope_name
295
295
  assert_equal 0, NewRelic::Agent.instance.stats_engine.metrics.size, NewRelic::Agent.instance.stats_engine.metrics.inspect
296
296
 
@@ -549,7 +549,7 @@ class NewRelic::Agent::Instrumentation::ActiveRecordInstrumentationTest < Test::
549
549
  private
550
550
 
551
551
  def rails3?
552
- (defined?(Rails) && Rails.respond_to?(:version) && Rails.version.to_i >= 3)
552
+ (defined?(Rails) && Rails::VERSION::MAJOR.to_i >= 3)
553
553
  end
554
554
 
555
555
  def rails_env