newrelic_rpm 3.9.6.257 → 3.9.7.266

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. data.tar.gz.sig +0 -0
  2. data/CHANGELOG +45 -0
  3. data/lib/new_relic/agent.rb +0 -1
  4. data/lib/new_relic/agent/agent.rb +61 -22
  5. data/lib/new_relic/agent/agent_logger.rb +11 -9
  6. data/lib/new_relic/agent/configuration/default_source.rb +25 -2
  7. data/lib/new_relic/agent/cross_app_monitor.rb +15 -53
  8. data/lib/new_relic/agent/cross_app_tracing.rb +11 -3
  9. data/lib/new_relic/agent/custom_event_aggregator.rb +98 -0
  10. data/lib/new_relic/agent/event_buffer.rb +84 -0
  11. data/lib/new_relic/agent/harvester.rb +4 -15
  12. data/lib/new_relic/agent/hostname.rb +1 -9
  13. data/lib/new_relic/agent/inbound_request_monitor.rb +41 -0
  14. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +2 -2
  15. data/lib/new_relic/agent/instrumentation/queue_time.rb +0 -5
  16. data/lib/new_relic/agent/instrumentation/resque.rb +4 -9
  17. data/lib/new_relic/agent/javascript_instrumentor.rb +0 -12
  18. data/lib/new_relic/agent/method_tracer_helpers.rb +3 -1
  19. data/lib/new_relic/agent/new_relic_service.rb +1 -1
  20. data/lib/new_relic/agent/sampled_buffer.rb +13 -41
  21. data/lib/new_relic/agent/samplers/delayed_job_sampler.rb +52 -24
  22. data/lib/new_relic/agent/sized_buffer.rb +23 -0
  23. data/lib/new_relic/agent/synthetics_monitor.rb +50 -0
  24. data/lib/new_relic/agent/system_info.rb +28 -0
  25. data/lib/new_relic/agent/transaction.rb +78 -9
  26. data/lib/new_relic/agent/transaction/synthetics_sample_buffer.rb +25 -0
  27. data/lib/new_relic/agent/{request_sampler.rb → transaction_event_aggregator.rb} +53 -19
  28. data/lib/new_relic/agent/transaction_sample_builder.rb +3 -1
  29. data/lib/new_relic/agent/transaction_sampler.rb +10 -0
  30. data/lib/new_relic/agent/transaction_state.rb +1 -9
  31. data/lib/new_relic/coerce.rb +8 -2
  32. data/lib/new_relic/control.rb +0 -1
  33. data/lib/new_relic/local_environment.rb +12 -8
  34. data/lib/new_relic/metric_spec.rb +11 -2
  35. data/lib/new_relic/rack/developer_mode.rb +9 -1
  36. data/lib/new_relic/transaction_sample.rb +4 -10
  37. data/lib/new_relic/version.rb +1 -1
  38. data/newrelic_rpm.gemspec +1 -0
  39. data/test/agent_helper.rb +15 -2
  40. data/test/environments/norails/Gemfile +1 -0
  41. data/test/environments/rails21/Gemfile +1 -0
  42. data/test/environments/rails22/Gemfile +1 -0
  43. data/test/environments/rails23/Gemfile +1 -0
  44. data/test/environments/rails30/Gemfile +1 -0
  45. data/test/environments/rails31/Gemfile +1 -0
  46. data/test/environments/rails32/Gemfile +2 -1
  47. data/test/environments/rails40/Gemfile +2 -1
  48. data/test/environments/rails41/Gemfile +3 -1
  49. data/test/environments/rails42/Gemfile +3 -1
  50. data/test/fixtures/cross_agent_tests/README.md +6 -2
  51. data/test/fixtures/cross_agent_tests/docker_container_id/README.md +6 -0
  52. data/test/fixtures/cross_agent_tests/docker_container_id/cases.json +22 -0
  53. data/test/fixtures/cross_agent_tests/docker_container_id/docker-0.9.1.txt +10 -0
  54. data/test/fixtures/cross_agent_tests/docker_container_id/docker-1.0.0.txt +10 -0
  55. data/test/fixtures/cross_agent_tests/docker_container_id/docker-1.3.txt +9 -0
  56. data/test/fixtures/cross_agent_tests/docker_container_id/empty.txt +0 -0
  57. data/test/fixtures/cross_agent_tests/docker_container_id/lxc-containers-without-docker.txt +10 -0
  58. data/test/fixtures/cross_agent_tests/proc_meminfo/README.md +7 -0
  59. data/test/fixtures/cross_agent_tests/proc_meminfo/meminfo_4096MB.txt +47 -0
  60. data/test/fixtures/cross_agent_tests/rum_client_config.json +0 -80
  61. data/test/fixtures/cross_agent_tests/synthetics/synthetics.json +317 -0
  62. data/test/multiverse/lib/multiverse/runner.rb +1 -1
  63. data/test/multiverse/lib/multiverse/suite.rb +1 -0
  64. data/test/multiverse/suites/active_record/Envfile +42 -8
  65. data/test/multiverse/suites/active_record/ar_method_aliasing.rb +8 -4
  66. data/test/multiverse/suites/agent_only/audit_log_test.rb +0 -2
  67. data/test/multiverse/suites/agent_only/collector_exception_handling_test.rb +1 -2
  68. data/test/multiverse/suites/agent_only/cross_application_tracing_test.rb +5 -5
  69. data/test/multiverse/suites/agent_only/encoding_handling_test.rb +2 -0
  70. data/test/multiverse/suites/agent_only/harvest_timestamps_test.rb +8 -0
  71. data/test/multiverse/suites/agent_only/synthetics_test.rb +139 -0
  72. data/test/multiverse/suites/delayed_job/Envfile +79 -0
  73. data/test/multiverse/suites/delayed_job/before_suite.rb +33 -0
  74. data/test/multiverse/suites/delayed_job/config/newrelic.yml +18 -0
  75. data/test/multiverse/suites/delayed_job/delayed_job_sampler_test.rb +131 -0
  76. data/test/multiverse/suites/delayed_job/unsupported_backend_test.rb +24 -0
  77. data/test/multiverse/suites/high_security/high_security_test.rb +3 -10
  78. data/test/multiverse/suites/rails/Envfile +4 -4
  79. data/test/multiverse/suites/rails/request_statistics_test.rb +4 -4
  80. data/test/new_relic/agent/agent_test.rb +32 -4
  81. data/test/new_relic/agent/configuration/default_source_test.rb +6 -0
  82. data/test/new_relic/agent/cross_app_monitor_test.rb +23 -29
  83. data/test/new_relic/agent/custom_event_aggregator_test.rb +88 -0
  84. data/test/new_relic/agent/event_buffer_test_cases.rb +152 -0
  85. data/test/new_relic/agent/harvester_test.rb +5 -25
  86. data/test/new_relic/agent/hostname_test.rb +1 -1
  87. data/test/new_relic/agent/inbound_request_monitor_test.rb +49 -0
  88. data/test/new_relic/agent/instrumentation/controller_instrumentation_test.rb +9 -9
  89. data/test/new_relic/agent/instrumentation/queue_time_test.rb +0 -19
  90. data/test/new_relic/agent/javascript_instrumentor_test.rb +0 -45
  91. data/test/new_relic/agent/new_relic_service_test.rb +17 -12
  92. data/test/new_relic/agent/pipe_channel_manager_test.rb +4 -4
  93. data/test/new_relic/agent/sampled_buffer_test.rb +73 -145
  94. data/test/new_relic/agent/sized_buffer_test.rb +29 -0
  95. data/test/new_relic/agent/synthetics_monitor_test.rb +96 -0
  96. data/test/new_relic/agent/system_info_test.rb +19 -3
  97. data/test/new_relic/agent/transaction/developer_mode_sample_buffer_test.rb +14 -8
  98. data/test/new_relic/agent/transaction/synthetics_sample_buffer_test.rb +38 -0
  99. data/test/new_relic/agent/{request_sampler_test.rb → transaction_event_aggregator_test.rb} +55 -4
  100. data/test/new_relic/agent/transaction_sampler_test.rb +33 -11
  101. data/test/new_relic/agent/transaction_state_test.rb +0 -1
  102. data/test/new_relic/agent/transaction_test.rb +121 -19
  103. data/test/new_relic/coerce_test.rb +38 -3
  104. data/test/new_relic/control_test.rb +1 -0
  105. data/test/new_relic/fake_collector.rb +6 -2
  106. data/test/new_relic/fake_external_server.rb +2 -6
  107. data/test/new_relic/fake_server.rb +46 -29
  108. data/test/new_relic/http_client_test_cases.rb +71 -2
  109. data/test/new_relic/local_environment_test.rb +78 -0
  110. data/test/new_relic/metric_parser/metric_parser_test.rb +2 -0
  111. data/test/new_relic/metric_spec_test.rb +43 -0
  112. data/test/new_relic/multiverse_helpers.rb +11 -18
  113. data/test/new_relic/rack/browser_monitoring_test.rb +1 -18
  114. data/test/new_relic/rack/developer_mode_test.rb +1 -1
  115. data/test/new_relic/transaction_sample_test.rb +14 -4
  116. data/test/performance/suites/rack_middleware.rb +3 -1
  117. data/test/test_helper.rb +33 -0
  118. metadata +48 -7
  119. metadata.gz.sig +0 -0
  120. data/lib/new_relic/agent/browser_token.rb +0 -41
  121. data/test/multiverse/suites/agent_only/before_suite.rb +0 -7
  122. data/test/new_relic/agent/browser_token_test.rb +0 -56
