newrelic_rpm 3.7.0.174.beta → 3.7.0.177

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. data.tar.gz.sig +0 -0
  2. data/CHANGELOG +27 -4
  3. data/bin/nrdebug +10 -4
  4. data/lib/new_relic/agent.rb +33 -11
  5. data/lib/new_relic/agent/agent.rb +83 -120
  6. data/lib/new_relic/agent/agent_logger.rb +28 -16
  7. data/lib/new_relic/agent/audit_logger.rb +3 -4
  8. data/lib/new_relic/agent/autostart.rb +20 -8
  9. data/lib/new_relic/agent/commands/agent_command_router.rb +26 -17
  10. data/lib/new_relic/agent/commands/thread_profiler_session.rb +2 -2
  11. data/lib/new_relic/agent/configuration/default_source.rb +146 -59
  12. data/lib/new_relic/agent/configuration/manager.rb +3 -3
  13. data/lib/new_relic/agent/cross_app_monitor.rb +15 -40
  14. data/lib/new_relic/agent/cross_app_tracing.rb +20 -12
  15. data/lib/new_relic/agent/database.rb +24 -0
  16. data/lib/new_relic/agent/error_collector.rb +6 -2
  17. data/lib/new_relic/agent/instrumentation/merb/controller.rb +3 -1
  18. data/lib/new_relic/agent/javascript_instrumentor.rb +187 -0
  19. data/lib/new_relic/agent/new_relic_service.rb +30 -22
  20. data/lib/new_relic/agent/obfuscator.rb +48 -0
  21. data/lib/new_relic/agent/request_sampler.rb +5 -13
  22. data/lib/new_relic/agent/shim_agent.rb +1 -0
  23. data/lib/new_relic/agent/sql_sampler.rb +15 -5
  24. data/lib/new_relic/agent/stats_engine/metric_stats.rb +9 -4
  25. data/lib/new_relic/agent/transaction.rb +0 -1
  26. data/lib/new_relic/agent/transaction_sampler.rb +28 -16
  27. data/lib/new_relic/agent/transaction_state.rb +9 -0
  28. data/lib/new_relic/agent/transaction_timings.rb +5 -1
  29. data/lib/new_relic/agent/worker_loop.rb +0 -10
  30. data/lib/new_relic/cli/deployments.rb +1 -1
  31. data/lib/new_relic/control/instance_methods.rb +1 -1
  32. data/lib/new_relic/helper.rb +3 -1
  33. data/lib/new_relic/rack/browser_monitoring.rb +1 -2
  34. data/lib/new_relic/transaction_sample.rb +11 -13
  35. data/lib/newrelic_rpm.rb +1 -0
  36. data/test/agent_helper.rb +20 -5
  37. data/test/environments/lib/environments/runner.rb +1 -0
  38. data/test/helpers/file_searching.rb +28 -0
  39. data/test/multiverse/lib/multiverse/suite.rb +36 -19
  40. data/test/multiverse/suites/agent_only/collector_exception_handling_test.rb +49 -0
  41. data/test/multiverse/suites/agent_only/http_response_code_test.rb +2 -2
  42. data/test/multiverse/suites/agent_only/rum_instrumentation_test.rb +4 -2
  43. data/test/multiverse/suites/agent_only/service_timeout_test.rb +1 -1
  44. data/test/multiverse/suites/agent_only/set_transaction_name_test.rb +7 -4
  45. data/test/multiverse/suites/agent_only/thread_profiling_test.rb +2 -1
  46. data/test/multiverse/suites/rails/error_tracing_test.rb +34 -4
  47. data/test/multiverse/suites/rails/ignore_test.rb +1 -1
  48. data/test/multiverse/suites/rails/request_statistics_test.rb +1 -3
  49. data/test/multiverse/suites/sequel/sequel_instrumentation_test.rb +10 -7
  50. data/test/multiverse/suites/sinatra/ignoring_test.rb +1 -1
  51. data/test/new_relic/agent/agent/start_worker_thread_test.rb +1 -1
  52. data/test/new_relic/agent/agent_logger_test.rb +108 -114
  53. data/test/new_relic/agent/agent_test.rb +139 -21
  54. data/test/new_relic/agent/audit_logger_test.rb +22 -20
  55. data/test/new_relic/agent/autostart_test.rb +3 -2
  56. data/test/new_relic/agent/commands/agent_command_router_test.rb +51 -32
  57. data/test/new_relic/agent/configuration/default_source_test.rb +8 -2
  58. data/test/new_relic/agent/configuration/manager_test.rb +5 -1
  59. data/test/new_relic/agent/configuration/orphan_configuration_test.rb +57 -0
  60. data/test/new_relic/agent/cross_app_monitor_test.rb +10 -26
  61. data/test/new_relic/agent/database_test.rb +32 -0
  62. data/test/new_relic/agent/error_collector_test.rb +33 -16
  63. data/test/new_relic/agent/instrumentation/active_record_instrumentation_test.rb +88 -71
  64. data/test/new_relic/agent/instrumentation/task_instrumentation_test.rb +2 -2
  65. data/test/new_relic/agent/javascript_instrumentor_test.rb +341 -0
  66. data/test/new_relic/agent/memcache_instrumentation_test.rb +91 -89
  67. data/test/new_relic/agent/method_tracer_test.rb +1 -1
  68. data/test/new_relic/agent/obfuscator_test.rb +77 -0
  69. data/test/new_relic/agent/pipe_channel_manager_test.rb +5 -5
  70. data/test/new_relic/agent/pipe_service_test.rb +1 -1
  71. data/test/new_relic/agent/request_sampler_test.rb +21 -11
  72. data/test/new_relic/agent/sql_sampler_test.rb +52 -8
  73. data/test/new_relic/agent/stats_engine/metric_stats_test.rb +6 -6
  74. data/test/new_relic/agent/stats_engine_test.rb +18 -2
  75. data/test/new_relic/agent/transaction_sampler_test.rb +98 -53
  76. data/test/new_relic/agent/transaction_state_test.rb +44 -0
  77. data/test/new_relic/agent/transaction_test.rb +1 -1
  78. data/test/new_relic/agent/transaction_timings_test.rb +15 -5
  79. data/test/new_relic/agent/worker_loop_test.rb +0 -9
  80. data/test/new_relic/agent_test.rb +9 -21
  81. data/test/new_relic/data_container_tests.rb +72 -0
  82. data/test/new_relic/fake_collector.rb +69 -20
  83. data/test/new_relic/http_client_test_cases.rb +17 -2
  84. data/test/new_relic/license_test.rb +6 -15
  85. data/test/new_relic/multiverse_helpers.rb +2 -3
  86. data/test/new_relic/rack/browser_monitoring_test.rb +15 -37
  87. data/test/new_relic/transaction_sample_test.rb +92 -62
  88. data/test/performance/suites/rum_autoinsertion.rb +0 -3
  89. data/test/rum/x_ua_meta_tag_spaces_around_equals.result.html +10 -0
  90. data/test/rum/x_ua_meta_tag_spaces_around_equals.source.html +10 -0
  91. data/test/test_helper.rb +9 -5
  92. metadata +29 -11
  93. metadata.gz.sig +0 -0
  94. data/lib/new_relic/agent/beacon_configuration.rb +0 -37
  95. data/lib/new_relic/agent/browser_monitoring.rb +0 -257
  96. data/test/new_relic/agent/beacon_configuration_test.rb +0 -44
  97. data/test/new_relic/agent/browser_monitoring_test.rb +0 -474
