newrelic_rpm 3.9.5.251 → 3.9.6.257

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. data.tar.gz.sig +0 -0
  2. data/CHANGELOG +74 -3
  3. data/GUIDELINES_FOR_CONTRIBUTING.md +19 -15
  4. data/README.md +1 -1
  5. data/Rakefile +22 -1
  6. data/lib/new_relic/agent/agent.rb +17 -5
  7. data/lib/new_relic/agent/agent_logger.rb +4 -0
  8. data/lib/new_relic/agent/configuration/default_source.rb +45 -1
  9. data/lib/new_relic/agent/configuration/manager.rb +43 -7
  10. data/lib/new_relic/agent/cross_app_monitor.rb +0 -3
  11. data/lib/new_relic/agent/cross_app_tracing.rb +8 -5
  12. data/lib/new_relic/agent/instrumentation/action_controller_subscriber.rb +4 -1
  13. data/lib/new_relic/agent/instrumentation/active_job.rb +93 -0
  14. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +2 -1
  15. data/lib/new_relic/agent/instrumentation/middleware_tracing.rb +2 -2
  16. data/lib/new_relic/agent/instrumentation/sinatra.rb +1 -2
  17. data/lib/new_relic/agent/new_relic_service.rb +1 -1
  18. data/lib/new_relic/agent/new_relic_service/json_marshaller.rb +20 -1
  19. data/lib/new_relic/agent/new_relic_service/pruby_marshaller.rb +5 -1
  20. data/lib/new_relic/agent/pipe_channel_manager.rb +32 -11
  21. data/lib/new_relic/agent/threading/agent_thread.rb +1 -1
  22. data/lib/new_relic/agent/threading/backtrace_node.rb +4 -3
  23. data/lib/new_relic/agent/transaction.rb +27 -6
  24. data/lib/new_relic/agent/transaction_state.rb +3 -3
  25. data/lib/new_relic/agent/vm/mri_vm.rb +3 -3
  26. data/lib/new_relic/control/frameworks/rails3.rb +1 -16
  27. data/lib/new_relic/control/instance_methods.rb +2 -0
  28. data/lib/new_relic/json_wrapper.rb +18 -3
  29. data/lib/new_relic/rack/browser_monitoring.rb +7 -5
  30. data/lib/new_relic/rack/developer_mode.rb +2 -0
  31. data/lib/new_relic/rack/error_collector.rb +12 -51
  32. data/lib/new_relic/transaction_sample.rb +0 -4
  33. data/lib/new_relic/transaction_sample/segment.rb +0 -4
  34. data/lib/new_relic/version.rb +1 -1
  35. data/newrelic_rpm.gemspec +3 -2
  36. data/test/agent_helper.rb +1 -1
  37. data/test/config/test.cert.crt +16 -12
  38. data/test/config/test.cert.key +13 -13
  39. data/test/environments/lib/environments/runner.rb +3 -0
  40. data/test/environments/rails30/Gemfile +2 -2
  41. data/test/environments/rails31/Gemfile +2 -2
  42. data/test/environments/rails32/Gemfile +2 -2
  43. data/test/environments/rails40/Gemfile +2 -4
  44. data/test/environments/rails41/Gemfile +2 -4
  45. data/test/environments/rails42/Gemfile +2 -4
  46. data/test/fixtures/cross_agent_tests/attribute_configuration.json +349 -0
  47. data/test/fixtures/cross_agent_tests/labels.json +31 -2
  48. data/test/fixtures/cross_agent_tests/postgres_explain_obfuscation/README.md +16 -0
  49. data/test/fixtures/cross_agent_tests/rum_client_config.json +9 -9
  50. data/test/fixtures/cross_agent_tests/rum_loader_insertion_location/empty_head +4 -0
  51. data/test/fixtures/cross_agent_tests/rum_loader_insertion_location/no_end_header.html +6 -0
  52. data/test/fixtures/cross_agent_tests/rum_loader_insertion_location/x_ua_meta_tag_multiple_tags.html +12 -0
  53. data/test/multiverse/lib/multiverse/runner.rb +33 -1
  54. data/test/multiverse/lib/multiverse/suite.rb +79 -7
  55. data/test/multiverse/suites/active_record/Envfile +1 -1
  56. data/test/multiverse/suites/agent_only/encoding_handling_test.rb +1 -1
  57. data/test/multiverse/suites/agent_only/labels_test.rb +2 -1
  58. data/test/multiverse/suites/agent_only/set_transaction_name_test.rb +2 -3
  59. data/test/multiverse/suites/agent_only/thread_profiling_test.rb +6 -6
  60. data/test/multiverse/suites/capistrano/Envfile +2 -2
  61. data/test/multiverse/suites/capistrano2/Envfile +4 -0
  62. data/test/multiverse/suites/curb/Envfile +4 -0
  63. data/test/multiverse/suites/high_security/config/newrelic.yml +5 -2
  64. data/test/multiverse/suites/high_security/high_security_test.rb +10 -8
  65. data/test/multiverse/suites/json/Envfile +23 -0
  66. data/test/multiverse/suites/json/config/newrelic.yml +22 -0
  67. data/test/multiverse/suites/json/json_test.rb +17 -0
  68. data/test/multiverse/suites/marshalling/marshalling_test.rb +2 -45
  69. data/test/multiverse/suites/rails/Envfile +3 -3
  70. data/test/multiverse/suites/rails/activejob_test.rb +137 -0
  71. data/test/multiverse/suites/rails/error_tracing_test.rb +15 -8
  72. data/test/multiverse/suites/rails/parameter_capture_test.rb +39 -19
  73. data/test/multiverse/suites/sequel/Envfile +5 -5
  74. data/test/multiverse/suites/sidekiq/Envfile +2 -2
  75. data/test/multiverse/suites/sinatra/Envfile +2 -1
  76. data/test/multiverse/suites/yajl/Envfile +13 -0
  77. data/test/multiverse/suites/yajl/config/newrelic.yml +21 -0
  78. data/test/multiverse/suites/yajl/yajl_test.rb +19 -0
  79. data/test/new_relic/agent/agent_logger_test.rb +10 -0
  80. data/test/new_relic/agent/agent_test.rb +7 -1
  81. data/test/new_relic/agent/configuration/default_source_test.rb +24 -0
  82. data/test/new_relic/agent/configuration/manager_test.rb +60 -2
  83. data/test/new_relic/agent/configuration/orphan_configuration_test.rb +25 -13
  84. data/test/new_relic/agent/cross_app_tracing_test.rb +10 -1
  85. data/test/new_relic/agent/instrumentation/active_job_test.rb +20 -0
  86. data/test/new_relic/agent/instrumentation/active_record_test.rb +10 -17
  87. data/test/new_relic/agent/instrumentation/controller_instrumentation_test.rb +15 -0
  88. data/test/new_relic/agent/instrumentation/sinatra_test.rb +1 -1
  89. data/test/new_relic/agent/new_relic_service_test.rb +24 -0
  90. data/test/new_relic/agent/pipe_channel_manager_test.rb +44 -2
  91. data/test/new_relic/agent/threading/agent_thread_test.rb +1 -2
  92. data/test/new_relic/agent/threading/backtrace_node_test.rb +12 -0
  93. data/test/new_relic/agent/transaction_state_test.rb +3 -6
  94. data/test/new_relic/agent/transaction_test.rb +163 -0
  95. data/test/new_relic/agent_test.rb +13 -1
  96. data/test/new_relic/fake_collector.rb +5 -5
  97. data/test/new_relic/fake_server.rb +5 -3
  98. data/test/new_relic/http_client_test_cases.rb +0 -4
  99. data/test/new_relic/marshalling_test_cases.rb +54 -0
  100. data/test/new_relic/multiverse_helpers.rb +2 -2
  101. data/test/new_relic/rack/browser_monitoring_test.rb +6 -0
  102. data/test/new_relic/rack/developer_mode_test.rb +8 -0
  103. data/test/new_relic/rack/error_collector_test.rb +0 -41
  104. data/test/new_relic/transaction_sample/segment_test.rb +0 -13
  105. data/test/new_relic/transaction_sample_test.rb +1 -11
  106. data/test/performance/lib/performance/instrumentation/perf_tools.rb +1 -1
  107. data/test/performance/lib/performance/runner.rb +1 -1
  108. data/test/performance/script/runner +2 -1
  109. data/test/performance/suites/rum_autoinsertion.rb +12 -2
  110. metadata +24 -11
  111. metadata.gz.sig +0 -0
  112. data/test/config/test.cert.csr +0 -11
  113. data/test/config/testing-privkey.pem +0 -18