data.tar.gz.sig CHANGED
Binary file
data/CHANGELOG CHANGED
@@ -1,5 +1,50 @@
1
1
  # New Relic Ruby Agent Release Notes #
2
2
 
3
+ ## v3.9.7 ##
4
+
5
+ * Support for New Relic Synthetics
6
+
7
+ The Ruby agent now gives you additional information for requests from New
8
+ Relic Synthetics. More transaction traces and events give you a clearer look
9
+ into how your applicaiton is performing around the world.
10
+
11
+ For more details, see https://docs.newrelic.com/docs/synthetics/new-relic-synthetics/getting-started/new-relic-synthetics
12
+
13
+ * Support for multiple job per fork gems with Resque
14
+
15
+ The resque-jobs-per-fork and resque-multi-job-forks gems alter Resque to
16
+ fork every N jobs instead of every job. This previously caused issues for
17
+ the Ruby agent, but those have been resolved. These gems are fully supported.
18
+
19
+ Running Resque with the FORK_PER_JOB=false environment variable setting is
20
+ also supported now.
21
+
22
+ For more details on our Resque support, see https://docs.newrelic.com/docs/agents/ruby-agent/background-jobs/resque-instrumentation
23
+
24
+ * Support agent when starting Resque Pool from Rake task
25
+
26
+ When running resque-pool with its provided rake tasks, the agent would not
27
+ start up properly. Thanks Tiago Sousa for the fix!
28
+
29
+ * Fix for DelayedJob + Rails 4.x queue depth metrics
30
+
31
+ The Ruby agent periodically records DelayedJob queuedepth as a metric, but
32
+ this didn't work properly in Rails 4.x applications. This has been fixed.
33
+ Thanks Jonathan del Strother for his help with the issue!
34
+
35
+ * Fix for failure in background transactions with rules.ignore_url_regexes
36
+
37
+ The recently added feature for ignoring transactions via URL regexes caused
38
+ errors for non-web transactions. This has been fixed.
39
+
40
+ * Rename the TransactionNamer.name method to TransactionNamer.name_for
41
+
42
+ The internal TransactionNamer class had a class method called 'name', with a
43
+ different signature than the existing Class#name method and could cause
44
+ problems when trying to introspect instances of the class.
45
+
46
+ Thanks to Dennis Taylor for contributing this fix!
47
+
3
48
  ## v3.9.6 ##