data.tar.gz.sig CHANGED
Binary file
data/CHANGELOG CHANGED
@@ -2,12 +2,35 @@
2
2
 
3
3
  ## v3.7.0 ##
4
4
 
5
+ * Official Rubinius support (for Rubinius >= 2.2.1)
6
+
7
+ We're happy to say that all known issues with the Ruby agent running on
8
+ Rubinius have been resolved as of Rubinius version 2.2.1! See
9
+ http://docs.newrelic.com/docs/ruby/rubinius for the most up-to-date status.
10
+
5
11
  * RUM injection updates
6
12
 
7
- The Ruby agent's code for both automatically and manually injecting the Real
8
- User Monitoring scripts has been updated. This should not require
9
- application changes, but does result in a different script being injected
10
- than previous versions of the agent.
13
+ The Ruby agent's code for both automatic and manual injection of Real User
14
+ Monitoring scripts has been improved. No application changes are required, but
15
+ the new injection logic is simpler, faster, more robust, and paves the way for
16
+ future improvements to Real User Monitoring.
17
+
18
+ * More robust communication with New Relic
19
+
20
+ Failures when transmitting data to New Relic could cause data to be held over
21
+ unnecessarily to a later harvest. This has been improved both to handle
22
+ errors more robustly and consistently, and to send data as soon as possible.
23
+
24
+ * Fix for agent not restarting on server-side config changes
25
+
26
+ A bug in 3.6.9 caused the agent to not reset correctly after server-side
27
+ config changes. New settings would not be received without a full process
28
+ restart. This has been fixed.
29
+
30
+ * Blacklisting rake spec tasks
31
+
32
+ A blacklist helps the agent avoid starting during rake tasks. Some default
33
+ RSpec tasks were missing. Thanks for the contribution Kohei Hasegawa!
11
34
 
