newrelic_rpm 3.0.1 → 3.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of newrelic_rpm might be problematic. Click here for more details.

Files changed (74) hide show
  1. data/CHANGELOG +2 -3
  2. data/README.rdoc +3 -3
  3. data/lib/new_relic/agent.rb +19 -7
  4. data/lib/new_relic/agent/agent.rb +83 -19
  5. data/lib/new_relic/agent/beacon_configuration.rb +8 -12
  6. data/lib/new_relic/agent/browser_monitoring.rb +8 -8
  7. data/lib/new_relic/agent/error_collector.rb +13 -13
  8. data/lib/new_relic/agent/instrumentation.rb +9 -0
  9. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +10 -2
  10. data/lib/new_relic/agent/instrumentation/metric_frame.rb +41 -35
  11. data/lib/new_relic/agent/instrumentation/metric_frame/pop.rb +92 -0
  12. data/lib/new_relic/agent/method_tracer.rb +0 -2
  13. data/lib/new_relic/agent/shim_agent.rb +2 -0
  14. data/lib/new_relic/agent/stats_engine/metric_stats.rb +89 -60
  15. data/lib/new_relic/agent/stats_engine/transactions.rb +1 -1
  16. data/lib/new_relic/agent/worker_loop.rb +1 -1
  17. data/lib/new_relic/collection_helper.rb +0 -2
  18. data/lib/new_relic/control/class_methods.rb +25 -12
  19. data/lib/new_relic/control/logging_methods.rb +30 -17
  20. data/lib/new_relic/data_serialization.rb +81 -0
  21. data/lib/new_relic/local_environment.rb +1 -1
  22. data/lib/new_relic/metric_data.rb +9 -5
  23. data/lib/new_relic/metric_spec.rb +7 -1
  24. data/lib/new_relic/rack/browser_monitoring.rb +1 -7
  25. data/lib/new_relic/stats.rb +4 -0
  26. data/lib/new_relic/transaction_analysis.rb +45 -88
  27. data/lib/new_relic/transaction_analysis/segment_summary.rb +47 -0
  28. data/lib/new_relic/transaction_sample.rb +15 -332
  29. data/lib/new_relic/transaction_sample/composite_segment.rb +27 -0
  30. data/lib/new_relic/transaction_sample/fake_segment.rb +9 -0
  31. data/lib/new_relic/transaction_sample/segment.rb +250 -0
  32. data/lib/new_relic/transaction_sample/summary_segment.rb +21 -0
  33. data/lib/new_relic/version.rb +3 -3
  34. data/newrelic.yml +3 -3
  35. data/newrelic_rpm.gemspec +27 -4
  36. data/test/active_record_fixtures.rb +31 -13
  37. data/test/new_relic/agent/agent/start_worker_thread_test.rb +1 -3
  38. data/test/new_relic/agent/agent_test.rb +73 -28
  39. data/test/new_relic/agent/agent_test_controller_test.rb +11 -10
  40. data/test/new_relic/agent/beacon_configuration_test.rb +37 -20
  41. data/test/new_relic/agent/browser_monitoring_test.rb +17 -28
  42. data/test/new_relic/agent/error_collector/notice_error_test.rb +9 -7
  43. data/test/new_relic/agent/error_collector_test.rb +6 -7
  44. data/test/new_relic/agent/instrumentation/active_record_instrumentation_test.rb +12 -5
  45. data/test/new_relic/agent/instrumentation/metric_frame/pop_test.rb +195 -0
  46. data/test/new_relic/agent/instrumentation/net_instrumentation_test.rb +60 -58
  47. data/test/new_relic/agent/instrumentation/queue_time_test.rb +14 -0
  48. data/test/new_relic/agent/instrumentation/rack_test.rb +35 -0
  49. data/test/new_relic/agent/instrumentation/task_instrumentation_test.rb +0 -1
  50. data/test/new_relic/agent/method_tracer_test.rb +8 -8
  51. data/test/new_relic/agent/sampler_test.rb +19 -0
  52. data/test/new_relic/agent/shim_agent_test.rb +20 -0
  53. data/test/new_relic/agent/stats_engine/metric_stats/harvest_test.rb +150 -0
  54. data/test/new_relic/agent/stats_engine/metric_stats_test.rb +1 -0
  55. data/test/new_relic/agent/stats_engine/samplers_test.rb +4 -3
  56. data/test/new_relic/agent/{stats_engine/stats_engine_test.rb → stats_engine_test.rb} +8 -8
  57. data/test/new_relic/agent/transaction_sampler_test.rb +1 -1
  58. data/test/new_relic/agent/worker_loop_test.rb +2 -2
  59. data/test/new_relic/control/class_methods_test.rb +62 -0
  60. data/test/new_relic/control/logging_methods_test.rb +157 -0
  61. data/test/new_relic/control_test.rb +10 -10
  62. data/test/new_relic/data_serialization_test.rb +50 -0
  63. data/test/new_relic/local_environment_test.rb +13 -13
  64. data/test/new_relic/metric_data_test.rb +125 -0
  65. data/test/new_relic/metric_spec_test.rb +8 -0
  66. data/test/new_relic/transaction_analysis/segment_summary_test.rb +77 -0
  67. data/test/new_relic/transaction_analysis_test.rb +121 -0
  68. data/test/new_relic/transaction_sample/composite_segment_test.rb +35 -0
  69. data/test/new_relic/transaction_sample/fake_segment_test.rb +17 -0
  70. data/test/new_relic/transaction_sample/segment_test.rb +454 -0
  71. data/test/new_relic/transaction_sample/summary_segment_test.rb +31 -0
  72. data/test/new_relic/transaction_sample_test.rb +51 -0
  73. data/test/test_helper.rb +4 -14
  74. metadata +32 -7
