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
@@ -3,158 +3,9 @@
3
3
  # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
4
4
 
5
5
  require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'test_helper'))
6
- require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', 'test_contexts'))
7
6
 
8
7
  class NewRelic::Agent::Instrumentation::TaskInstrumentationTest < Test::Unit::TestCase
9
8
  include NewRelic::Agent::Instrumentation::ControllerInstrumentation
10
- extend TestContexts
11
- attr_accessor :agent
12
-
13
- with_running_agent do
14
-
15
- should "run" do
16
- run_task_inner 0
17
- stat_names = %w[Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_0
18
- HttpDispatcher
19
- Apdex Apdex/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_0].sort
20
- expected_but_missing = stat_names - @agent.stats_engine.metrics
21
- assert_equal 0, expected_but_missing.size, @agent.stats_engine.metrics.map { |n|
22
- stat = @agent.stats_engine.get_stats_no_scope(n)
23
- "#{'%-26s' % n}: #{stat.call_count} calls"
24
- }.join("\n ") + "\nmissing: #{expected_but_missing.inspect}"
25
- assert_equal 0, @agent.stats_engine.get_stats_no_scope('Controller').call_count
26
- assert_equal 1, @agent.stats_engine.get_stats_no_scope('Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_0').call_count
27
- end
28
-
29
- should "run_recursive" do
30
- run_task_inner(3)
31
- assert_equal 1, @agent.stats_engine.lookup_stats(
32
- 'Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_0',
33
- 'Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_1').call_count
34
- assert_equal 1, @agent.stats_engine.lookup_stats(
35
- 'Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_1',
36
- 'Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_2').call_count
37
- assert_equal 1, @agent.stats_engine.lookup_stats(
38
- 'Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_2',
39
- 'Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_3').call_count
40
- assert_equal 1, @agent.stats_engine.get_stats_no_scope('Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_0').call_count
41
- assert_equal 1, @agent.stats_engine.get_stats_no_scope('Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_1').call_count
42
- assert_equal 1, @agent.stats_engine.get_stats_no_scope('Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_2').call_count
43
- assert_equal 1, @agent.stats_engine.get_stats_no_scope('Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_3').call_count
44
- assert_equal 0, @agent.stats_engine.get_stats_no_scope('Controller').call_count
45
- end
46
-
47
- should "run_nested" do
48
- run_task_outer(3)
49
- @agent.stats_engine.metrics.sort.each do |n|
50
- stat = @agent.stats_engine.get_stats_no_scope(n)
51
- end
52
- assert_equal 1, @agent.stats_engine.get_stats_no_scope('Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/outer_task').call_count
53
- assert_equal 2, @agent.stats_engine.get_stats_no_scope('Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_0').call_count
54
- end
55
-
56
- should "reentrancy" do
57
- assert_equal 0, NewRelic::Agent::BusyCalculator.busy_count
58
- run_task_inner(1)
59
- assert_equal 1, @agent.stats_engine.get_stats_no_scope('Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_0').call_count
60
- assert_equal 1, @agent.stats_engine.get_stats_no_scope('Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_1').call_count
61
- compare_metrics %w[
62
- Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_0:Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_1
63
- Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_0
64
- Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_1
65
- ], @agent.stats_engine.metrics.grep(/^Controller/)
66
- end
67
-
68
- should "transaction" do
69
- assert_equal 0, @agent.transaction_sampler.scope_depth, "existing unfinished sample"
70
- assert_nil @agent.transaction_sampler.last_sample
71
- assert_equal @agent.transaction_sampler, @agent.stats_engine.instance_variable_get("@transaction_sampler")
72
- run_task_outer(10)
73
- assert_equal 0, @agent.transaction_sampler.scope_depth, "existing unfinished sample"
74
- @agent.stats_engine.metrics.sort.each do |n|
75
- stat = @agent.stats_engine.get_stats_no_scope(n)
76
- end
77
- assert_equal 1, @agent.stats_engine.get_stats_no_scope('Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/outer_task').call_count
78
- assert_equal 0, @agent.stats_engine.get_stats_no_scope('Controller').call_count
79
- assert_equal 2, @agent.stats_engine.get_stats_no_scope('Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_0').call_count
80
- assert_equal 0, @agent.transaction_sampler.scope_depth, "existing unfinished sample"
81
- sample = @agent.transaction_sampler.last_sample
82
- assert_not_nil sample
83
- assert_not_nil sample.params[:custom_params][:cpu_time], "cpu time nil: \n#{sample}"
84
- assert sample.params[:custom_params][:cpu_time] >= 0, "cpu time: #{sample.params[:cpu_time]},\n#{sample}"
85
- assert_equal '10', sample.params[:request_params][:level]
86
- end
87
-
88
- should "abort" do
89
- @acct = 'Redrocks'
90
- perform_action_with_newrelic_trace(:name => 'hello', :force => true, :params => { :account => @acct}) do
91
- self.class.inspect
92
- NewRelic::Agent.abort_transaction!
93
- end
94
- # We record the controller metric still, but abort any transaction recording.
95
- assert_equal 1, @agent.stats_engine.get_stats_no_scope('Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/hello').call_count
96
- assert_nil @agent.transaction_sampler.last_sample
97
- end
98
- should "block" do
99
- assert_equal @agent, NewRelic::Agent.instance
100
- @acct = 'Redrocks'
101
- perform_action_with_newrelic_trace(:name => 'hello', :force => true, :params => { :account => @acct}) do
102
- self.class.inspect
103
- end
104
- @agent.stats_engine.metrics.sort.each do |n|
105
- stat = @agent.stats_engine.get_stats_no_scope(n)
106
- end
107
- assert_equal @agent, NewRelic::Agent.instance
108
- assert_equal 1, @agent.stats_engine.get_stats_no_scope('Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/hello').call_count
109
- sample = @agent.transaction_sampler.last_sample
110
- assert_not_nil sample
111
- assert_equal 'Redrocks', sample.params[:request_params][:account]
112
-
113
- end
114
-
115
- should "error_handling" do
116
- @agent.error_collector.ignore_error_filter
117
- @agent.error_collector.harvest_errors([])
118
- @agent.error_collector.expects(:notice_error).once
119
- assert_equal @agent.error_collector, NewRelic::Agent.instance.error_collector
120
- assert_raise RuntimeError do
121
- run_task_exception
122
- end
123
- end
124
-
125
- should "custom_params" do
126
- @agent.error_collector.stubs(:enabled).returns(true)
127
- @agent.error_collector.ignore_error_filter
128
- @agent.error_collector.harvest_errors([])
129
- assert_equal @agent.error_collector, NewRelic::Agent.instance.error_collector
130
- assert_raise RuntimeError do
131
- run_task_exception
132
- end
133
- errors = @agent.error_collector.harvest_errors([])
134
- assert_equal 1, errors.size
135
- error = errors.first
136
- assert_equal "Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/run_task_exception", error.path
137
- assert_not_nil error.params[:stack_trace]
138
- assert_not_nil error.params[:custom_params]
139
- end
140
-
141
- should "instrument_bg" do
142
- run_background_job
143
- stat_names = %w[OtherTransaction/Background/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/run_background_job
144
- OtherTransaction/Background/all
145
- OtherTransaction/all].sort
146
-
147
- expected_but_missing = stat_names - @agent.stats_engine.metrics
148
- assert_equal 0, expected_but_missing.size, @agent.stats_engine.metrics.map { |n|
149
- stat = @agent.stats_engine.get_stats_no_scope(n)
150
- "#{'%-26s' % n}: #{stat.call_count} calls"
151
- }.join("\n ") + "\nmissing: #{expected_but_missing.inspect}"
152
- assert_equal 1, @agent.stats_engine.get_stats_no_scope('OtherTransaction/all').call_count
153
- assert_equal 1, @agent.stats_engine.get_stats_no_scope('OtherTransaction/Background/all').call_count
154
- end
155
- end
156
-
157
- private
158
9
 