12
35
  ## v3.6.9 ##
13
36
 
@@ -133,6 +133,7 @@ class RubyProcess
133
133
  backtrace_file = Tempfile.new('nrdebug_ruby_bt')
134
134
  File.chmod(0666, backtrace_file.path)
135
135
 
136
+ backtrace_gathering_code = 'Thread.list.each { |t| bt = t.backtrace rescue nil; puts \"#{t.inspect}\n#{bt && bt.join(\"\n\")}\n\n\" }'
136
137
  gdb_script_body = <<-END
137
138
  attach #{pid}
138
139
  t a a bt
@@ -142,6 +143,8 @@ class RubyProcess
142
143
  call (int)open("#{backtrace_file.path}", 2, 0)
143
144
  call (void)rb_backtrace()
144
145
  call (void)fflush(0)
146
+ call (void)rb_eval_string_protect("#{backtrace_gathering_code}",(int*)0)
147
+ call (void)fflush(0)
145
148
  quit
146
149
  END
147
150
  Logger.log("Using gdb script:\n#{gdb_script_body}")
@@ -212,7 +215,7 @@ class ProcessReport
212
215
  fail("Failed to attach to target process. Please try again with sudo.")
213
216
  end
214
217
  section(f, "C Backtraces") { c_backtraces }
215
- section(f, "Ruby Backtrace") { ruby_backtraces }
218
+ section(f, "Ruby Backtrace(s)") { ruby_backtraces }
216
219
  end
217
220
 
218
221
  section(f, "Open files") { @target.open_files }
@@ -227,13 +230,16 @@ end
227
230
  def prompt_for_confirmation(target_pid, target_cmd)
228
231
  puts "Are you sure you want to attach to PID #{target_pid} ('#{target_cmd}')}?"
229
232
  puts ''
230
- puts "Extracting debug information from this process may cause it to hang, crash,"
231
- puts "or otherwise malfunction. It is highly recommended that you only run this"
232
- puts "script against processes that are already unresponsive."
233
+ puts '************************** !WARNING! **************************'
234
+ puts "Extracting debug information from this process may cause it to CRASH OR HANG."
235
+ puts ''
236
+ puts "It is highly recommended that you only run this script against processes that"
237
+ puts "are already unresponsive."
233
238
  puts ''
234
239
  puts "Additionally, the output may contain sensitive information from the program's"
235
240
  puts "command line arguments, environment, or open file list. Please examine the"
236
241
  puts "output before sharing it."
242
+ puts '************************** !WARNING! **************************'
237
243
  puts ''
238
244
  puts "To continue, type 'continue':"
239
245
 
@@ -85,7 +85,6 @@ module NewRelic
85
85
  require 'new_relic/agent'
86
86
  require 'new_relic/agent/stats'
87
87
  require 'new_relic/agent/chained_call'
88
- require 'new_relic/agent/browser_monitoring'
89
88
  require 'new_relic/agent/cross_app_monitor'
90
89
  require 'new_relic/agent/agent'
91
90
  require 'new_relic/agent/shim_agent'
@@ -140,9 +139,6 @@ module NewRelic
140
139
  # An unrecoverable client-side error that prevents the agent from continuing
141
140
  class UnrecoverableAgentException < ServerConnectionException; end
142
141
 
143
- # Reserved for future use. Meant to represent a problem on the server side.
144
- class ServerError < StandardError; end
145
-
146
142
  class BackgroundLoadingError < StandardError; end
147
143
 
148
144
  # placeholder name used when we cannot determine a transaction's name
@@ -291,11 +287,20 @@ module NewRelic
291
287
  agent.after_fork(options)