data/CHANGELOG CHANGED
@@ -1,6 +1,5 @@
1
- v3.0.1
2
- * Updated Real User Monitoring to reduce javascript size and improve
3
- compatibility, fix a few known bugs
1
+ v3.1.0
2
+ * Experimental support for aggregating data from short-running processes using NewRelic::Agent.load_data and NewRelic::Agent.save_data
4
3
 
5
4
  v3.0.0
6
5
  * Support for Real User Monitoring
data/README.rdoc CHANGED
@@ -25,9 +25,9 @@ automatically in Rails applications.
25
25
 
26
26
  == Supported Environments
27
27
 
28
- * Ruby 1.8.6, 1.8.7 or 1.9.1, including REE
29
- * JRuby 1.3 minimum
30
- * Rails 1.2.6 or later for Production Mode
28
+ * Ruby 1.8.6, 1.8.7, 1.9.1, or 1.9.2, including REE
29
+ * JRuby 1.4 minimum
30
+ * Rails 2.0 or later for Production Mode
31
31
  * Rails 2.2 or later for Developer Mode
32
32
  * Merb 1.0 or later
33
33
  * Sinatra
@@ -125,7 +125,7 @@ module NewRelic
125
125
  @agent
126
126
  end
127
127
 
128
- def agent= new_instance #:nodoc:
128
+ def agent=(new_instance)#:nodoc:
129
129
  @agent = new_instance
130
130
  end
131
131
 
@@ -167,7 +167,7 @@ module NewRelic
167
167
  # (ie, RAILS_ENV) can be overridden with an :env argument.
168
168
  #
169
169
  def manual_start(options={})
170
- raise unless Hash === options
170
+ raise "Options must be a hash" unless Hash === options
171
171
  NewRelic::Control.instance.init_plugin({ :agent_enabled => true, :sync_startup => true }.merge(options))
172
172
  end
173
173
 
@@ -204,8 +204,20 @@ module NewRelic
204
204
 
205
205
  # Shutdown the agent. Call this before exiting. Sends any queued data
206
206
  # and kills the background thread.