159
10
  def run_task_inner(n)
160
11
  return if n == 0
@@ -181,6 +32,139 @@ class NewRelic::Agent::Instrumentation::TaskInstrumentationTest < Test::Unit::Te
181
32
  add_transaction_tracer :run_task_exception
182
33
  add_transaction_tracer :run_task_inner, :name => 'inner_task_#{args[0]}'
183
34
  add_transaction_tracer :run_task_outer, :name => 'outer_task', :params => '{ :level => args[0] }'
184
- # Eventually we need th change this to :category => :task
185
- add_transaction_tracer :run_background_job, :category => 'OtherTransaction/Background'
35
+ add_transaction_tracer :run_background_job, :category => :task
36
+
37
+ def setup
38
+ @agent = NewRelic::Agent.instance
39
+ @agent.transaction_sampler.reset!
40
+ @agent.stats_engine.clear_stats
41
+ end
42
+
43
+ #
44
+ # Tests
45
+ #
46
+
47
+ def test_should_run
48
+ run_task_inner(0)
49
+ assert_metrics_recorded_exclusive([
50
+ 'Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_0',
51
+ 'Apdex/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_0',
52
+ 'HttpDispatcher',
53
+ 'Apdex'
54
+ ])
55
+ end
56
+
57
+ def test_should_handle_single_recursive_invocation
58
+ run_task_inner(1)
59
+ assert_metrics_recorded_exclusive(
60
+ [
61
+ [
62
+ 'Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_0',
63
+ 'Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_1'
64
+ ],
65
+ 'Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_0',
66
+ 'Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_1'
67
+ ],
68
+ :filter => /^Controller/
69
+ )
70
+ end
71
+
72
+ def test_should_handle_recursive_task_invocations
73
+ run_task_inner(3)
74
+ assert_metrics_recorded_exclusive(
75
+ [
76
+ [
77
+ 'Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_0',
78
+ 'Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_1'
79
+ ],
80
+ [
81
+ 'Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_1',
82
+ 'Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_2'
83
+ ],
84
+ [
85
+ 'Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_2',
86
+ 'Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_3'
87
+ ],
88
+ 'Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_0',
89
+ 'Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_1',
90
+ 'Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_2',
91
+ 'Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_3'
92
+ ],
93
+ :filter => /^Controller/
94
+ )
95
+ end
96
+
97
+ def test_should_handle_nested_task_invocations
98
+ run_task_outer(3)
99
+ assert_metrics_recorded({
100
+ 'Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/outer_task' => { :call_count => 1 },
101
+ 'Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_0' => { :call_count => 2 }
102
+ })
103
+ end
104
+
105
+ def test_transaction
106
+ run_task_outer(10)
107
+
108
+ assert_equal 0, @agent.transaction_sampler.scope_depth, "existing unfinished sample"
109
+ assert_metrics_recorded({
110
+ 'Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/outer_task' => { :call_count => 1 },
111
+ 'Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/inner_task_0' => { :call_count => 2 }
112
+ })
113
+ assert_metrics_not_recorded(['Controller'])
114
+
115
+ sample = @agent.transaction_sampler.last_sample
116
+ assert_not_nil(sample)
117
+ assert_not_nil(sample.params[:custom_params][:cpu_time], "cpu time nil: \n#{sample}")
118
+ assert((sample.params[:custom_params][:cpu_time] >= 0), "cpu time: #{sample.params[:cpu_time]},\n#{sample}")
119
+ assert_equal('10', sample.params[:request_params][:level])
120
+ end
121
+
122
+ def test_abort_transaction
123
+ perform_action_with_newrelic_trace(:name => 'hello', :force => true) do
124
+ self.class.inspect
125
+ NewRelic::Agent.abort_transaction!
126
+ end
127
+ # We record the controller metric still, but abort any transaction recording.
128
+ assert_metrics_recorded(['Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/hello'])
129
+ assert_nil(@agent.transaction_sampler.last_sample)
130
+ end
131
+
132
+ def test_perform_action_with_newrelic_trace_saves_params
133
+ account = 'Redrocks'
134
+ perform_action_with_newrelic_trace(:name => 'hello', :force => true,
135
+ :params => { :account => account }) do
136
+ self.class.inspect
137
+ end
138
+
139
+ assert_metrics_recorded(['Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/hello'])
140
+ sample = @agent.transaction_sampler.last_sample
141
+ assert_not_nil(sample)
142
+ assert_equal(account, sample.params[:request_params][:account])
143
+ end
144
+
145
+ def test_errors_are_noticed_and_not_swallowed
146
+ @agent.error_collector.expects(:notice_error).once
147
+ assert_raise(RuntimeError) { run_task_exception }
148
+ end
149
+
150
+ def test_error_collector_captures_custom_params
151
+ @agent.error_collector.harvest_errors([])
152
+ run_task_exception rescue nil
153
+ errors = @agent.error_collector.harvest_errors([])
154
+
155
+ assert_equal(1, errors.size)
156
+ error = errors.first
157
+ assert_equal("Controller/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/run_task_exception", error.path)
158
+ assert_not_nil(error.params[:stack_trace])
159
+ assert_not_nil(error.params[:custom_params])
160
+ end
161
+
162
+ def test_instrument_background_job
163
+ run_background_job
164
+ assert_metrics_recorded([
165
+ 'OtherTransaction/Background/NewRelic::Agent::Instrumentation::TaskInstrumentationTest/run_background_job',
166
+ 'OtherTransaction/Background/all',
167
+ 'OtherTransaction/all'
168
+ ])
169
+ end
186
170
  end