292
288
  end
293
289
 
294
- # Clear out any unsent metric data. See NewRelic::Agent::Agent#reset_stats
295
- def reset_stats
296
- agent.reset_stats
290
+ # Clear out any data the agent has buffered but has not yet transmitted
291
+ # to the collector.
292
+ #
293
+ # @api public
294
+ def drop_buffered_data
295
+ agent.drop_buffered_data
297
296
  end
298
297
 
298
+ # Deprecated in favor of drop_buffered_data
299
+ #
300
+ # @api public
301
+ # @deprecated
302
+ def reset_stats; drop_buffered_data; end
303
+
299
304
  # Shutdown the agent. Call this before exiting. Sends any queued data
300
305
  # and kills the background thread.
301
306
  #
@@ -583,16 +588,33 @@ module NewRelic
583
588
  NewRelic::Agent.logger.debug "Ignoring exception during %p event notification" % [event_type]
584
589
  end
585
590
 
586
- # Returns a Javascript string which should be injected into the very top of the response body
591
+ # This method returns a string suitable for inclusion in a page - known as
592
+ # 'manual instrumentation' for Real User Monitoring. Can return either a
593
+ # script tag with associated javascript, or in the case of disabled Real
594
+ # User Monitoring, an empty string
595
+ #
596
+ # This is the header string - it should be placed as high in the page as is
597
+ # reasonably possible - that is, before any style or javascript inclusions,
598
+ # but after any header-related meta tags
599
+ #
600
+ # In previous agents there was a corresponding footer required, but all the
601
+ # work is now done by this single method.
602
+ #
603
+ # @api public
587
604
  #
588
605
  def browser_timing_header
589
- agent.browser_timing_header
606
+ agent.javascript_instrumentor.browser_timing_header
590
607
  end
591
608
 
592
- # Returns a Javascript string which should be injected into the very bottom of the response body
609
+ # In previous agent releases, this method was required for manual RUM
610
+ # instrumentation. That work is now all done by the browser_timing_header
611
+ # method, but this is left for compatibility.
612
+ #
613
+ # @api public
614
+ # @deprecated
593
615
  #
594
616
  def browser_timing_footer
595
- agent.browser_timing_footer
617
+ ""
596
618
  end
597
619
 
598
620
  def_delegator :'NewRelic::Agent::PipeChannelManager', :register_report_channel
@@ -19,6 +19,7 @@ require 'new_relic/agent/event_listener'
19
19
  require 'new_relic/agent/cross_app_monitor'
20
20
  require 'new_relic/agent/request_sampler'
21
21
  require 'new_relic/agent/sampler_collection'
22
+ require 'new_relic/agent/javascript_instrumentor'
22
23
  require 'new_relic/environment_report'
23
24
 
24
25
  module NewRelic
@@ -38,8 +39,6 @@ module NewRelic
38
39
  @service = NewRelic::Agent::NewRelicService.new
39
40
  end
40
41
 
41
- @launch_time = Time.now
42
-
43
42
  @events = NewRelic::Agent::EventListener.new
44
43
  @stats_engine = NewRelic::Agent::StatsEngine.new
45
44
  @transaction_sampler = NewRelic::Agent::TransactionSampler.new
@@ -50,6 +49,7 @@ module NewRelic
50
49
  @transaction_rules = NewRelic::Agent::RulesEngine.new
51
50
  @request_sampler = NewRelic::Agent::RequestSampler.new(@events)
52
51
  @harvest_samplers = NewRelic::Agent::SamplerCollection.new(@events)
52
+ @javascript_instrumentor = NewRelic::Agent::JavascriptInstrumentor.new(@events)
53
53
 
54
54
  @connect_state = :pending
55
55
  @connect_attempts = 0
@@ -86,10 +86,8 @@ module NewRelic
86
86
  attr_reader :harvest_samplers
87
87
  # whether we should record raw, obfuscated, or no sql
88
88
  attr_reader :record_sql
89
- # a configuration for the Real User Monitoring system -
90
- # handles things like static setup of the header for inclusion
91
- # into pages
92
- attr_reader :beacon_configuration
89
+ # builder for JS agent scripts to inject
90
+ attr_reader :javascript_instrumentor
93
91
  # cross application tracing ids and encoding
94
92
  attr_reader :cross_process_id
