newrelic_rpm 3.6.7.159 → 3.6.8.164

Sign up to get free protection for your applications and to get access to all the features.
Files changed (103) hide show
  1. data/CHANGELOG +14 -0
  2. data/lib/new_relic/agent/agent.rb +38 -35
  3. data/lib/new_relic/agent/agent_logger.rb +6 -47
  4. data/lib/new_relic/agent/beacon_configuration.rb +10 -4
  5. data/lib/new_relic/agent/browser_monitoring.rb +39 -33
  6. data/lib/new_relic/agent/commands/agent_command.rb +4 -4
  7. data/lib/new_relic/agent/commands/agent_command_router.rb +72 -10
  8. data/lib/new_relic/agent/commands/thread_profiler_session.rb +110 -0
  9. data/lib/new_relic/agent/commands/xray_session.rb +55 -0
  10. data/lib/new_relic/agent/commands/xray_session_collection.rb +158 -0
  11. data/lib/new_relic/agent/configuration/default_source.rb +61 -24
  12. data/lib/new_relic/agent/configuration/mask_defaults.rb +2 -2
  13. data/lib/new_relic/agent/configuration/server_source.rb +1 -1
  14. data/lib/new_relic/agent/instrumentation/action_controller_subscriber.rb +2 -0
  15. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +4 -10
  16. data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +10 -11
  17. data/lib/new_relic/agent/memory_logger.rb +52 -0
  18. data/lib/new_relic/agent/new_relic_service.rb +4 -0
  19. data/lib/new_relic/agent/request_sampler.rb +32 -13
  20. data/lib/new_relic/agent/samplers/cpu_sampler.rb +6 -3
  21. data/lib/new_relic/agent/threading/agent_thread.rb +2 -1
  22. data/lib/new_relic/agent/threading/backtrace_node.rb +80 -27
  23. data/lib/new_relic/agent/threading/backtrace_service.rb +264 -0
  24. data/lib/new_relic/agent/threading/thread_profile.rb +79 -118
  25. data/lib/new_relic/agent/transaction/developer_mode_sample_buffer.rb +56 -0
  26. data/lib/new_relic/agent/transaction/force_persist_sample_buffer.rb +25 -0
  27. data/lib/new_relic/agent/transaction/slowest_sample_buffer.rb +25 -0
  28. data/lib/new_relic/agent/transaction/transaction_sample_buffer.rb +86 -0
  29. data/lib/new_relic/agent/transaction/xray_sample_buffer.rb +64 -0
  30. data/lib/new_relic/agent/transaction.rb +25 -4
  31. data/lib/new_relic/agent/transaction_sample_builder.rb +6 -10
  32. data/lib/new_relic/agent/transaction_sampler.rb +47 -202
  33. data/lib/new_relic/agent/worker_loop.rb +47 -39
  34. data/lib/new_relic/agent.rb +1 -1
  35. data/lib/new_relic/build.rb +2 -2
  36. data/lib/new_relic/coerce.rb +8 -0
  37. data/lib/new_relic/control/instance_methods.rb +1 -0
  38. data/lib/new_relic/rack/browser_monitoring.rb +15 -1
  39. data/lib/new_relic/rack/developer_mode.rb +1 -1
  40. data/lib/new_relic/transaction_sample.rb +20 -5
  41. data/lib/new_relic/version.rb +1 -1
  42. data/newrelic.yml +4 -6
  43. data/newrelic_rpm.gemspec +1 -1
  44. data/test/agent_helper.rb +11 -0
  45. data/test/environments/lib/environments/runner.rb +5 -1
  46. data/test/environments/rails21/Gemfile +2 -2
  47. data/test/environments/rails22/Gemfile +2 -2
  48. data/test/environments/rails23/Gemfile +2 -2
  49. data/test/environments/rails31/Gemfile +2 -2
  50. data/test/environments/rails32/Gemfile +2 -2
  51. data/test/multiverse/suites/agent_only/marshaling_test.rb +1 -1
  52. data/test/multiverse/suites/agent_only/testing_app.rb +6 -0
  53. data/test/multiverse/suites/agent_only/thread_profiling_test.rb +5 -5
  54. data/test/multiverse/suites/agent_only/xray_sessions_test.rb +163 -0
  55. data/test/multiverse/suites/rails/request_statistics_test.rb +2 -2
  56. data/test/multiverse/suites/rails/view_instrumentation_test.rb +20 -21
  57. data/test/new_relic/agent/agent/connect_test.rb +0 -10
  58. data/test/new_relic/agent/agent_test.rb +27 -44
  59. data/test/new_relic/agent/browser_monitoring_test.rb +0 -52
  60. data/test/new_relic/agent/commands/agent_command_router_test.rb +150 -12
  61. data/test/new_relic/agent/commands/{thread_profiler_test.rb → thread_profiler_session_test.rb} +58 -19
  62. data/test/new_relic/agent/commands/xray_session_collection_test.rb +332 -0
  63. data/test/new_relic/agent/commands/xray_session_test.rb +42 -0
  64. data/test/new_relic/agent/configuration/manager_test.rb +2 -1
  65. data/test/new_relic/agent/configuration/server_source_test.rb +10 -10
  66. data/test/new_relic/agent/cpu_sampler_test.rb +50 -0
  67. data/test/new_relic/agent/instrumentation/action_controller_subscriber_test.rb +31 -0
  68. data/test/new_relic/agent/instrumentation/queue_time_test.rb +0 -1
  69. data/test/new_relic/agent/instrumentation/sequel_test.rb +1 -1
  70. data/test/new_relic/agent/instrumentation/task_instrumentation_test.rb +0 -1
  71. data/test/new_relic/agent/memory_logger_test.rb +53 -0
  72. data/test/new_relic/agent/new_relic_service_test.rb +1 -1
  73. data/test/new_relic/agent/pipe_channel_manager_test.rb +4 -5
  74. data/test/new_relic/agent/request_sampler_test.rb +70 -20
  75. data/test/new_relic/agent/rules_engine_test.rb +6 -0
  76. data/test/new_relic/agent/threading/agent_thread_test.rb +2 -2
  77. data/test/new_relic/agent/threading/backtrace_node_test.rb +110 -17
  78. data/test/new_relic/agent/threading/backtrace_service_test.rb +567 -0
  79. data/test/new_relic/agent/threading/fake_thread.rb +4 -0
  80. data/test/new_relic/agent/threading/thread_profile_test.rb +141 -217
  81. data/test/new_relic/agent/threading/threaded_test_case.rb +3 -8
  82. data/test/new_relic/agent/transaction/developer_mode_sample_buffer_test.rb +69 -0
  83. data/test/new_relic/agent/transaction/force_persist_sample_buffer_test.rb +52 -0
  84. data/test/new_relic/agent/transaction/slowest_sample_buffer_test.rb +67 -0
  85. data/test/new_relic/agent/transaction/xray_sample_buffer_test.rb +71 -0
  86. data/test/new_relic/agent/transaction_sampler_test.rb +171 -307
  87. data/test/new_relic/agent/transaction_test.rb +33 -5
  88. data/test/new_relic/agent/worker_loop_test.rb +33 -11
  89. data/test/new_relic/coerce_test.rb +13 -0
  90. data/test/new_relic/fake_collector.rb +26 -3
  91. data/test/new_relic/multiverse_helpers.rb +2 -0
  92. data/test/new_relic/rack/browser_monitoring_test.rb +12 -0
  93. data/test/new_relic/rack/developer_mode_test.rb +2 -2
  94. data/test/new_relic/transaction_sample_test.rb +19 -2
  95. data/test/performance/lib/performance/console_reporter.rb +1 -1
  96. data/test/performance/lib/performance/test_case.rb +7 -3
  97. data/test/performance/script/runner +3 -0
  98. data/test/performance/suites/thread_profiling.rb +83 -0
  99. data/test/test_helper.rb +2 -2
  100. data.tar.gz.sig +0 -0
  101. metadata +32 -32
  102. metadata.gz.sig +1 -1
  103. data/lib/new_relic/agent/commands/thread_profiler.rb +0 -80