207
- def shutdown
208
- agent.shutdown
207
+ def shutdown(options = {})
208
+ agent.shutdown(options)
209
+ end
210
+
211
+ def save_data
212
+ NewRelic::DataSerialization.dump_to_file do |old_data|
213
+ agent.merge_data_from(old_data)
214
+ agent.serialize
215
+ end
216
+ end
217
+
218
+ def load_data
219
+ agent.merge_data_from(NewRelic::DataSerialization.load_from_file)
220
+ {:metrics => agent.stats_engine.metrics.length, :traces => agent.unsent_traces_size, :errors => agent.unsent_errors_size}
209
221
  end
210
222
 
211
223
  # Add instrumentation files to the agent. The argument should be
@@ -214,7 +226,7 @@ module NewRelic
214
226
  # when the agent is not running it's better to use this method to
215
227
  # register instrumentation than just loading the files directly,
216
228
  # although that probably also works.
217
- def add_instrumentation file_pattern
229
+ def add_instrumentation(file_pattern)
218
230
  NewRelic::Control.instance.add_instrumentation file_pattern
219
231
  end
220
232
 
@@ -292,11 +304,11 @@ module NewRelic
292
304
  def is_execution_traced?
293
305
  Thread.current[:newrelic_untraced].nil? || Thread.current[:newrelic_untraced].last != false
294
306
  end
295
-
307
+
296
308
  def is_transaction_traced?
297
309
  Thread::current[:record_tt] != false
298
310
  end
299
-
311
+
300
312
  def is_sql_recorded?
301
313
  Thread::current[:record_sql] != false
302
314
  end
@@ -64,6 +64,18 @@ module NewRelic
64
64
  attr_reader :url_rules
65
65
  attr_reader :beacon_configuration
66
66
 
67
+ def unsent_errors_size
68
+ @unsent_errors.length if @unsent_errors
69
+ end
70
+
71
+ def unsent_traces_size
72
+ @traces.length if @traces
73
+ end
74
+
75
+ def unsent_timeslice_data
76
+ @unsent_timeslice_data.keys.length
77
+ end
78
+
67
79
  def record_transaction(duration_seconds, options={})
68
80
  is_error = options['is_error'] || options['error_message'] || options['exception']
69
81
  metric = options['metric']
@@ -150,9 +162,11 @@ module NewRelic
150
162
  end
151
163
 
152
164
  # Attempt a graceful shutdown of the agent.
153
- def shutdown
165
+ def shutdown(options={})
166
+ run_loop_before_exit = options.fetch(:force_send, false)
154
167
  return if not started?
155
168
  if @worker_loop
169
+ @worker_loop.run_task if run_loop_before_exit
156
170
  @worker_loop.stop
157
171
 
158
172
  log.debug "Starting Agent shutdown"
@@ -431,8 +445,9 @@ module NewRelic
431
445
  def create_and_run_worker_loop
432
446
  @worker_loop = WorkerLoop.new
433
447
  @worker_loop.run(@report_period) do
434
- harvest_and_send_slowest_sample if @should_send_samples
435
- harvest_and_send_errors if error_collector.enabled
448
+ NewRelic::Agent.load_data
449
+ harvest_and_send_errors
450
+ harvest_and_send_slowest_sample
436
451
  harvest_and_send_timeslice_data
437
452
  end
438
453
  end
@@ -662,6 +677,37 @@ module NewRelic
662
677
  end
663
678
  include Connect
664
679
 
680
+ def serialize
681
+ accumulator = []
682
+ accumulator[1] = harvest_transaction_traces if @transaction_sampler
683
+ accumulator[2] = harvest_errors if @error_collector
684
+ accumulator[0] = harvest_timeslice_data
685
+ accumulator
686
+ end
687
+
688
+ public :serialize
689
+
690
+ def merge_data_from(data)
691
+ metrics, transaction_traces, errors = data
692
+ @stats_engine.merge_data(metrics) if metrics
693
+ if transaction_traces
694
+ if @traces
695
+ @traces = @traces + transaction_traces
696
+ else
697
+ @traces = transaction_traces
698
+ end
699
+ end
700
+ if errors
701
+ if @unsent_errors
702
+ @unsent_errors = @unsent_errors + errors
703
+ else
704
+ @unsent_errors = errors
705
+ end
706
+ end
707
+ end
708
+
709
+ public :merge_data_from
710
+
665
711
  # Connect to the server and validate the license. If successful,