4
49
 
5
50
  * Rails 4.2 ActiveJob support
@@ -76,7 +76,6 @@ module NewRelic
76
76
  require 'new_relic/metric_spec'
77
77
  require 'new_relic/metric_data'
78
78
  require 'new_relic/collection_helper'
79
- require 'new_relic/transaction_analysis'
80
79
  require 'new_relic/transaction_sample'
81
80
  require 'new_relic/url_rule'
82
81
  require 'new_relic/noticed_error'
@@ -19,7 +19,9 @@ require 'new_relic/agent/database'
19
19
  require 'new_relic/agent/commands/agent_command_router'
20
20
  require 'new_relic/agent/event_listener'
21
21
  require 'new_relic/agent/cross_app_monitor'
22
- require 'new_relic/agent/request_sampler'
22
+ require 'new_relic/agent/synthetics_monitor'
23
+ require 'new_relic/agent/transaction_event_aggregator'
24
+ require 'new_relic/agent/custom_event_aggregator'
23
25
  require 'new_relic/agent/sampler_collection'
24
26
  require 'new_relic/agent/javascript_instrumentor'
25
27
  require 'new_relic/agent/vm/monotonic_gc_profiler'
@@ -48,14 +50,19 @@ module NewRelic
48
50
  @sql_sampler = NewRelic::Agent::SqlSampler.new