@@ -30,7 +30,7 @@ class RequestStatsTest < ActionController::TestCase
30
30
  #
31
31
 
32
32
  def test_doesnt_send_when_disabled
33
- with_config( :'request_sampler.enabled' => false ) do
33
+ with_config( :'analytics_events.enabled' => false ) do
34
34
  20.times { get :stats_action }
35
35
 
36
36
  NewRelic::Agent.agent.send(:harvest_and_send_analytic_event_data)
@@ -40,7 +40,7 @@ class RequestStatsTest < ActionController::TestCase
40
40
  end
41
41
 
42
42
  def test_request_times_should_be_reported_if_enabled
43
- with_config( :'request_sampler.enabled' => true ) do
43
+ with_config( :'analytics_events.enabled' => true ) do
44
44
  20.times { get :stats_action }
45
45
 
46
46
  NewRelic::Agent.agent.send(:harvest_and_send_analytic_event_data)
@@ -121,13 +121,13 @@ end
121
121
  class NormalishRenderTest < ViewControllerTest
122
122
  test "should count all the template and partial segments" do
123
123
  get :template_render_with_3_partial_renders
124
- sample = NewRelic::Agent.agent.transaction_sampler.samples.last
124
+ sample = NewRelic::Agent.agent.transaction_sampler.last_sample
125
125
  assert_equal 5, sample.count_segments, "should be a node for the controller action, the template, and 3 partials (5)"