666
712
  # @connected has true when finished. If not successful, you can
667
713
  # keep calling this. Return false if we could not establish a
@@ -715,32 +761,39 @@ module NewRelic
715
761
  $0 =~ /ApplicationSpawner|^unicorn\S* master/
716
762
  end
717
763
 
718
- def harvest_and_send_timeslice_data
719
-
764
+ def harvest_timeslice_data(time=Time.now)
765
+ # this creates timeslices that are harvested below
720
766
  NewRelic::Agent::BusyCalculator.harvest_busy
721
767
 
722
- now = Time.now
723
- NewRelic::Agent.instance.stats_engine.get_stats_no_scope('Supportability/invoke_remote').record_data_point(0.0)
724
- NewRelic::Agent.instance.stats_engine.get_stats_no_scope('Supportability/invoke_remote/metric_data').record_data_point(0.0)
725
-
726
768
  @unsent_timeslice_data ||= {}
727
769
  @unsent_timeslice_data = @stats_engine.harvest_timeslice_data(@unsent_timeslice_data, @metric_ids)
770
+ @unsent_timeslice_data
771
+ end
728
772
 
773
+ def fill_metric_id_cache(pairs_of_specs_and_ids)
774
+ Array(pairs_of_specs_and_ids).each do |metric_spec, metric_id|
775
+ @metric_ids[metric_spec] = metric_id
776
+ end
777
+ end
778
+
779
+ def harvest_and_send_timeslice_data
780
+ now = Time.now
781
+ NewRelic::Agent.instance.stats_engine.get_stats_no_scope('Supportability/invoke_remote').record_data_point(0.0)
782
+ NewRelic::Agent.instance.stats_engine.get_stats_no_scope('Supportability/invoke_remote/metric_data').record_data_point(0.0)
783
+ harvest_timeslice_data(now)
729
784
  begin
730
785
  # In this version of the protocol, we get back an assoc array of spec to id.