49
51
  @agent_command_router = NewRelic::Agent::Commands::AgentCommandRouter.new(@events)
50
52
  @cross_app_monitor = NewRelic::Agent::CrossAppMonitor.new(@events)
53
+ @synthetics_monitor = NewRelic::Agent::SyntheticsMonitor.new(@events)
51
54
  @error_collector = NewRelic::Agent::ErrorCollector.new
52
55
  @transaction_rules = NewRelic::Agent::RulesEngine.new
53
- @request_sampler = NewRelic::Agent::RequestSampler.new(@events)
54
56
  @harvest_samplers = NewRelic::Agent::SamplerCollection.new(@events)
55
57
  @javascript_instrumentor = NewRelic::Agent::JavascriptInstrumentor.new(@events)
56
- @harvester = NewRelic::Agent::Harvester.new(@events)
57
58
  @monotonic_gc_profiler = NewRelic::Agent::VM::MonotonicGCProfiler.new
58
59
 
60
+ @harvester = NewRelic::Agent::Harvester.new(@events)
61
+ @after_fork_lock = Mutex.new
62
+
63
+ @transaction_event_aggregator = NewRelic::Agent::TransactionEventAggregator.new(@events)
64
+ @custom_event_aggregator = NewRelic::Agent::CustomEventAggregator.new
65
+
59
66
  @connect_state = :pending
60
67
  @connect_attempts = 0
61
68
  @environment_report = nil
@@ -112,6 +119,7 @@ module NewRelic
112
119
  attr_reader :harvest_lock
113
120
  # GC::Profiler.total_time is not monotonic so we wrap it.
114
121
  attr_reader :monotonic_gc_profiler
122
+ attr_reader :custom_event_aggregator
115
123
 
116
124
  # This method should be called in a forked process after a fork.
117
125
  # It assumes the parent process initialized the agent, but does
@@ -133,28 +141,22 @@ module NewRelic
133
141
  # connection, this tells me to only try it once so this method returns
134
142
  # quickly if there is some kind of latency with the server.
135
143
  def after_fork(options={})
136
- # Mark started early because if we've explicitly called after_fork,
137
- # we should be ready to run and shouldn't restarting if we can't.
138
- @harvester.mark_started
139
-
140
- if channel_id = options[:report_to_channel]
141
- @service = NewRelic::Agent::PipeService.new(channel_id)
142
- if connected?
143
- @connected_pid = Process.pid
144
- else
145
- ::NewRelic::Agent.logger.debug("Child process #{Process.pid} not reporting to non-connected parent (process #{Process.ppid}).")
146
- @service.shutdown(Time.now)
147
- disconnect
148
- end
144
+ needs_restart = false
145
+ @after_fork_lock.synchronize do
146
+ needs_restart = @harvester.needs_restart?
147
+ @harvester.mark_started
149
148
  end