95
93
  attr_reader :cross_app_encoding_bytes
@@ -185,7 +183,7 @@ module NewRelic
185
183
  reset_objects_with_locks
186
184
 
187
185
  # Clear out stats that are left over from parent process
188
- reset_stats
186
+ drop_buffered_data
189
187
 
190
188
  generate_environment_report unless @service.is_a?(NewRelic::Agent::PipeService)
191
189
  start_worker_thread(options)
@@ -499,17 +497,20 @@ module NewRelic
499
497
  log_version_and_pid
500
498
  end
501
499
 
502
- # Clear out the metric data, errors, and transaction traces,
503
- # making sure the agent is in a fresh state
504
- def reset_stats
505
- @stats_engine.reset_stats
500
+ # Clear out the metric data, errors, and transaction traces, etc.
501
+ def drop_buffered_data
502
+ @stats_engine.reset!
506
503
  @error_collector.reset!
507
504
  @transaction_sampler.reset!
508
505
  @request_sampler.reset!
509
506
  @sql_sampler.reset!
510
- @launch_time = Time.now
511
507
  end
512
508
 
509
+ # Deprecated, and not part of the public API, but here for backwards
510
+ # compatibility because some 3rd-party gems call it.
511
+ # @deprecated
512
+ def reset_stats; drop_buffered_data; end
513
+
513
514
  # Clear out state for any objects that we know lock from our parents
514
515
  # This is necessary for cases where we're in a forked child and Ruby
515
516
  # might be holding locks for background thread that aren't there anymore.
@@ -553,10 +554,12 @@ module NewRelic
553
554
  harvest_lock.unlock if harvest_lock.locked?
554
555
  end
555
556
 
556
- # Creates the worker loop and loads it with the instructions
557
- # it should run every @report_period seconds
557
+ def create_worker_loop
558
+ WorkerLoop.new
559
+ end
560
+
558
561
  def create_and_run_worker_loop
559
- @worker_loop = WorkerLoop.new
562
+ @worker_loop = create_worker_loop
560
563
  @worker_loop.run(Agent.config[:data_report_period]) do
561
564
  transmit_data
562
565
  end
@@ -567,7 +570,7 @@ module NewRelic
567
570
  # waits a while to reconnect.
568
571
  def handle_force_restart(error)
569
572
  ::NewRelic::Agent.logger.debug error.message
570
- reset_stats
573
+ drop_buffered_data
571
574
  @service.reset_metric_id_cache if @service
572
575
  @connect_state = :pending
573
576
  sleep 30
@@ -794,8 +797,6 @@ module NewRelic
794
797
 
795
798
  # If you're adding something else here to respond to the server-side config,
796
799
  # use Agent.instance.events.subscribe(:finished_configuring) callback instead!
797
-
798
- @beacon_configuration = BeaconConfiguration.new
799
800
  end
800
801
 
801
802
  # Logs when we connect to the server, for debugging purposes
@@ -893,39 +894,60 @@ module NewRelic
893
894
  control.root
894
895
  end
895
896
 
896
- # calls the busy harvester and collects timeslice data to
897
- # send later
898
- def harvest_timeslice_data
899
- NewRelic::Agent::BusyCalculator.harvest_busy
900
- @stats_engine.harvest
897
+ # Harvests data from the given container, sends it to the named endpoint
898
+ # on the service, and automatically merges back in upon a recoverable
899
+ # failure.
900
+ #
901
+ # The given container should respond to:
902
+ #
903
+ # #harvest!
904
+ # returns an enumerable collection of data items to be sent to the
905
+ # collector.
906
+ #
907
+ # #reset!
908
+ # drop any stored data and reset to a clean state.
909
+ #
910
+ # #merge!(items)
911
+ # merge the given items back into the internal buffer of the
912
+ # container, so that they may be harvested again later.
913
+ #
914
+ def harvest_and_send_from_container(container, endpoint)
915
+ items = harvest_from_container(container, endpoint)
916
+ send_data_to_endpoint(endpoint, items, container) unless items.empty?
901
917
  end
902
918
 
903
- def harvest_and_send_timeslice_data
904
- timeslices = harvest_timeslice_data
919
+ def harvest_from_container(container, endpoint)
920
+ items = []
905
921
  begin