@@ -7,6 +7,10 @@ class NewRelic::Agent::MethodTracer::InstanceMethods::TraceExecutionScopedTest <
7
7
  require 'new_relic/agent/method_tracer'
8
8
  include NewRelic::Agent::MethodTracer::InstanceMethods::TraceExecutionScoped
9
9
 
10
+ def setup
11
+ NewRelic::Agent.agent.stats_engine.clear_stats
12
+ end
13
+
10
14
  def test_trace_disabled_negative
11
15
  self.expects(:traced?).returns(false)
12
16
  options = {:force => false}
@@ -51,36 +55,117 @@ class NewRelic::Agent::MethodTracer::InstanceMethods::TraceExecutionScopedTest <
51
55
  assert_equal NewRelic::Agent.instance, agent_instance
52
56
  end
53
57
 
54
- def test_get_metric_specs_with_metric_option
55
- first_name = 'foo'
56
- other_names = ['bar', 'baz']
57
- opts = {:metric => true}
58
+ def test_metric_recording_outside_transaction
59
+ trace_execution_scoped(['foo']) do
60
+ # meh
61
+ end
62
+ assert_metrics_recorded_exclusive(
63
+ 'foo' => { :call_count => 1 }
64
+ )
65
+ end
58
66
 
59
- specs = get_metric_specs(first_name, other_names, 'scope', opts)
67
+ def test_metric_recording_in_root_transaction
68
+ options = { :transaction => true }
69
+ self.stubs(:has_parent?).returns(false)
60
70
 