150
149
 
151
- return if !Agent.config[:agent_enabled] ||
150
+ return if !needs_restart ||
151
+ !Agent.config[:agent_enabled] ||
152
152
  !Agent.config[:monitor_mode] ||
153
- disconnected? ||
154
- @worker_thread && @worker_thread.alive?
153
+ disconnected?
155
154
 
156
155
  ::NewRelic::Agent.logger.debug "Starting the worker thread in #{Process.pid} (parent #{Process.ppid}) after forking."
157
156
 
157
+ channel_id = options[:report_to_channel]
158
+ install_pipe_service(channel_id) if channel_id
159
+
158
160
  # Clear out locks and stats left over from parent process
159
161
  reset_objects_with_locks
160
162
  drop_buffered_data
@@ -162,6 +164,17 @@ module NewRelic
162
164
  setup_and_start_agent(options)
163
165
  end
164
166
 
167
+ def install_pipe_service(channel_id)
168
+ @service = NewRelic::Agent::PipeService.new(channel_id)
169
+ if connected?
170
+ @connected_pid = Process.pid
171
+ else
172
+ ::NewRelic::Agent.logger.debug("Child process #{Process.pid} not reporting to non-connected parent (process #{Process.ppid}).")
173
+ @service.shutdown(Time.now)
174
+ disconnect
175
+ end
176
+ end
177
+
165
178
  # True if we have initialized and completed 'start'
166
179
  def started?
167
180
  @started
@@ -514,7 +527,8 @@ module NewRelic
514
527
  @stats_engine.reset!
515
528
  @error_collector.reset!
516
529
  @transaction_sampler.reset!
517
- @request_sampler.reset!
530
+ @transaction_event_aggregator.reset!
531
+ @custom_event_aggregator.reset!
518
532
  @sql_sampler.reset!
519
533
  end
520
534
 
@@ -531,6 +545,13 @@ module NewRelic
531
545
  reset_harvest_locks
532
546
  end
533
547
 
548
+ def flush_pipe_data
549
+ if connected? && @service.is_a?(::NewRelic::Agent::PipeService)
550
+ transmit_data
551
+ transmit_event_data
552
+ end
553
+ end
554
+
534
555
  private
535
556
 
536
557
  # All of this module used to be contained in the
@@ -577,6 +598,8 @@ module NewRelic
577
598
  period
578
599
  end
579
600
 
601
+ LOG_ONCE_KEYS_RESET_PERIOD = 60.0
602
+
580
603
  def create_and_run_event_loop
581
604
  @event_loop = create_event_loop
582
605
  @event_loop.on(:report_data) do
@@ -585,8 +608,12 @@ module NewRelic
585
608
  @event_loop.on(:report_event_data) do
586
609
  transmit_event_data
587
610
  end
611
+ @event_loop.on(:reset_log_once_keys) do
612
+ ::NewRelic::Agent.logger.clear_already_logged
613
+ end
588
614
  @event_loop.fire_every(Agent.config[:data_report_period], :report_data)
589
615
  @event_loop.fire_every(report_period_for(:analytic_event_data), :report_event_data)
616
+ @event_loop.fire_every(LOG_ONCE_KEYS_RESET_PERIOD, :reset_log_once_keys)
590
617
  @event_loop.run
591
618
  end
592
619
 
@@ -854,7 +881,7 @@ module NewRelic
854
881
  when :metric_data then @stats_engine
855
882
  when :transaction_sample_data then @transaction_sampler
856
883
  when :error_data then @error_collector
857
- when :analytic_event_data then @request_sampler
884
+ when :analytic_event_data then @transaction_event_aggregator
858
885
  when :sql_trace_data then @sql_sampler
859
886
  end
860
887
  end
@@ -978,6 +1005,9 @@ module NewRelic
978
1005
  NewRelic::Agent.logger.warn("Failed to serialize data for #{endpoint}, discarding. Error: ", e)