731
- metric_ids = invoke_remote(:metric_data, @agent_id,
786
+ metric_specs_and_ids = invoke_remote(:metric_data, @agent_id,
732
787
  @last_harvest_time.to_f,
733
788
  now.to_f,
734
789
  @unsent_timeslice_data.values)
735
790
 
736
791
  rescue Timeout::Error
737
792
  # assume that the data was received. chances are that it was
738
- metric_ids = nil
793
+ metric_specs_and_ids = []
739
794
  end
740
795
 
741
- metric_ids.each do | spec, id |
742
- @metric_ids[spec] = id
743
- end if metric_ids
796
+ fill_metric_id_cache(metric_specs_and_ids)
744
797
 
745
798
  log.debug "#{now}: sent #{@unsent_timeslice_data.length} timeslices (#{@agent_id}) in #{Time.now - now} seconds"
746
799
 
@@ -754,9 +807,13 @@ module NewRelic
754
807
  # then the metric data is downsampled for another timeslices
755
808
  end
756
809
 
757
- def harvest_and_send_slowest_sample
810
+ def harvest_transaction_traces
758
811
  @traces = @transaction_sampler.harvest(@traces, @slowest_transaction_threshold)
812
+ @traces
813
+ end
759
814
 
815
+ def harvest_and_send_slowest_sample
816
+ harvest_transaction_traces
760
817
  unless @traces.empty?
761
818
  now = Time.now
762
819
  log.debug "Sending (#{@traces.length}) transaction traces"
@@ -792,8 +849,13 @@ module NewRelic
792
849
  # sample.
793
850
  end
794
851
 
795
- def harvest_and_send_errors
852
+ def harvest_errors
796
853
  @unsent_errors = @error_collector.harvest_errors(@unsent_errors)
854
+ @unsent_errors
855
+ end
856
+
857
+ def harvest_and_send_errors
858
+ harvest_errors
797
859
  if @unsent_errors && @unsent_errors.length > 0
798
860
  log.debug "Sending #{@unsent_errors.length} errors"
799
861
  begin
@@ -925,15 +987,17 @@ module NewRelic
925
987
  raise NewRelic::Agent::ServerConnectionException, "Recoverable error connecting to the server: #{e}"
926
988
  ensure
927
989
  NewRelic::Agent.instance.stats_engine.get_stats_no_scope('Supportability/invoke_remote').record_data_point((Time.now - now).to_f)
928
- NewRelic::Agent.instance.stats_engine.get_stats_no_scope('Supportability/invoke_remote/' + method.to_s).record_data_point((Time.now - now).to_f)
990
+ NewRelic::Agent.instance.stats_engine.get_stats_no_scope('Supportability/invoke_remote/' + method.to_s).record_data_point((Time.now - now).to_f)
929
991
  end
930
992
 
931
993
  def graceful_disconnect
932
994
  if @connected
933
995
  begin
934
996
  @request_timeout = 10
935
- log.debug "Flushing unsent metric data to server"
936
- @worker_loop.run_task
997
+ # log.debug "Flushing unsent metric data to server"
998
+ # harvest_and_send_timeslice_data
999
+ log.debug "Serializing agent data to disk"
1000
+ NewRelic::Agent.save_data
937
1001
  if @connected_pid == $$
938
1002
  log.debug "Sending RPM service agent run shutdown message"
939
1003
  invoke_remote :shutdown, @agent_id, Time.now.to_f
@@ -2,23 +2,19 @@ module NewRelic
2
2
  module Agent
3
3
  class BeaconConfiguration
4
4
  attr_reader :browser_timing_header
5
- attr_reader :browser_timing_static_footer
6
5
  attr_reader :application_id
7
6
  attr_reader :browser_monitoring_key
8
7
  attr_reader :beacon
9
8
  attr_reader :rum_enabled
10
9
  attr_reader :license_bytes
11
10
 
12
- JS_HEADER = "<script>var NREUMQ=[];NREUMQ.push([\"mark\",\"firstbyte\",new Date().getTime()]);</script>"
13
-
14
11
  def initialize(connect_data)
15
12
  @browser_monitoring_key = connect_data['browser_key']
16
13
  @application_id = connect_data['application_id']
17
14
  @beacon = connect_data['beacon']
18
15
  @rum_enabled = connect_data['rum.enabled']
19
16
  @rum_enabled = true if @rum_enabled.nil?
20
- @browser_timing_header = build_browser_timing_header
21
- @browser_timing_static_footer = build_load_file_js(connect_data)
17
+ @browser_timing_header = build_browser_timing_header(connect_data)
22
18
  end
23
19
 
24
20
  def license_bytes
@@ -29,22 +25,22 @@ module NewRelic
29
25
  @license_bytes
30
26
  end
31
27
 
32
- def build_load_file_js(connect_data)
28
+ def load_file_js(connect_data)
33
29
  return "" unless connect_data.fetch('rum.load_episodes_file', true)
34
30
 
35
31
  episodes_url = connect_data.fetch('episodes_url', '')
36
- "(function(){var d=document;var e=d.createElement(\"script\");e.async=true;e.src=\"#{episodes_url}\";var s=d.getElementsByTagName(\"script\")[0];s.parentNode.insertBefore(e,s);})();"
32
+ "(function(){var d=document;var e=d.createElement(\"script\");e.type=\"text/javascript\";e.async=true;e.src=\"#{episodes_url}\";var s=d.getElementsByTagName(\"script\")[0];s.parentNode.insertBefore(e,s);})()"
37
33
  end
38
34
 
39
- def javascript_header
40
- JS_HEADER.dup
35
+ def basic_javascript(connect_data)
36
+ "<script>var NREUMQ=[];NREUMQ.push([\"mark\",\"firstbyte\",new Date().getTime()]);#{load_file_js(connect_data)}</script>"
41
37
  end
42
38
 
43
- def build_browser_timing_header
39
+ def build_browser_timing_header(connect_data)
44
40
  return "" if !@rum_enabled
45
41
  return "" if @browser_monitoring_key.nil?
46
-
47
- value = javascript_header
42
+
43
+ value = basic_javascript(connect_data)
48
44
  if value.respond_to?(:html_safe)
49
45
  value.html_safe
50
46
  else
@@ -7,10 +7,10 @@ module NewRelic
7
7
  def browser_timing_header
8
8
  return "" if NewRelic::Agent.instance.beacon_configuration.nil?
9
9
  return "" if !NewRelic::Agent.is_transaction_traced? || !NewRelic::Agent.is_execution_traced?
10
-
10
+
11
11
  NewRelic::Agent.instance.beacon_configuration.browser_timing_header
12
12
  end
13
-
13
+
14
14
  def browser_timing_footer
15
15
  config = NewRelic::Agent.instance.beacon_configuration
16
16
  return "" if config.nil? || !config.rum_enabled || config.browser_monitoring_key.nil?
@@ -25,8 +25,8 @@ module NewRelic
25
25
  config = NewRelic::Agent.instance.beacon_configuration
26
26
  application_id = config.application_id
27
27
  beacon = config.beacon
28
- license_key = config.browser_monitoring_key
29
-
28
+ license_key = config.browser_monitoring_key
29
+
30
30
  footer_js_string(beacon, license_key, application_id)
31
31
  else
32
32
  ''
@@ -36,7 +36,7 @@ module NewRelic
36
36
  def browser_monitoring_transaction_name
37
37
  Thread.current[:newrelic_most_recent_transaction] || "<unknown>"
38
38
  end
39
-
39
+
40
40
  def browser_monitoring_start_time
41
41
  Thread.current[:newrelic_start_time]
42
42
  end
@@ -56,7 +56,7 @@ module NewRelic
56
56
 
57
57
  def footer_js_string(beacon, license_key, application_id)
58
58
  obfuscated_transaction_name = obfuscate(browser_monitoring_transaction_name)
59
- html_safe_if_needed("<script>#{NewRelic::Agent.instance.beacon_configuration.browser_timing_static_footer}NREUMQ.push([\"nrf2\",\"#{beacon}\",\"#{license_key}\",#{application_id},\"#{obfuscated_transaction_name}\",#{browser_monitoring_queue_time},#{browser_monitoring_app_time},new Date().getTime()])</script>")
59
+ html_safe_if_needed("<script type=\"text/javascript\" charset=\"utf-8\">NREUMQ.push([\"nrf2\",\"#{beacon}\",\"#{license_key}\",#{application_id},\"#{obfuscated_transaction_name}\",#{browser_monitoring_queue_time},#{browser_monitoring_app_time}])</script>")
60
60
  end
61
61
 
62
62
  def html_safe_if_needed(string)
@@ -66,7 +66,7 @@ module NewRelic
66
66
  string
67
67
  end
68
68
  end
69
-
69
+
70
70
  def obfuscate(text)
71
71
  obfuscated = ""
72
72
  key_bytes = NewRelic::Agent.instance.beacon_configuration.license_bytes
@@ -76,7 +76,7 @@ module NewRelic
76
76
  index+=1
77
77
  }