61
- expected_specs = [
62
- NewRelic::MetricSpec.new('foo', 'scope'),
63
- NewRelic::MetricSpec.new('foo'),
64
- NewRelic::MetricSpec.new('bar'),
65
- NewRelic::MetricSpec.new('baz')
66
- ]
71
+ in_transaction('outer') do
72
+ trace_execution_scoped(['foo', 'bar'], options) do
73
+ # erm
74
+ end
75
+ end
67
76
 
68
- assert_equal(expected_specs.sort, specs.sort)
77
+ expected_values = { :call_count => 1 }
78
+ assert_metrics_recorded_exclusive(
79
+ 'foo' => expected_values,
80
+ 'bar' => expected_values
81
+ )
69
82
  end
70
83
 
71
- def test_get_metric_stats_without_metric_option
72
- first_name = 'foo'
73
- other_names = ['bar', 'baz']
74
- opts = {:metric => false}
84
+ def test_metric_recording_in_non_root_transaction
85
+ options = { :transaction => true }
86
+ self.stubs(:has_parent?).returns(true)
87
+ in_transaction('outer') do
88
+ in_transaction('inner') do
89
+ trace_execution_scoped(['inner', 'bar'], options) do
90
+ # erm
91
+ end
92
+ end
93
+ end
94
+
95
+ expected_values = { :call_count => 1 }
96
+ assert_metrics_recorded_exclusive(
97
+ 'inner' => expected_values,
98
+ ['inner', 'outer'] => expected_values,
99
+ 'bar' => expected_values
100
+ )
101
+ end
75
102
 
76
- specs = get_metric_specs(first_name, other_names, 'scope', opts)
103
+ def test_metric_recording_in_root_non_transaction
104
+ options = { :transaction => false }
105
+ self.stubs(:has_parent?).returns(false)
77
106
 
78
- expected_specs = [
79
- NewRelic::MetricSpec.new('bar'),
80
- NewRelic::MetricSpec.new('baz')
81
- ]
107
+ in_transaction('outer') do
108
+ trace_execution_scoped(['foo', 'bar'], options) do
109
+ # erm
110
+ end
111
+ end
82
112
 