906
- @service.metric_data(timeslices)
922
+ items = container.harvest!
923
+ rescue => e
924
+ NewRelic::Agent.logger.error("Failed to harvest #{endpoint} data, resetting. Error: ", e)
925
+ container.reset!
926
+ end
927
+ items
928
+ end
929
+
930
+ def send_data_to_endpoint(endpoint, items, container)
931
+ NewRelic::Agent.logger.debug("Sending #{items.size} items to #{endpoint}")
932
+ begin
933
+ @service.send(endpoint, items)
934
+ rescue ForceRestartException, ForceDisconnectException
935
+ raise
907
936
  rescue UnrecoverableServerException => e
908
- ::NewRelic::Agent.logger.debug e.message
937
+ NewRelic::Agent.logger.warn("#{endpoint} data was rejected by remote service, discarding. Error: ", e)
909
938
  rescue => e
910
- NewRelic::Agent.logger.info("Failed to send timeslice data, trying again later. Error:", e)
911
- @stats_engine.merge!(timeslices)
939
+ NewRelic::Agent.logger.info("Unable to send #{endpoint} data, will try again later. Error: ", e)
940
+ container.merge!(items)
912
941
  end
913
942
  end
914
943
 
944
+ def harvest_and_send_timeslice_data
945
+ NewRelic::Agent::BusyCalculator.harvest_busy
946
+ harvest_and_send_from_container(@stats_engine, :metric_data)
947
+ end
948
+
915
949
  def harvest_and_send_slowest_sql
916
- # FIXME add the code to try to resend if our connection is down
917
- sql_traces = @sql_sampler.harvest
918
- unless sql_traces.empty?
919
- ::NewRelic::Agent.logger.debug "Sending (#{sql_traces.size}) sql traces"
920
- begin
921
- @service.sql_trace_data(sql_traces)
922
- rescue UnrecoverableServerException => e
923
- ::NewRelic::Agent.logger.debug e.message
924
- rescue => e
925
- ::NewRelic::Agent.logger.debug "Remerging SQL traces after #{e.class.name}: #{e.message}"
926
- @sql_sampler.merge!(sql_traces)
927
- end
928
- end
950
+ harvest_and_send_from_container(@sql_sampler, :sql_trace_data)
929
951
  end
930
952
 
931
953
  # This handles getting the transaction traces and then sending
@@ -935,89 +957,40 @@ module NewRelic
935
957
  # segments' execution times exceed our threshold (to avoid
936
958
  # unnecessary overhead of running explains on fast queries.)
937
959
  def harvest_and_send_transaction_traces
938
- traces = @transaction_sampler.harvest
939
- unless traces.empty?
940
- begin
941
- send_transaction_traces(traces)
942
- rescue UnrecoverableServerException => e
943
- # This indicates that there was a problem with the POST body, so
944
- # we discard the traces rather than trying again later.
945
- ::NewRelic::Agent.logger.debug("Server rejected transaction traces, discarding. Error: ", e)
946
- rescue => e
947
- ::NewRelic::Agent.logger.error("Failed to send transaction traces, will re-attempt next harvest. Error: ", e)
948
- @transaction_sampler.merge!(traces)
949
- end
950
- end
951
- end
952
-
953
- def send_transaction_traces(traces)
954
- start_time = Time.now
955
- ::NewRelic::Agent.logger.debug "Sending (#{traces.length}) transaction traces"
956
-
957
- options = {}
958
- unless NewRelic::Agent::Database.record_sql_method == :off
959
- options[:record_sql] = NewRelic::Agent::Database.record_sql_method
960
- end
961
-
962
- if Agent.config[:'transaction_tracer.explain_enabled']
963
- options[:explain_sql] = Agent.config[:'transaction_tracer.explain_threshold']
964
- end
965
-
966
- traces.each { |trace| trace.prepare_to_send!(options) }
967
-
968
- @service.transaction_sample_data(traces)
969
- ::NewRelic::Agent.logger.debug "Sent slowest sample (#{@service.agent_id}) in #{Time.now - start_time} seconds"
960
+ harvest_and_send_from_container(@transaction_sampler, :transaction_sample_data)
970
961
  end
971
962
 
972
- def harvest_and_send_for_agent_commands(disconnecting=false)
973
- data = @agent_command_router.harvest_data_to_send(disconnecting)
974
- data.each do |service_method, payload|
975
- @service.send(service_method, payload)
976
- end
963
+ def harvest_and_send_for_agent_commands
964
+ harvest_and_send_from_container(@agent_command_router, :profile_data)
977
965
  end