979
1006
  rescue UnrecoverableServerException => e
980
1007
  NewRelic::Agent.logger.warn("#{endpoint} data was rejected by remote service, discarding. Error: ", e)
1008
+ rescue ServerConnectionException => e
1009
+ log_remote_unavailable(endpoint, e)
1010
+ container.merge!(items)
981
1011
  rescue => e
982
1012
  NewRelic::Agent.logger.info("Unable to send #{endpoint} data, will try again later. Error: ", e)
983
1013
  container.merge!(items)
@@ -1012,7 +1042,8 @@ module NewRelic
1012
1042
  end
1013
1043
 
1014
1044
  def harvest_and_send_analytic_event_data
1015
- harvest_and_send_from_container(@request_sampler, :analytic_event_data)
1045
+ harvest_and_send_from_container(@transaction_event_aggregator, :analytic_event_data)
1046
+ harvest_and_send_from_container(@custom_event_aggregator, :analytic_event_data)
1016
1047
  end
1017
1048
 
1018
1049
  def check_for_and_handle_agent_commands
@@ -1020,11 +1051,19 @@ module NewRelic
1020
1051
  @agent_command_router.check_for_and_handle_agent_commands
1021
1052
  rescue ForceRestartException, ForceDisconnectException
1022
1053
  raise
1054
+ rescue ServerConnectionException => e
1055
+ log_remote_unavailable(:get_agent_commands, e)
1023
1056
  rescue => e
1024
1057
  NewRelic::Agent.logger.info("Error during check_for_and_handle_agent_commands, will retry later: ", e)
1025
1058
  end
1026
1059
  end
1027
1060
 
1061
+ def log_remote_unavailable(endpoint, e)
1062
+ NewRelic::Agent.logger.debug("Unable to send #{endpoint} data, will try again later. Error: ", e)
1063
+ NewRelic::Agent.record_metric("Supportability/remote_unavailable", 0.0)
1064
+ NewRelic::Agent.record_metric("Supportability/remote_unavailable/#{endpoint.to_s}", 0.0)
1065
+ end
1066
+
1028
1067
  def transmit_data
1029
1068
  harvest_lock.synchronize do
1030
1069
  transmit_data_already_locked
@@ -9,7 +9,10 @@ module NewRelic
9
9
  module Agent
10
10
  class AgentLogger
11
11
 
12
+ attr_reader :already_logged
13
+
12
14
  def initialize(root = "", override_logger=nil)
15
+ clear_already_logged
13
16
  create_log(root, override_logger)
14
17
  set_log_level!
15
18
  set_log_format!
@@ -40,10 +43,14 @@ module NewRelic
40
43
  NUM_LOG_ONCE_KEYS = 1000
41
44
 
42
45
  def log_once(level, key, *msgs)
43
- return if already_logged.include?(key)
46
+ # Since `already_logged` might change between calls, just grab it once
47
+ # and use it throughout this method.
48
+ logged = already_logged
49
+
50
+ return if logged.include?(key)
44
51
 
45
- if already_logged.size >= NUM_LOG_ONCE_KEYS && key.kind_of?(String)
46
- # The reason for preventing too many keys in `already_logged` is for
52
+ if logged.size >= NUM_LOG_ONCE_KEYS && key.kind_of?(String)
53
+ # The reason for preventing too many keys in `logged` is for
47
54
  # memory concerns.
48
55
  # The reason for checking the type of the key is that we always want
49
56
  # to allow symbols to log, since there are very few of them.
@@ -54,7 +61,7 @@ module NewRelic
54
61
  return
55
62
  end
56
63
 
57
- already_logged[key] = true
64
+ logged[key] = true
58
65
  self.send(level, *msgs)
59
66
  end
60
67
 
@@ -140,11 +147,6 @@ module NewRelic
140
147
  @log = ::NewRelic::Agent::NullLogger.new
141
148
  end
142
149
 
143
- def already_logged
144
- @already_logged ||= {}
145
- @already_logged
146
- end
147
-
148
150
  def clear_already_logged