83
- assert_equal(expected_specs.sort, specs.sort)
113
+ expected_values = { :call_count => 1 }
114
+ assert_metrics_recorded_exclusive(
115
+ 'foo' => expected_values,
116
+ ['foo', 'outer'] => expected_values,
117
+ 'bar' => expected_values
118
+ )
119
+ end
120
+
121
+ def test_metric_recording_in_non_root_non_transaction
122
+ options = { :transaction => false }
123
+ self.stubs(:has_parent?).returns(false)
124
+
125
+ in_transaction('outer') do
126
+ trace_execution_scoped(['foo', 'bar'], options) do
127
+ # erm
128
+ end
129
+ end
130
+
131
+ expected_values = { :call_count => 1 }
132
+ assert_metrics_recorded_exclusive(
133
+ 'foo' => expected_values,
134
+ ['foo', 'outer'] => expected_values,
135
+ 'bar' => expected_values
136
+ )
137
+ end
138
+
139
+ def test_metric_recording_without_metric_option
140
+ options = { :metric => false, :transaction => true }
141
+ self.stubs(:has_parent?).returns(false)
142
+
143
+ in_transaction('outer') do
144
+ trace_execution_scoped(['foo', 'bar'], options) do
145
+ # erm
146
+ end
147
+ end
148
+
149
+ expected_values = { :call_count => 1 }
150
+ assert_metrics_recorded_exclusive(
151
+ 'bar' => expected_values
152
+ )
153
+ end
154
+
155
+ def test_metric_recording_with_scoped_metric_only_option
156
+ options = { :transaction => false, :scoped_metric_only => true }
157
+ self.stubs(:has_parent?).returns(false)
158
+
159
+ in_transaction('outer') do
160
+ trace_execution_scoped(['foo', 'bar'], options) do
161
+ # erm
162
+ end
163
+ end
164
+
165
+ expected_values = { :call_count => 1 }
166
+ assert_metrics_recorded_exclusive(
167
+ ['foo', 'outer'] => expected_values
168
+ )
84
169
  end
85
170
 
86
171
  def test_set_if_nil
@@ -116,7 +201,7 @@ class NewRelic::Agent::MethodTracer::InstanceMethods::TraceExecutionScopedTest <
116
201
 
117
202
  def test_log_errors_base
118
203
  ran = false
119
- log_errors("name", "metric") do
204
+ log_errors("name") do
120
205
  ran = true
121
206
  end
122
207
  assert ran, "should run the contents of the block"
@@ -124,7 +209,7 @@ class NewRelic::Agent::MethodTracer::InstanceMethods::TraceExecutionScopedTest <
124
209
 
125
210
  def test_log_errors_with_return
126
211
  ran = false
127
- return_val = log_errors('name', 'metric') do
212
+ return_val = log_errors('name') do
128
213
  ran = true
129
214
  'happy trees'
130
215
  end
@@ -135,41 +220,56 @@ class NewRelic::Agent::MethodTracer::InstanceMethods::TraceExecutionScopedTest <
135
220
 
136
221
  def test_log_errors_with_error
137
222
  expects_logging(:error,
138
- includes("Caught exception in name. Metric name = metric"),
223
+ includes("Caught exception in name."),
139
224
  instance_of(RuntimeError))
140
225
 
141
- log_errors("name", "metric") do
226
+ log_errors("name") do
142
227
  raise "should not propagate out of block"
143
228
  end
144
229
  end
145
230
 
146
231
  def test_trace_execution_scoped_header
147
232
  options = {:force => false, :deduct_call_time_from_parent => false}
148
- self.expects(:log_errors).with('trace_execution_scoped header', 'foo').yields
233
+ self.expects(:log_errors).with('trace_execution_scoped header').yields
149
234
  self.expects(:push_flag!).with(false)
150
235
  fakestats = mocked_object('stat_engine')