978
966
 
979
- # Handles getting the errors from the error collector and
980
- # sending them to the server, and any error cases like trying
981
- # to send very large errors
982
967
  def harvest_and_send_errors
983
- errors = @error_collector.harvest_errors
984
- if errors && !errors.empty?
985
- ::NewRelic::Agent.logger.debug "Sending #{errors.length} errors"
986
- begin
987
- @service.error_data(errors)
988
- rescue UnrecoverableServerException => e
989
- ::NewRelic::Agent.logger.debug e.message
990
- rescue => e
991
- ::NewRelic::Agent.logger.debug "Failed to send error traces, will try again later. Error:", e
992
- @error_collector.merge!(errors)
993
- end
994
- end
968
+ harvest_and_send_from_container(@error_collector, :error_data)
995
969
  end
996
970
 
997
- # Fetch samples from the RequestSampler and send them.
998
971
  def harvest_and_send_analytic_event_data
999
- samples = @request_sampler.harvest
1000
- begin
1001
- @service.analytic_event_data(samples) unless samples.empty?
1002
- rescue
1003
- @request_sampler.merge!(samples)
1004
- raise
1005
- end
972
+ harvest_and_send_from_container(@request_sampler, :analytic_event_data)
1006
973
  end
1007
974
 
1008
975
  def check_for_and_handle_agent_commands
1009
- @agent_command_router.check_for_and_handle_agent_commands
976
+ begin
977
+ @agent_command_router.check_for_and_handle_agent_commands
978
+ rescue ForceRestartException, ForceDisconnectException
979
+ raise
980
+ rescue => e
981
+ NewRelic::Agent.logger.warn("Error during check_for_and_handle_agent_commands, will retry later: ", e)
982
+ end
1010
983
  end
1011
984
 
1012
- def transmit_data(disconnecting=false)
985
+ def transmit_data
1013
986
  harvest_lock.synchronize do
1014
- transmit_data_already_locked(disconnecting)
987
+ transmit_data_already_locked
1015
988
  end
1016
989
  end
1017
990
 
1018
991
  # This method is expected to only be called with the harvest_lock
1019
992
  # already held
1020
- def transmit_data_already_locked(disconnecting)
993
+ def transmit_data_already_locked
1021
994
  now = Time.now
1022
995
  ::NewRelic::Agent.logger.debug "Sending data to New Relic Service"
1023
996
 
@@ -1030,19 +1003,8 @@ module NewRelic
1030
1003
  harvest_and_send_analytic_event_data
1031
1004
 
1032
1005
  check_for_and_handle_agent_commands
1033
- harvest_and_send_for_agent_commands(disconnecting)
1034
- end
1035
- rescue EOFError => e
1036
- ::NewRelic::Agent.logger.warn("EOFError after #{Time.now - now}s when transmitting data to New Relic Service.")
1037
- ::NewRelic::Agent.logger.debug(e)
1038
- rescue => e
1039
- retry_count ||= 0
1040
- retry_count += 1
1041
- if retry_count <= 1
1042
- ::NewRelic::Agent.logger.debug "retrying transmit_data after #{e}"
1043
- retry
1006
+ harvest_and_send_for_agent_commands
1044
1007
  end
1045
- raise e
1046
1008
  ensure
1047
1009
  NewRelic::Agent::Database.close_connections
1048
1010
  duration = (Time.now - now).to_f
@@ -1062,7 +1024,9 @@ module NewRelic
1062
1024
  if connected?
1063
1025
  begin
1064
1026
  @service.request_timeout = 10
1065
- transmit_data(true)
1027
+
1028
+ @events.notify(:before_shutdown)
1029
+ transmit_data
1066
1030
 
1067
1031
  if @connected_pid == $$ && !@service.kind_of?(NewRelic::Agent::NewRelicService)
1068
1032
  ::NewRelic::Agent.logger.debug "Sending New Relic service agent run shutdown message"
@@ -1082,7 +1046,6 @@ module NewRelic
1082
1046
 
1083
1047
  extend ClassMethods
1084
1048
  include InstanceMethods
1085
- include BrowserMonitoring
1086
1049
  end
1087
1050
  end
1088
1051
  end