78
78
 
79
- [obfuscated].pack("m0").gsub("\n", '')
79
+ [obfuscated].pack("m0").chomp
80
80
  end
81
81
  end
82
82
  end
@@ -143,16 +143,16 @@ module NewRelic
143
143
  }
144
144
  end
145
145
 
146
- def over_queue_limit?(exception)
146
+ def over_queue_limit?(message)
147
147
  over_limit = (@errors.length >= MAX_ERROR_QUEUE_LENGTH)
148
- log.warn("The error reporting queue has reached #{MAX_ERROR_QUEUE_LENGTH}. The error detail for this and subsequent errors will not be transmitted to RPM until the queued errors have been sent: #{exception}") if over_limit
148
+ log.warn("The error reporting queue has reached #{MAX_ERROR_QUEUE_LENGTH}. The error detail for this and subsequent errors will not be transmitted to RPM until the queued errors have been sent: #{message}") if over_limit
149
149
  over_limit
150
150
  end
151
151
 
152
152
 
153
- def add_to_error_queue(noticed_error, exception)
153
+ def add_to_error_queue(noticed_error)
154
154
  @lock.synchronize do
155
- @errors << noticed_error unless over_queue_limit?(exception)
155
+ @errors << noticed_error unless over_queue_limit?(noticed_error.message)
156
156
  end