149
151
  @already_logged = {}
150
152
  end
@@ -202,10 +202,13 @@ module NewRelic
202
202
  case value
203
203
  when String
204
204
  value.split(',')
205
- else
205
+ when Array
206
206
  value
207
+ else
208
+ raise ArgumentError.new("Config value '#{value}' couldn't be turned into a list.")
207
209
  end
208
210
  end
211
+
209
212
  end
210
213
 
211
214
  AUTOSTART_BLACKLISTED_RAKE_TASKS = [
@@ -1079,6 +1082,7 @@ module NewRelic
1079
1082
  :default => ['scheduler', 'run'],
1080
1083
  :public => true,
1081
1084
  :type => Array,
1085
+ :transform => DefaultSource.method(:convert_to_list),
1082
1086
  :description => 'List of prefixes for heroku dyno names (such as "scheduler") to report as hostname without trailing dot and process ID.'
1083
1087
  },
1084
1088
  :labels => {
@@ -1112,7 +1116,26 @@ module NewRelic
1112
1116
  :type => Array,
1113
1117
  :transform => DefaultSource.rules_ignore,
1114
1118
  :description => 'A list of patterns that will cause a transaction to be ignored if any of them match the URI.'
1115
- }
1119
+ },
1120
+ :'synthetics.traces_limit' => {
1121
+ :default => 20,
1122
+ :public => false,
1123
+ :type => Fixnum,
1124
+ :description => 'Maximum number of synthetics transaction traces to hold for a given harvest'
1125
+ },
1126
+ :'synthetics.events_limit' => {
1127
+ :default => 200,
1128
+ :public => false,
1129
+ :type => Fixnum,
1130
+ :description => 'Maximum number of synthetics transaction events to hold for a given harvest'
1131
+ },
1132
+ :'custom_insights_events.max_samples_stored' => {
1133
+ :default => 1000,
1134
+ :public => true,
1135
+ :type => Fixnum,
1136
+ :description => 'Maximum number of custom Insights events buffered in memory at a time.',
1137
+ :dynamic_name => true
1138
+ }
1116
1139
  }.freeze
1117
1140
 
1118
1141
  end
@@ -4,51 +4,33 @@
4
4
 
5
5
  require 'digest'
6
6
 
7
+ require 'new_relic/agent/inbound_request_monitor'
7
8
  require 'new_relic/agent/transaction_state'
8
9
  require 'new_relic/agent/threading/agent_thread'
9
10
 
10
11
  module NewRelic
11
12
  module Agent
13
+ class CrossAppMonitor < InboundRequestMonitor
12
14
 
13
- class CrossAppMonitor
14
-
15
- NEWRELIC_ID_HEADER = 'X-NewRelic-ID'
15
+ NEWRELIC_ID_HEADER = 'X-NewRelic-ID'
16
+ NEWRELIC_TXN_HEADER = 'X-NewRelic-Transaction'
16
17
  NEWRELIC_APPDATA_HEADER = 'X-NewRelic-App-Data'
17
- NEWRELIC_TXN_HEADER = 'X-NewRelic-Transaction'
18
- NEWRELIC_TXN_HEADER_KEYS = %W{
19
- #{NEWRELIC_TXN_HEADER} HTTP_X_NEWRELIC_TRANSACTION X_NEWRELIC_TRANSACTION
20
- }
21
- NEWRELIC_ID_HEADER_KEYS = %W{
22
- #{NEWRELIC_ID_HEADER} HTTP_X_NEWRELIC_ID X_NEWRELIC_ID
23
- }
24
- CONTENT_LENGTH_HEADER_KEYS = %w{Content-Length HTTP_CONTENT_LENGTH CONTENT_LENGTH}
25
-
26
- attr_reader :obfuscator
27
-
28
- def initialize(events = nil)
29
- # When we're starting up for real in the agent, we get passed the events
30
- # Other spots can pull from the agent, during startup the agent doesn't exist yet!
31
- events ||= Agent.instance.events
32
-
33
- events.subscribe(:finished_configuring) do
34
- on_finished_configuring
35
- end
36
- end
37
18
 