@@ -80,6 +80,30 @@ module NewRelic::Agent::Configuration
80
80
  nil
81
81
  end
82
82
 
83
+ def test_transform_for_returns_a_proc_for_settings_with_a_transform
84
+ assert_equal Proc, DefaultSource.transform_for(:'rules.ignore_url_regexes').class
85
+ end
86
+
87
+ def test_transform_for_returns_nil_for_settings_that_do_not_have_a_transform
88
+ assert_nil DefaultSource.transform_for(:ca_bundle_path)
89
+ end
90
+
91
+ def test_convert_to_list
92
+ result = DefaultSource.convert_to_list("Foo,Bar,Baz")
93
+ assert_equal ['Foo', 'Bar', 'Baz'], result
94
+ end
95
+
96
+ def test_convert_to_list_returns_original_argument_given_array
97
+ result = DefaultSource.convert_to_list(['Foo'])
98
+ assert_equal ['Foo'], result
99
+ end
100
+
101
+ def test_rules_ignore_converts_comma_delimited_string_to_array
102
+ with_config(:'rules.ignore_url_regexes' => 'Foo,Bar,Baz') do
103
+ assert_equal [/Foo/, /Bar/, /Baz/], NewRelic::Agent.config[:'rules.ignore_url_regexes']
104
+ end
105
+ end
106
+
83
107
  def get_config_value_class(value)