126
126
  end
127
127
 
128
128
  test "should have 3 segments with the metric name 'View/views/_a_partial.html.erb/Partial'" do
129
129
  get :template_render_with_3_partial_renders
130
- sample = NewRelic::Agent.agent.transaction_sampler.samples.last
130
+ sample = NewRelic::Agent.agent.transaction_sampler.last_sample
131
131
 
132
132
  partial_segments = sample.root_segment.called_segments.first.called_segments.first.called_segments
133
133
  assert_equal 3, partial_segments.size, "sanity check"
@@ -141,13 +141,13 @@ class TextRenderTest < ViewControllerTest
141
141
  if Rails::VERSION::MAJOR.to_i == 3 && Rails::VERSION::MINOR.to_i == 0
142
142
  test "should not instrument rendering of text" do
143
143
  get :text_render
144
- sample = NewRelic::Agent.agent.transaction_sampler.samples.last
144
+ sample = NewRelic::Agent.agent.transaction_sampler.last_sample
145
145
  assert_equal [], sample.root_segment.called_segments.first.called_segments
146
146
  end
147
147
  else
148
148
  test "should create a metric for the rendered text" do
149
149
  get :text_render
150
- sample = NewRelic::Agent.agent.transaction_sampler.samples.last
150
+ sample = NewRelic::Agent.agent.transaction_sampler.last_sample
151
151
  text_segment = sample.root_segment.called_segments.first.called_segments.first
152
152
  assert_equal 'View/text template/Rendering', text_segment.metric_name
153
153
  end
@@ -157,7 +157,7 @@ end
157
157
  class InlineTemplateRenderTest < ViewControllerTest
158
158
  test "should create a metric for the rendered inline template" do
159
159
  get :inline_render
160
- sample = NewRelic::Agent.agent.transaction_sampler.samples.last
160
+ sample = NewRelic::Agent.agent.transaction_sampler.last_sample
161
161
  text_segment = sample.root_segment.called_segments.first.called_segments.first
162
162
  assert_equal 'View/inline template/Rendering', text_segment.metric_name
163
163
  end
@@ -166,26 +166,25 @@ end
166
166
  class HamlRenderTest < ViewControllerTest
167
167
  test "should create a metric for the rendered haml template" do
168
168
  get :haml_render
169
- sample = NewRelic::Agent.agent.transaction_sampler.samples.last
169
+ sample = NewRelic::Agent.agent.transaction_sampler.last_sample
170
170
  text_segment = sample.root_segment.called_segments.first.called_segments.first
171
171
  assert_equal 'View/views/haml_view.html.haml/Rendering', text_segment.metric_name
172
172
  end
173
173
  end
174
174
 
175
175
  class MissingTemplateTest < ViewControllerTest