151
- fakestats.expects(:push_scope).with('foo', 1.0, false)
152
- trace_execution_scoped_header('foo', options, 1.0)
153
- end
154
-
155
- def test_trace_execution_scoped_footer
156
- t0 = 1.0
157
- t1 = 2.0
158
- metric = 'foo'
159
- metric_specs = [NewRelic::MetricSpec.new('foo'), NewRelic::MetricSpec.new('bar')]
160
- stats = [NewRelic::Agent::Stats.new, NewRelic::Agent::Stats.new]
161
- expected_scope = 'an expected scope'
162
- engine = mocked_object('stat_engine')
163
- scope = mock('scope')
164
- engine.expects(:pop_scope).with('an expected scope', 1.0, 2.0).returns(scope)
165
- engine.expects(:record_metrics).with(metric_specs).multiple_yields(*stats)
166
- stats[0].expects(:record_data_point).with(1.0, 0.5)
167
- stats[1].expects(:record_data_point).with(1.0, 0.5)
168
- scope.expects(:children_time).returns(0.5)
169
- self.expects(:pop_flag!).with(false)
170
- self.expects(:log_errors).with('trace_method_execution footer', 'foo').yields
171
-
172
- trace_execution_scoped_footer(t0, metric, metric_specs, expected_scope, false, t1)
236
+ fakestats.expects(:push_scope).with(:method_tracer, 1.0, false)
237
+ trace_execution_scoped_header(options, 1.0)
238
+ end
239
+
240
+ def test_trace_execution_scoped_calculates_exclusive_time
241
+ freeze_time
242
+ in_transaction('txn') do
243
+ trace_execution_scoped(['parent']) do
244
+ advance_time(10)
245
+ trace_execution_scoped(['child']) do
246
+ advance_time(10)
247
+ end
248
+ end
249
+ end
250
+
251
+ assert_metrics_recorded_exclusive(
252
+ 'parent' => { :call_count => 1, :total_call_time => 20, :total_exclusive_time => 10 },
253
+ ['parent', 'txn'] => { :call_count => 1, :total_call_time => 20, :total_exclusive_time => 10 },
254
+ 'child' => { :call_count => 1, :total_call_time => 10, :total_exclusive_time => 10 },
255
+ ['child', 'txn'] => { :call_count => 1, :total_call_time => 10, :total_exclusive_time => 10 }
256
+ )
257
+ end
258
+
259
+ def test_force_flag_enables_metric_recording_in_ignored_transaction
260
+ NewRelic::Agent.instance.push_trace_execution_flag(false)
261
+ in_transaction('txn') do
262
+ trace_execution_scoped(['foo'], :force => true) do
263
+ # whatever, man
264
+ end
265
+ end
266
+
267
+ assert_metrics_recorded_exclusive(
268
+ 'foo' => { :call_count => 1 },
269
+ ['foo', 'txn'] => { :call_count => 1 }
270
+ )
271
+ ensure
272
+ NewRelic::Agent.instance.pop_trace_execution_flag()
173
273
  end
174
274
 
175
275
  def test_trace_execution_scoped_disabled
@@ -186,47 +286,19 @@ class NewRelic::Agent::MethodTracer::InstanceMethods::TraceExecutionScopedTest <
186
286
  assert_equal 1172, value, 'should return contents of block'
187
287
  end
188
288
 
189
- def test_trace_execution_scoped_default
190
- passed_in_opts = {}
191
- opts_after_correction = {:metric => true, :deduct_call_time_from_parent => true}
192
- specs = [
193
- NewRelic::MetricSpec.new('metric'),
194
- NewRelic::MetricSpec.new('array')
195
- ]
196
- self.expects(:trace_disabled?).returns(false)
197
- self.expects(:get_metric_specs).with('metric', ['array'], nil, opts_after_correction).returns(specs)
198
- self.expects(:trace_execution_scoped_header).with('metric', opts_after_correction).returns(['start_time', 'expected_scope'])
199
- self.expects(:trace_execution_scoped_footer).with('start_time', 'metric', specs, 'expected_scope', nil)
200
- ran = false
201
- value = trace_execution_scoped(['metric', 'array'], passed_in_opts) do
202
- ran = true
289
+ def test_trace_execution_scope_runs_passed_block_and_returns_its_value
290
+ value = trace_execution_scoped(['metric', 'array'], {}) do
203
291
  1172
204
292
  end
205
-
206
- assert ran, 'should run contents of the block'
207
293
  assert_equal 1172, value, 'should return the contents of the block'
208
294
  end
209
295
 
210
- def test_trace_execution_scoped_with_error
211
- passed_in_opts = {}
212
- opts_after_correction = {:metric => true, :deduct_call_time_from_parent => true}
213
- specs = [
214
- NewRelic::MetricSpec.new('metric'),
215
- NewRelic::MetricSpec.new('array')
216
- ]
217
- self.expects(:trace_disabled?).returns(false)
218
- self.expects(:get_metric_specs).with('metric', ['array'], nil, opts_after_correction).returns(specs)
219
- self.expects(:trace_execution_scoped_header).with('metric', opts_after_correction).returns(['start_time', 'expected_scope'])
220
- self.expects(:trace_execution_scoped_footer).with('start_time', 'metric', specs, 'expected_scope', nil)
221
- ran = false
296
+ def test_trace_execution_scoped_does_not_swallow_errors
222
297
  assert_raises(RuntimeError) do
223
- trace_execution_scoped(['metric', 'array'], passed_in_opts) do
224
- ran = true
298
+ trace_execution_scoped(['metric', 'array'], {}) do
225
299
  raise 'raising a test error'
226
300
  end
227
301
  end
228
-
229
- assert ran, 'should run contents of the block'
230
302
  end
231
303
 
232
304
  private