84
108
  type = value.class
85
109
 
@@ -298,7 +298,8 @@ module NewRelic::Agent::Configuration
298
298
  @manager.add_config_for_testing(:labels => testcase["labelString"])
299
299
 
300
300
  assert_warning if testcase["warning"]
301
- assert_equal(testcase["expected"], @manager.parse_labels_from_string)
301
+ assert_equal(testcase["expected"].sort_by { |h| h["label_type"] },
302
+ @manager.parse_labels_from_string.sort_by { |h| h["label_type"] })
302
303
  end
303
304
  end
304
305
 
@@ -312,7 +313,7 @@ module NewRelic::Agent::Configuration
312
313
 
313
314
  def test_parse_labels_from_string_with_hard_failure
314
315
  bad_string = "baaaad"
315
- bad_string.stubs(:gsub).raises("Booom")
316
+ bad_string.stubs(:strip).raises("Booom")
316
317
  @manager.add_config_for_testing(:labels => bad_string)
317
318
 
318
319
  assert_parsing_error
@@ -367,6 +368,63 @@ module NewRelic::Agent::Configuration
367
368
  assert_parsed_labels(expected)
368
369
  end
369
370
 
371
+ def test_apply_transformations
372
+ transform = Proc.new { |value| value.gsub('foo', 'baz') }
373
+ ::NewRelic::Agent::Configuration::DefaultSource.stubs(:transform_for).returns(transform)
374
+
375
+ assert_equal 'bazbar', @manager.apply_transformations(:test, 'foobar')
376
+ end
377
+
378
+ def test_fetch_with_a_transform_returns_the_transformed_value
379
+ with_config(:rules => { :ignore_url_regexes => ['more than meets the eye'] }) do
380
+ assert_equal [/more than meets the eye/], @manager.fetch(:'rules.ignore_url_regexes')
381
+ end
382
+ end
383
+
384
+ def test_fetch_skips_the_config_layer_if_transformation_raises_error
385
+ bomb = Proc.new do |value|
386
+ if value == 'boom'
387
+ raise StandardError.new
388
+ else
389
+ value
390
+ end
391
+ end
392
+ @manager.stubs(:transform_from_default).returns(bomb)
393
+
394
+ with_config(:'rules.ignore_url_regexes' => 'boom') do
395
+ assert_equal [], @manager.fetch(:'rules.ignore_url_regexes')
396
+ end
397
+ end
398
+
399
+ def test_evaluate_procs_returns_evaluated_value_if_it_responds_to_call
400
+ callable = Proc.new { 'test' }
401
+ assert_equal 'test', @manager.evaluate_procs(callable)
402
+ end
403
+
404
+ def test_evaluate_procs_returns_original_value_if_it_does_not_respond_to_call
405
+ assert_equal 'test', @manager.evaluate_procs('test')
406
+ end
407
+
408
+ def test_apply_transformations_logs_error_if_transformation_fails
409
+ bomb = Proc.new { raise StandardError.new }
410
+ @manager.stubs(:transform_from_default).returns(bomb)
411
+
412
+ expects_logging(:error, includes("Error applying transformation"), any_parameters)
413
+
414
+ assert_raises StandardError do
415
+ @manager.apply_transformations(:test_key, 'test_value')
416
+ end
417
+ end
418
+
419
+ def test_apply_transformations_reraises_errors
420
+ bomb = Proc.new { raise StandardError.new }
421
+ @manager.stubs(:transform_from_default).returns(bomb)
422
+
423
+ assert_raises StandardError do
424
+ @manager.apply_transformations(:test_key, 'test_value')
425
+ end
426
+ end
427
+
370
428
  def assert_parsed_labels(expected)