38
- def on_finished_configuring
39
- setup_obfuscator
40
- register_event_listeners
19
+ NEWRELIC_ID_HEADER_KEY = 'HTTP_X_NEWRELIC_ID'.freeze
20
+ NEWRELIC_TXN_HEADER_KEY = 'HTTP_X_NEWRELIC_TRANSACTION'.freeze
21
+ CONTENT_LENGTH_HEADER_KEY = 'HTTP_CONTENT_LENGTH'.freeze
22
+
23
+ def on_finished_configuring(events)
24
+ register_event_listeners(events)
41
25
  end
42
26
 
43
27
  # Expected sequence of events:
44
28
  # :before_call will save our cross application request id to the thread
45
- # :start_transaction will get called when a transaction starts up
46
29
  # :after_call will write our response headers/metrics and clean up the thread
47
- def register_event_listeners
30
+ def register_event_listeners(events)
48
31
  NewRelic::Agent.logger.
49
32
  debug("Wiring up Cross Application Tracing to events after finished configuring")
50
33
 
51
- events = Agent.instance.events
52
34
  events.subscribe(:before_call) do |env| #THREAD_LOCAL_ACCESS
53
35
  if should_process_request(env)
54
36
  state = NewRelic::Agent::TransactionState.tl_get
@@ -72,11 +54,6 @@ module NewRelic
72
54
  end
73
55
  end
74
56
 
75
- # This requires :encoding_key, so must wait until :finished_configuring
76
- def setup_obfuscator
77
- @obfuscator = NewRelic::Agent::Obfuscator.new(NewRelic::Agent.config[:encoding_key])
78
- end
79
-
80
57
  def save_client_cross_app_id(state, request_headers)
81
58
  state.client_cross_app_id = decoded_id(request_headers)
82
59
  end
@@ -86,9 +63,8 @@ module NewRelic
86
63
  end
87
64
 
88
65
  def save_referring_transaction_info(state, request_headers)
89
- txn_header = from_headers(request_headers, NEWRELIC_TXN_HEADER_KEYS) or return
90
- txn_header = obfuscator.deobfuscate(txn_header)
91
- txn_info = NewRelic::JSONWrapper.load(txn_header)
66
+ txn_header = request_headers[NEWRELIC_TXN_HEADER_KEY] or return
67
+ txn_info = deserialize_header(txn_header, NEWRELIC_TXN_HEADER)
92
68
  state.referring_transaction_info = txn_info
93
69
  end
94
70
 
@@ -182,14 +158,14 @@ module NewRelic
182
158
  end
183
159
 
184
160
  def decoded_id(request)
185
- encoded_id = from_headers(request, NEWRELIC_ID_HEADER_KEYS)
161
+ encoded_id = request[NEWRELIC_ID_HEADER_KEY]
186
162
  return "" if encoded_id.nil?
187
163
 
188
164
  obfuscator.deobfuscate(encoded_id)
189
165
  end
190
166
 
191
167
  def content_length_from_request(request)
192
- from_headers(request, CONTENT_LENGTH_HEADER_KEYS) || -1
168
+ request[CONTENT_LENGTH_HEADER_KEY] || -1
193
169
  end
194
170
 
195
171
  def hash_transaction_name(identifier)
@@ -202,20 +178,6 @@ module NewRelic
202
178
  identifier = "#{app_name};#{txn_name}"
203
179
  sprintf("%08x", rotated ^ hash_transaction_name(identifier))
204
180
  end
205
-
206
- private
207
-
208
- def from_headers(request, try_keys)
209
- # For lookups, upcase all our keys on both sides just to be safe
210
- upcased_keys = try_keys.map{|k| k.upcase}
211
- upcased_keys.each do |header|
212
- found_key = request.keys.find { |k| k.upcase == header }
213
- return request[found_key] unless found_key.nil?
214
- end
215
- nil
216
- end
217
-
218
181
  end
219
-
220
182
  end
221
183
  end