157
157
  end
158
158
  end
@@ -173,7 +173,7 @@ module NewRelic
173
173
  return if should_exit_notice_error?(exception)
174
174
  action_path = fetch_from_options(options, :metric, (NewRelic::Agent.instance.stats_engine.scope_name || ''))
175
175
  exception_options = error_params_from_options(options).merge(exception_info(exception))
176
- add_to_error_queue(NewRelic::NoticedError.new(action_path, exception_options, exception), exception)
176
+ add_to_error_queue(NewRelic::NoticedError.new(action_path, exception_options, exception))
177
177
  exception
178
178
  rescue Exception => e
179
179
  log.error("Error capturing an error, yodawg. #{e}")
@@ -181,16 +181,16 @@ module NewRelic
181
181
 
182
182
  # Get the errors currently queued up. Unsent errors are left
183
183
  # over from a previous unsuccessful attempt to send them to the server.
184
- # We first clear out all unsent errors before sending the newly queued errors.
185
184
  def harvest_errors(unsent_errors)
186
- if unsent_errors && !unsent_errors.empty?
187
- return unsent_errors
188
- else
189
- @lock.synchronize do
190
- errors = @errors
191
- @errors = []
192
- return errors
185
+ @lock.synchronize do
186
+ errors = @errors
187
+ @errors = []
188
+
189
+ if unsent_errors && !unsent_errors.empty?
190
+ errors = unsent_errors + errors
193
191
  end
192
+
193
+ errors
194
194
  end
195
195
  end
196
196
 
@@ -0,0 +1,9 @@
1
+ require 'new_relic/agent'
2
+ # stub module that contains instrumentation defined in the
3
+ # instrumentation directory
4
+ module NewRelic
5
+ module Agent
6
+ module Instrumentation
7
+ end
8
+ end
9
+ end
@@ -234,7 +234,7 @@ module NewRelic
234
234
 
235
235
  # Skip instrumentation based on the value of 'do_not_trace' and if
236
236
  # we aren't calling directly with a block.
237
- if !block_given? && _is_filtered?('do_not_trace')
237
+ if !block_given? && do_not_trace?
238
238
  # Also ignore all instrumentation in the call sequence
239
239
  NewRelic::Agent.disable_all_tracing do
240
240
  return perform_action_without_newrelic_trace(*args)
@@ -263,7 +263,7 @@ module NewRelic
263
263
  NewRelic::Agent::BusyCalculator.dispatcher_finish
264
264
  # Look for a metric frame in the thread local and process it.
265
265
  # Clear the thread local when finished to ensure it only gets called once.
266
- frame_data.record_apdex unless _is_filtered?('ignore_apdex')
266
+ frame_data.record_apdex unless ignore_apdex?
267
267
 
268
268
  frame_data.pop
269
269
  end
@@ -277,6 +277,14 @@ module NewRelic
277
277
  self.respond_to?(:request) && self.request.respond_to?(:headers) && self.request.headers
278
278
  end
279
279
 
280
+ def do_not_trace?
281
+ _is_filtered?('do_not_trace')
282
+ end
283
+
284
+ def ignore_apdex?
285
+ _is_filtered?('ignore_apdex')
286
+ end
287
+
280
288
  private
281
289
 
282
290
  # Profile the instrumented call. Dev mode only. Experimental.