176
- # Rails 3.0 has different behavior for rendering an empty array. We're okay with this.
177
- if Rails::VERSION::MAJOR.to_i == 3 && Rails::VERSION::MINOR.to_i == 0
178
- test "should create an proper metric when the template is unknown" do
179
- get :no_template
180
- sample = NewRelic::Agent.agent.transaction_sampler.samples.last
181
- text_segment = sample.root_segment.called_segments.first.called_segments.first
176
+ test "should create an proper metric when the template is unknown" do
177
+ get :no_template
178
+ sample = NewRelic::Agent.agent.transaction_sampler.last_sample
179
+ text_segment = sample.root_segment.called_segments.first.called_segments.first
180
+
181
+ # Different versions have significant difference in handling, but we're
182
+ # happy enough with what each of them does in the unknown case
183
+ if Rails::VERSION::MAJOR.to_i == 3 && Rails::VERSION::MINOR.to_i == 0
182
184
  assert_nil text_segment
183
- end
184
- else
185
- test "should create an proper metric when the template is unknown" do
186
- get :no_template
187
- sample = NewRelic::Agent.agent.transaction_sampler.samples.last
188
- text_segment = sample.root_segment.called_segments.first.called_segments.first
185
+ elsif Rails::VERSION::MAJOR.to_i == 3
186
+ assert_equal 'View/collection/Partial', text_segment.metric_name
187
+ else
189
188
  assert_equal 'View/(unknown)/Partial', text_segment.metric_name
190
189
  end
191
190
  end
@@ -194,7 +193,7 @@ end
194
193
  class CollectionTemplateTest < ViewControllerTest
195
194
  test "should create a proper metric when we render a collection" do
196
195
  get :collection_render
197
- sample = NewRelic::Agent.agent.transaction_sampler.samples.last
196
+ sample = NewRelic::Agent.agent.transaction_sampler.last_sample
198
197
  text_segment = sample.root_segment.called_segments.first.called_segments.first
199
198
  assert_equal "View/foos/_foo.html.haml/Partial", text_segment.metric_name
200
199
  end
@@ -204,7 +203,7 @@ class UninstrumentedRendersTest < ViewControllerTest
204
203
  [:js_render, :xml_render, :proc_render, :json_render ].each do |action|
205
204
  test "should not instrument rendering of #{action.inspect}" do
206
205
  get action
207
- sample = NewRelic::Agent.agent.transaction_sampler.samples.last
206
+ sample = NewRelic::Agent.agent.transaction_sampler.last_sample
208
207
  assert_equal [], sample.root_segment.called_segments.first.called_segments
209
208
  end
210
209
  end
@@ -213,7 +212,7 @@ end
213
212
  class FileRenderTest < ViewControllerTest
214
213
  test "should create a metric for rendered file that does not include the filename so it doesn't metric explode" do
215
214
  get :file_render
216
- sample = NewRelic::Agent.agent.transaction_sampler.samples.last
215
+ sample = NewRelic::Agent.agent.transaction_sampler.last_sample
217
216
  text_segment = sample.root_segment.called_segments.first.called_segments.first
218
217
  assert_equal 'View/file/Rendering', text_segment.metric_name
219
218
  end
@@ -106,16 +106,6 @@ class NewRelic::Agent::Agent::ConnectTest < Test::Unit::TestCase
106
106
  end
107
107
  end
108
108
 
109
- def test_configure_transaction_tracer_with_random_sampling
110
- with_config(:'transaction_tracer.transaction_threshold' => 5,
111
- :'transaction_tracer.random_sample' => true) do
112
- sample = make_sql_transaction
113
- @transaction_sampler.store_sample(sample)
114
-
115
- assert_equal sample, @transaction_sampler.instance_variable_get(:@random_sample)
116
- end
117
- end
118
-
119
109
  def test_configure_transaction_tracer_positive
120
110
  with_config(:'transaction_tracer.enabled' => true) do
121
111
  assert @transaction_sampler.enabled?
@@ -3,7 +3,6 @@
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 'new_relic/agent/commands/thread_profiler'
7
6
 
8
7
  module NewRelic
9
8
  module Agent
@@ -17,23 +16,6 @@ module NewRelic
17
16
  @agent.stubs(:start_worker_thread)
18
17
  end
19
18
 
20
- #
21
- # Helpers
22
- #
23
-
24
- def with_profile(opts)
25
- profile = NewRelic::Agent::Threading::ThreadProfile.new(create_agent_command)
26
- profile.aggregate(["chunky.rb:42:in `bacon'"], profile.traces[:other])
27
- profile.instance_variable_set(:@finished, opts[:finished])
28
-
29
- @agent.thread_profiler.instance_variable_set(:@profile, profile)
30
- profile
31
- end
32
-
33
- #
34
- # Tests
35
- #
36
-
37
19
  def test_after_fork_reporting_to_channel