371
429
  result = @manager.parsed_labels
372
430
 
@@ -12,12 +12,8 @@ class OrphanedConfigTest < Minitest::Test
12
12
  end
13
13
 
14
14
  def test_all_agent_config_keys_are_declared_in_default_source
15
- non_test_files = all_rb_files.reject { |filename| filename.include? 'test.rb' }
16
-
17
15
  non_test_files.each do |file|
18
- lines = File.read(file).split("\n")
19
-
20
- lines.each_with_index do |line, index|
16
+ lines_in(file).each_with_index do |line, index|
21
17
  config_match = line.match(/Agent\.config\[:['"]?([a-z\._]+)['"]?\]/)
22
18
  next unless config_match
23
19
 
@@ -35,22 +31,16 @@ class OrphanedConfigTest < Minitest::Test
35
31
 
36
32
  AGENT_CONFIG_PATTERN = /Agent\.config\[:['"]?([a-z\._]+)['"]?\s*\]/
37
33
  REGISTER_CALLBACK_PATTERN = /register_callback\(:['"]?([a-z\._]+)['"]?\)/
38
- NAMED_DEPENDENCY_PATTERN = /^\s*named[ (]+\:?([a-z\._]+).*$/
34
+ NAMED_DEPENDENCY_PATTERN = /^\s*named[ (]+\:?([a-z0-9\._]+).*$/
39
35
 
40
36
  def test_all_default_source_config_keys_are_used_in_the_agent
41
- non_test_files = all_rb_files.reject { |filename| filename.include? 'test.rb' }
42
-
43
37
  non_test_files.each do |file|
44
- lines = File.read(file).split("\n")
45
-
46
- lines.each_with_index do |line, index|
38
+ lines_in(file).each do |line|
47
39
  captures = []
48
40
  captures << line.scan(AGENT_CONFIG_PATTERN)
49
41
  captures << line.scan(REGISTER_CALLBACK_PATTERN)
50
42
  captures << line.scan(NAMED_DEPENDENCY_PATTERN).map(&method(:disable_name))
51
43
 
52
- next if captures.empty?
53
-
54
44
  captures.flatten.map do |key|
55
45
  @default_keys.delete key.gsub("'", "").to_sym
56
46
  end
@@ -67,6 +57,28 @@ class OrphanedConfigTest < Minitest::Test
67
57
  assert_empty @default_keys
68
58
  end
69
59
 
60
+ def test_documented_all_named_instrumentation_files
61
+ non_test_files.each do |file|
62
+ next unless file.include?("new_relic/agent/instrumentation")
63
+
64
+ lines_in(file).each_with_index do |line, index|
65
+ captures = line.scan(NAMED_DEPENDENCY_PATTERN).map(&method(:disable_name))
66
+
67
+ captures.flatten.map do |key|
68
+ refute NewRelic::Agent::Configuration::DEFAULTS[key.to_sym].nil?, "#{file}:#{index+1} - Document key `#{key}` found as name for instrumentation.\n"
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ def lines_in(file)
75
+ File.read(file).split("\n")
76
+ end
77
+
78
+ def non_test_files
79
+ all_rb_files.reject { |filename| filename.include? 'test.rb' }
80
+ end
81
+
70
82
  def disable_name(names)
71
83
  names.map { |name| "disable_#{name}" }
72
84
  end
@@ -33,6 +33,12 @@ module NewRelic
33
33
  assert_nil segment
34
34
  end
35
35
 
36
+ def test_finish_trace_treats_nil_start_time_as_agent_error
37
+ expects_logging(:error, any_parameters)
38
+ expects_no_pop_frame
39
+ CrossAppTracing.finish_trace(@state, nil, segment, request, response)
40
+ end
41
+
36
42
  # Since we log and swallow errors, assert on the logging to ensure these
37
43
  # paths are cleanly accepting nils, not just smothering the exceptions.
38
44
 
@@ -53,10 +59,13 @@ module NewRelic
53
59
  CrossAppTracing.finish_trace(@state, Time.now, segment, request, nil)
54
60
  end
55
61
 
56
-
57
62
  def expects_pop_frame
58
63
  @state.traced_method_stack.stubs(:pop_frame).once
59
64
  end
65
+
66
+ def expects_no_pop_frame
67
+ @state.traced_method_stack.stubs(:pop_frame).never
68
+ end
60
69
  end
61
70
  end
62
71
  end
@@ -0,0 +1,20 @@
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
+
5
+ require File.expand_path(File.join(File.dirname(__FILE__),'..','..','..','test_helper'))
6
+ require 'new_relic/agent/instrumentation/active_job'
7
+
8
+ module NewRelic::Agent::Instrumentation
9
+ class ActiveJobHelperTest < Minitest::Test
10
+ def test_rails_formatted_adapters_get_shortened
11
+ name = ActiveJobHelper.clean_adapter_name("ActiveJob::QueueAdapters::InlineAdapter")
12
+ assert_equal "ActiveJob::Inline", name
13
+ end
14
+
15
+ def test_unexpected_name_format
16
+ name = ActiveJobHelper.clean_adapter_name("Not::AnExpected::Adapter")
17
+ assert_equal "Not::AnExpected::Adapter", name
18
+ end
19
+ end
20
+ end
@@ -13,8 +13,7 @@ class NewRelic::Agent::Instrumentation::NewActiveRecordInstrumentationTest < Min
13
13
  NewRelic::Agent.manual_start
14
14
  ActiveRecord::Base.establish_connection unless ActiveRecord::Base.connection.active?
15
15
  ActiveRecordFixtures.setup
16
- NewRelic::Agent.instance.transaction_sampler.reset!
17
- NewRelic::Agent.instance.stats_engine.clear_stats
16
+ NewRelic::Agent.drop_buffered_data
18
17
  end
19
18
 
20
19
  def teardown
@@ -311,15 +310,21 @@ class NewRelic::Agent::Instrumentation::NewActiveRecordInstrumentationTest < Min
311
310
  end
312
311
  end
313
312
 
314
- call_count = active_record_query_caching_broken_for_find ? 3 : 1
315
- assert_activerecord_metrics(ActiveRecordFixtures::Order, 'find', :call_count => call_count)
313
+ assert_activerecord_metrics(ActiveRecordFixtures::Order, 'find', :call_count => 1)
316
314
  assert_remote_service_metrics
317
315
  end
318
316
 
319
317
  def test_cached_calls_are_not_recorded_with_select_all
320
- query = "SELECT * FROM #{ActiveRecordFixtures::Order.table_name} WHERE name = 'Oberon'"
318
+ # If this is the first create, ActiveRecord needs to warm up,
319
+ # send some SQL SELECTS, etc.
321
320
  in_web_transaction do
322
321
  ActiveRecordFixtures::Order.create(:name => 'Oberon')
322
+ end
323
+ NewRelic::Agent.drop_buffered_data
324
+
325
+ # the actual test is here
326
+ query = "SELECT * FROM #{ActiveRecordFixtures::Order.table_name} WHERE name = 'Oberon'"
327
+ in_web_transaction do
323
328
  ActiveRecordFixtures::Order.connection.cache do
324
329
  ActiveRecordFixtures::Order.connection.select_all(query)
325
330
  ActiveRecordFixtures::Order.connection.select_all(query)
@@ -385,18 +390,6 @@ class NewRelic::Agent::Instrumentation::NewActiveRecordInstrumentationTest < Min
385
390
  end
386
391
  end
387
392
 
388
- def active_record_query_caching_broken_for_find
389
- # For ActiveRecord 3.1 and 3.2 running in JRuby, some
390
- # query caching does not work.
391
- return false unless defined? JRuby
392
- return false unless active_record_major_version == 3
393
-
394
- case active_record_minor_version
395
- when 1, 2 then true
396
- else false
397
- end
398
- end
399
-
400
393
  def assert_activerecord_metrics(model, operation, stats={})
401
394
  assert_metrics_recorded({
402
395
  "ActiveRecord/all" => {},
@@ -341,5 +341,20 @@ module NewRelic::Agent::Instrumentation
341
341
  host.doit
342
342
  end
343
343
  end
344
+
345
+ def test_should_not_set_request
346
+ clazz = Class.new do
347
+ include ControllerInstrumentation
348
+
349
+ def doit
350
+ perform_action_with_newrelic_trace do
351
+ NewRelic::Agent::TransactionState.tl_get.current_transaction.request
352
+ end
353
+ end
354
+ end
355
+
356
+ request = clazz.new.doit
357
+ assert_nil request
358
+ end
344
359
  end
345
360
  end
@@ -56,7 +56,7 @@ class NewRelic::Agent::Instrumentation::SinatraTest < Minitest::Test
56
56
  SinatraTestApp.stubs(:middleware).returns([])
57
57
 
58
58
  SinatraTestApp.expects(:build_without_newrelic).once
59
- SinatraTestApp.expects(:use).at_least(3)
59
+ SinatraTestApp.expects(:use).at_least(2)
60
60
 
61
61
  SinatraTestApp.build_with_newrelic(@app)
62
62
  end
@@ -429,6 +429,18 @@ class NewRelicServiceTest < Minitest::Test
429
429
  end
430
430
  end
431
431
 
432
+ def test_json_marshaller_logs_on_empty_response_from_collector
433
+ marshaller = NewRelic::Agent::NewRelicService::JsonMarshaller.new
434
+ expects_logging(:error, any_parameters)
435
+ assert_nil marshaller.load('')
436
+ end
437
+
438
+ def test_json_marshaller_logs_on_nil_response_from_collector
439
+ marshaller = NewRelic::Agent::NewRelicService::JsonMarshaller.new
440
+ expects_logging(:error, any_parameters)
441
+ assert_nil marshaller.load(nil)
442
+ end
443
+
432
444
  def test_raises_serialization_error_if_json_serialization_fails
433
445
  ::NewRelic::JSONWrapper.stubs(:dump).raises(RuntimeError.new('blah'))
434
446
  assert_raises(NewRelic::Agent::SerializationError) do
@@ -529,6 +541,18 @@ class NewRelicServiceTest < Minitest::Test
529
541
  end
530
542
  end
531
543
 
544
+ def test_pruby_marshaller_logs_on_empty_response_from_collector
545
+ marshaller = NewRelic::Agent::NewRelicService::PrubyMarshaller.new
546
+ expects_logging(:error, any_parameters)
547
+ assert_nil marshaller.load('')
548
+ end
549
+
550
+ def test_pruby_marshaller_logs_on_nil_response_from_collector
551
+ marshaller = NewRelic::Agent::NewRelicService::PrubyMarshaller.new
552
+ expects_logging(:error, any_parameters)
553
+ assert_nil marshaller.load(nil)
554
+ end
555
+
532
556
  def test_compress_request_if_needed_compresses_large_payloads
533
557
  large_payload = 'a' * 65 * 1024
534
558
  body, encoding = @service.compress_request_if_needed(large_payload)
@@ -13,12 +13,16 @@ class NewRelic::Agent::PipeChannelManagerTest < Minitest::Test
13
13
  @test_config = { :developer_mode => true }
14
14
  NewRelic::Agent.agent.drop_buffered_data
15
15
  NewRelic::Agent.config.add_config_for_testing(@test_config)
16
- NewRelic::Agent::PipeChannelManager.listener.close_all_pipes
16
+
17
+ listener = NewRelic::Agent::PipeChannelManager::Listener.new
18
+ NewRelic::Agent::PipeChannelManager.instance_variable_set(:@listener, listener)
19
+
17
20
  NewRelic::Agent.manual_start
18
21
  NewRelic::Agent::TransactionState.tl_clear_for_testing
19
22
  end
20
23
 
21
24
  def teardown
25
+ NewRelic::Agent::PipeChannelManager.listener.close_all_pipes
22
26
  NewRelic::Agent::PipeChannelManager.listener.stop
23
27
  NewRelic::Agent.shutdown
24
28
  NewRelic::Agent.config.remove_config(@test_config)
@@ -110,7 +114,7 @@ class NewRelic::Agent::PipeChannelManagerTest < Minitest::Test
110
114
  :duration => 10,
111
115
  :type => :controller
112
116
  })
113
- NewRelic::Agent.agent.send(:transmit_transaction_event_data)
117
+ NewRelic::Agent.agent.send(:transmit_event_data)
114
118
  end
115
119
 
116
120
  assert_equal(1, request_sampler.samples.size)
@@ -223,6 +227,44 @@ class NewRelic::Agent::PipeChannelManagerTest < Minitest::Test
223
227
  assert_nil pipe.read
224
228
  end
225
229
 
230
+ def test_listener_pipes_race_condition
231
+ # 1.8.7 doesn't have easy singleton_class access, but also doesn't have
232
+ # races thanks to green threads and the GIL, so pitch it!
233
+ return if RUBY_VERSION < "1.9.2"
234
+
235
+ begin
236
+ listener = NewRelic::Agent::PipeChannelManager.listener
237
+ listener.instance_variable_set(:@select_timeout, 0.00001)
238
+ listener.start
239
+
240
+ listener.register_pipe(0)
241
+ pipe_out = listener.pipes[0].out
242
+
243
+ mutex = Mutex.new
244
+ mutex.lock
245
+ tried_to_close = false
246
+ pipe_out.singleton_class.send(:define_method, :closed?, Proc.new do
247
+ tried_to_close = true
248
+ mutex.synchronize do
249
+ end
250
+ end)
251
+
252
+ # Make sure we're actually paused in closed? call
253
+ until tried_to_close
254
+ end
255
+
256
+ t = Thread.new do
257
+ listener.register_pipe(1)
258
+ end
259
+
260
+ mutex.unlock
261
+ t.join
262
+ ensure
263
+ listener.close_all_pipes
264
+ listener.stop
265
+ end
266
+ end
267
+
226
268
  def run_child(channel_id)
227
269
  pid = Process.fork do
228
270
  yield
@@ -32,8 +32,7 @@ module NewRelic::Agent::Threading
32
32
 
33
33
  t = Thread.new do
34
34
  begin
35
- in_transaction do |txn|
36
- txn.request = 'whatever'
35
+ in_web_transaction do
37
36
  q0.push 'unblock main thread'
38
37
  q1.pop
39
38
  end
@@ -73,6 +73,18 @@ module NewRelic::Agent::Threading
73
73
  node.as_array)
74
74
  end
75
75
 
76
+ def test_nodes_without_line_numbers
77
+ line = "transaction_sample_buffer.rb:in `visit_segment'"
78
+ node = create_node(line)
79
+ convert_nodes_to_array([node])
80
+
81
+ assert_equal([
82
+ ["transaction_sample_buffer.rb", "visit_segment", -1],
83
+ 0, 0,
84
+ []],
85
+ node.as_array)
86
+ end
87
+
76
88
  def test_gracefully_handle_bad_values_in_to_array
77
89
  node = BacktraceNode.new(SINGLE_LINE)
78
90
  node.stubs(:parse_backtrace_frame).returns(["irb.rb", "catch", "blarg"])