38
20
  @agent.stubs(:connected?).returns(true)
39
21
  @agent.after_fork(:report_to_channel => 123)
@@ -105,7 +87,10 @@ module NewRelic
105
87
  with_config(:'transaction_tracer.explain_threshold' => 2,
106
88
  :'transaction_tracer.explain_enabled' => true,
107
89
  :'transaction_tracer.record_sql' => 'raw') do
108
- trace = stub('transaction trace', :force_persist => true,
90
+ trace = stub('transaction trace',
91
+ :duration => 2.0, :threshold => 1.0,
92
+ :transaction_name => nil,
93
+ :force_persist => true,
109
94
  :truncate => 4000)
110
95
  trace.expects(:prepare_to_send).with(:record_sql => :raw,
111
96
  :explain_sql => 2,
@@ -115,30 +100,6 @@ module NewRelic
115
100
  end
116
101
  end
117
102
 
118
- def test_graceful_shutdown_ends_thread_profiling
119
- @agent.thread_profiler.expects(:stop).once
120
- @agent.stubs(:connected?).returns(true)
121
- @agent.send(:graceful_disconnect)
122
- end
123
-
124
- def test_harvest_and_send_thread_profile
125
- profile = with_profile(:finished => true)
126
- @agent.service.expects(:profile_data).with(any_parameters)
127
- @agent.send(:harvest_and_send_thread_profile, false)
128
- end
129
-
130
- def test_harvest_and_send_thread_profile_when_not_finished
131
- with_profile(:finished => false)
132
- @agent.service.expects(:profile_data).never
133
- @agent.send(:harvest_and_send_thread_profile, false)
134
- end
135
-
136
- def test_harvest_and_send_thread_profile_when_not_finished_but_disconnecting
137
- profile = with_profile(:finished => false)
138
- @agent.service.expects(:profile_data).with(any_parameters)
139
- @agent.send(:harvest_and_send_thread_profile, true)
140
- end
141
-
142
103
  def test_harvest_timeslice_data
143
104
  assert_equal({}, @agent.send(:harvest_timeslice_data),
144
105
  'should return timeslice data')
@@ -176,7 +137,13 @@ module NewRelic
176
137
 
177
138
  def test_handle_for_agent_commands
178
139
  @agent.service.expects(:get_agent_commands).returns([]).once
179
- @agent.send :handle_agent_commands
140
+ @agent.send :check_for_and_handle_agent_commands
141
+ end
142
+
143
+ def test_harvest_and_send_for_agent_commands
144
+ @agent.service.expects(:profile_data).with(any_parameters)
145
+ @agent.agent_command_router.stubs(:harvest_data_to_send).returns({:profile_data => Object.new})
146
+ @agent.send :harvest_and_send_for_agent_commands
180
147
  end
181
148
 
182
149
  def test_merge_data_from_empty
@@ -257,6 +224,22 @@ module NewRelic
257
224
  assert_equal 0, @agent.stats_engine.get_stats("Errors/all").call_count
258
225
  end
259
226
 
227
+ def test_harvest_and_send_analytic_event_data_merges_in_samples_on_failure
228
+ service = @agent.service
229
+ request_sampler = @agent.instance_variable_get(:@request_sampler)
230
+ samples = [mock('some analytics event')]
231
+
232
+ request_sampler.expects(:harvest).returns(samples)
233
+ request_sampler.expects(:merge).with(samples)
234
+
235
+ # simulate a failure in transmitting analytics events
236
+ service.stubs(:analytic_event_data).raises(StandardError.new)
237
+
238
+ assert_raises(StandardError) do
239
+ @agent.send(:harvest_and_send_analytic_event_data)
240
+ end
241
+ end
242
+
260
243
  def test_connect_retries_on_timeout
261
244
  service = @agent.service
262
245
  def service.connect(opts={})
@@ -15,7 +15,6 @@ class NewRelic::Agent::BrowserMonitoringTest < Test::Unit::TestCase
15
15
  NewRelic::Agent.manual_start
16
16
  @config = {
17
17
  :beacon => 'beacon',
18
- :disable_mobile_headers => false,
19
18
  :browser_key => 'browserKey',
20
19
  :application_id => '5, 6', # collector can return app multiple ids
21
20
  :'rum.enabled' => true,
@@ -312,46 +311,6 @@ var e=document.createElement("script");'
312
311
  assert_equal Base64.encode64(text).gsub("\n", ''), unoutput
313
312
  end
314
313
 
315
- def test_no_mobile_response_header_if_no_mobile_request_header_given
316
- request = Rack::Request.new({})
317
- response = Rack::Response.new
318
-
319
- NewRelic::Agent::BrowserMonitoring.insert_mobile_response_header(request, response)
320
- assert_nil response['X-NewRelic-Beacon-Url']
321
- end
322
-
323
- def test_no_mobile_response_header_if_mobile_request_header_is_false
324
- request = Rack::Request.new('HTTP_X_NEWRELIC_MOBILE_TRACE' => 'false')
325
- response = Rack::Response.new
326
-
327
- NewRelic::Agent::BrowserMonitoring.insert_mobile_response_header(request, response)
328
- assert_nil response['X-NewRelic-Beacon-Url']
329
- end
330
-
331
- def test_place_beacon_url_header_when_given_mobile_request_header
332
- response = mobile_transaction
333
- assert_equal('http://beacon/mobile/1/browserKey',
334
- response['X-NewRelic-Beacon-Url'])
335
- end
336
-
337
- def test_place_beacon_url_header_when_given_mobile_request_header_with_https
338
- request = Rack::Request.new('X_NEWRELIC_MOBILE_TRACE' => 'true',
339
- 'rack.url_scheme' => 'https')
340
- response = mobile_transaction(request)
341
- assert_equal('https://beacon/mobile/1/browserKey',
342
- response['X-NewRelic-Beacon-Url'])
343
- end
344
-
345
- def test_place_beacon_payload_head_when_given_mobile_request_header
346
- Time.stubs(:now).returns(Time.at(6))
347
- response = mobile_transaction
348
- txn_name = obfuscate(NewRelic::Agent.instance.beacon_configuration,
349
- browser_monitoring_transaction_name)
350
- expected_payload = %|["5, 6","#{txn_name}",#{current_timings.queue_time_in_millis},#{current_timings.app_time_in_millis}]|
351
-
352
- assert_equal expected_payload, response['X-NewRelic-App-Server-Metrics'].strip
353
- end
354
-
355
314
  def test_freezes_transaction_name_when_footer_is_written
356
315
  with_config(:license_key => 'a' * 13) do
357
316
  in_transaction do
@@ -361,15 +320,4 @@ var e=document.createElement("script");'
361
320
  end
362
321
  end
363
322
  end
364
-
365
- def mobile_transaction(request=nil)
366
- request ||= Rack::Request.new('X-NewRelic-Mobile-Trace' => 'true')
367
- response = Rack::Response.new
368
- txn = NewRelic::Agent::Transaction.new
369
- txn.name = 'a transaction name'
370
- txn.start_time = Time.at(5)
371
- NewRelic::Agent::TransactionState.get.transaction = txn
372
- NewRelic::Agent::BrowserMonitoring.insert_mobile_response_header(request, response)
373
- response
374
- end
375
323
  end
@@ -4,6 +4,7 @@
4
4
 
5
5
  require File.expand_path(File.join(File.dirname(__FILE__),'..','..','..','test_helper'))
6
6
  require 'new_relic/agent/commands/agent_command_router'
7
+ require 'new_relic/agent/commands/xray_session'
7
8
 
8
9
  class AgentCommandRouterTest < Test::Unit::TestCase
9
10
 
@@ -36,46 +37,52 @@ class AgentCommandRouterTest < Test::Unit::TestCase
36
37
  NewRelic::Agent.agent.stubs(:service).returns(@service)
37
38
  @calls = []
38
39
 
39
- @agent_commands = NewRelic::Agent::Commands::AgentCommandRouter.new(nil)
40
+ @agent_commands = NewRelic::Agent::Commands::AgentCommandRouter.new
40
41
  @agent_commands.handlers["bazzle"] = Proc.new { |args| handle_bazzle_command(args) }
41
42
  @agent_commands.handlers["boom"] = Proc.new { |args| handle_boom_command(args) }
42
43
  end
43
44
 
44
- def test_handle_agent_commands_dispatches_command
45
+ def teardown
46
+ agent_commands.backtrace_service.worker_thread.join if agent_commands.backtrace_service.worker_thread
47
+ end
48
+
49
+ # General command routing
50
+
51
+ def test_check_for_and_handle_agent_commands_dispatches_command
45
52
  service.stubs(:get_agent_commands).returns([BAZZLE])
46
53
  service.stubs(:agent_command_results)
47
54
 
48
- agent_commands.handle_agent_commands
55
+ agent_commands.check_for_and_handle_agent_commands
49
56
 
50
57
  assert_equal [DEFAULT_ARGS], calls
51
58
  end
52
59
 
53
- def test_handle_agent_commands_generates_results
60
+ def test_check_for_and_handle_agent_commands_generates_results
54
61
  service.stubs(:get_agent_commands).returns([BAZZLE])
55
62
  service.expects(:agent_command_results).with({ BAZZLE_ID.to_s => {} })
56
63
 
57
- agent_commands.handle_agent_commands
64
+ agent_commands.check_for_and_handle_agent_commands
58
65
  end
59
66
 
60
- def test_handle_agent_commands_dispatches_with_error
67
+ def test_check_for_and_handle_agent_commands_dispatches_with_error
61
68
  service.stubs(:get_agent_commands).returns([BOOM])
62
69
  service.expects(:agent_command_results).with({ BOOM_ID.to_s => { "error" => "BOOOOOM" }})
63
70
 
64
- agent_commands.handle_agent_commands
71
+ agent_commands.check_for_and_handle_agent_commands
65
72
  end
66
73
 
67
- def test_handle_agent_commands_allows_multiple
74
+ def test_check_for_and_handle_agent_commands_allows_multiple
68
75
  service.stubs(:get_agent_commands).returns([BAZZLE, BOOM])
69
76
  service.expects(:agent_command_results).with({ BAZZLE_ID.to_s => {},
70
77
  BOOM_ID.to_s => { "error" => "BOOOOOM" }})
71
- agent_commands.handle_agent_commands
78
+ agent_commands.check_for_and_handle_agent_commands
72
79
  end
73
80
 
74
- def test_handle_agent_commands_doesnt_call_results_if_no_commands
81
+ def test_check_for_and_handle_agent_commands_doesnt_call_results_if_no_commands
75
82
  service.stubs(:get_agent_commands).returns([])
76
83
  service.expects(:agent_command_results).never
77
84
 
78
- agent_commands.handle_agent_commands
85
+ agent_commands.check_for_and_handle_agent_commands
79
86
  end
80
87
 
81
88
  def test_unrecognized_commands
@@ -84,7 +91,117 @@ class AgentCommandRouterTest < Test::Unit::TestCase
84
91
 
85
92
  expects_logging(:debug, regexp_matches(/unrecognized/i))
86
93
 
87
- agent_commands.handle_agent_commands
94
+ agent_commands.check_for_and_handle_agent_commands
95
+ end
96
+
97
+ # Start/stop X-Ray tests
98
+
99
+ def test_empty_agent_commands_stops_running_xray
100
+ start_xray_session(123)
101
+
102
+ service.stubs(:get_agent_commands).returns([])
103
+ agent_commands.check_for_and_handle_agent_commands
104
+
105
+ assert_false agent_commands.xray_session_collection.include?(123)
106
+ end
107
+
108
+ # Harvesting tests
109
+
110
+ if NewRelic::Agent::Threading::BacktraceService.is_supported?
111
+
112
+ DISCONNECTING = true
113
+ NOT_DISCONNECTING = false
114
+
115
+ def test_harvest_data_to_send_not_started
116
+ result = agent_commands.harvest_data_to_send(NOT_DISCONNECTING)
117
+ assert_equal({}, result)
118
+ end
119
+
120
+ def test_harvest_data_to_send_with_profile_in_progress
121
+ start_profile('duration' => 1.0)
122
+
123
+ result = agent_commands.harvest_data_to_send(NOT_DISCONNECTING)
124
+ assert_equal({}, result)
125
+ end
126
+
127
+ def test_harvest_data_to_send_with_profile_completed
128
+ start_profile('duration' => 1.0)
129
+
130
+ advance_time(1.1)
131
+ result = agent_commands.harvest_data_to_send(NOT_DISCONNECTING)
132
+
133
+ assert_not_nil result[:profile_data]
134
+ end
135
+
136
+ def test_can_stop_multiple_times_safely
137
+ start_profile('duration' => 1.0)
138
+
139
+ advance_time(1.1)
140
+ agent_commands.thread_profiler_session.stop(true)
141
+
142
+ result = agent_commands.harvest_data_to_send(NOT_DISCONNECTING)
143
+ assert_not_nil result[:profile_data]
144
+ end
145
+
146
+ def test_transmits_after_forced_stop
147
+ start_profile('duration' => 1.0)
148
+
149
+ agent_commands.thread_profiler_session.stop(true)
150
+
151
+ result = agent_commands.harvest_data_to_send(NOT_DISCONNECTING)
152
+ assert_not_nil result[:profile_data]
153
+ end
154
+
155
+ def test_harvest_data_to_send_with_no_profile_disconnecting
156
+ result = agent_commands.harvest_data_to_send(DISCONNECTING)
157
+ assert_nil result[:profile_data]
158
+ end
159
+
160
+ def test_harvest_data_to_send_with_profile_in_progress_but_disconnecting
161
+ start_profile('duration' => 1.0)
162
+
163
+ result = agent_commands.harvest_data_to_send(DISCONNECTING)
164
+ assert_not_nil result[:profile_data]
165
+ end
166
+
167
+ def test_harvest_data_to_send_with_xray_sessions_in_progress
168
+ start_xray_session(123)
169
+ start_xray_session(456)
170
+
171
+ sample_on_profiles
172
+
173
+ result = agent_commands.harvest_data_to_send(NOT_DISCONNECTING)
174
+
175
+ assert_equal 2, result[:profile_data].length
176
+ end
177
+
178
+ def test_harvest_data_to_send_with_xray_sessions_and_thread_profile_in_progress
179
+ start_xray_session(123)
180
+ start_xray_session(456)
181
+
182
+ start_profile('duration' => 1.0)
183
+
184
+ sample_on_profiles
185
+
186
+ result = agent_commands.harvest_data_to_send(NOT_DISCONNECTING)
187
+
188
+ assert_equal 2, result[:profile_data].length
189
+ end
190
+
191
+ def test_harvest_data_to_send_with_xray_sessions_and_completed_thread_profile
192
+ start_xray_session(123)
193
+ start_xray_session(456)
194
+
195
+ start_profile('duration' => 1.0)
196
+
197
+ sample_on_profiles
198
+ advance_time(1.1)
199
+
200
+ result = agent_commands.harvest_data_to_send(NOT_DISCONNECTING)
201
+
202
+ assert_equal 3, result[:profile_data].length
203
+ end
204
+
88
205
  end
89
206
 
90
207
  # Helpers
@@ -96,4 +213,25 @@ class AgentCommandRouterTest < Test::Unit::TestCase
96
213
  def handle_boom_command(command)
97
214
  raise NewRelic::Agent::Commands::AgentCommandRouter::AgentCommandError.new("BOOOOOM")
98
215
  end
216
+
217
+ def start_profile(args={})
218
+ freeze_time
219
+ agent_commands.backtrace_service.worker_loop.stubs(:run)
220
+ agent_commands.thread_profiler_session.start(create_agent_command(args))
221
+ end
222
+
223
+ def start_xray_session(id)
224
+ args = { 'x_ray_id' => id, 'key_transaction_name' => "txn_#{id}" }
225
+ session = NewRelic::Agent::Commands::XraySession.new(args)
226
+
227
+ agent_commands.backtrace_service.worker_loop.stubs(:run)
228
+ agent_commands.xray_session_collection.add_session(session)
229
+ end
230
+
231
+ def sample_on_profiles
232
+ agent_commands.backtrace_service.profiles.each do |(_, profile)|
233
+ profile.aggregate([], :request, Thread.current)
234
+ end
235
+ end
236
+
99
237
  end