newrelic_rpm 9.6.0 → 9.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +33 -2
  3. data/CONTRIBUTING.md +0 -7
  4. data/bin/newrelic +2 -9
  5. data/bin/newrelic_rpm +15 -0
  6. data/init.rb +2 -2
  7. data/lib/new_relic/agent/agent.rb +1 -1
  8. data/lib/new_relic/agent/agent_helpers/shutdown.rb +1 -1
  9. data/lib/new_relic/agent/agent_helpers/special_startup.rb +1 -1
  10. data/lib/new_relic/agent/agent_helpers/start_worker_thread.rb +2 -2
  11. data/lib/new_relic/agent/agent_helpers/startup.rb +2 -2
  12. data/lib/new_relic/agent/attribute_filter.rb +3 -3
  13. data/lib/new_relic/agent/configuration/default_source.rb +14 -2
  14. data/lib/new_relic/agent/configuration/manager.rb +8 -7
  15. data/lib/new_relic/agent/datastores/mongo/metric_translator.rb +1 -1
  16. data/lib/new_relic/agent/distributed_tracing/distributed_trace_payload.rb +3 -3
  17. data/lib/new_relic/agent/event_loop.rb +1 -1
  18. data/lib/new_relic/agent/http_clients/abstract.rb +4 -0
  19. data/lib/new_relic/agent/http_clients/async_http_wrappers.rb +0 -3
  20. data/lib/new_relic/agent/http_clients/curb_wrappers.rb +1 -3
  21. data/lib/new_relic/agent/http_clients/ethon_wrappers.rb +0 -2
  22. data/lib/new_relic/agent/http_clients/excon_wrappers.rb +0 -3
  23. data/lib/new_relic/agent/http_clients/http_rb_wrappers.rb +1 -3
  24. data/lib/new_relic/agent/http_clients/httpclient_wrappers.rb +0 -3
  25. data/lib/new_relic/agent/http_clients/httpx_wrappers.rb +0 -2
  26. data/lib/new_relic/agent/http_clients/net_http_wrappers.rb +1 -4
  27. data/lib/new_relic/agent/http_clients/typhoeus_wrappers.rb +0 -3
  28. data/lib/new_relic/agent/instrumentation/active_merchant.rb +1 -1
  29. data/lib/new_relic/agent/instrumentation/elasticsearch/instrumentation.rb +1 -1
  30. data/lib/new_relic/agent/instrumentation/fiber/instrumentation.rb +1 -4
  31. data/lib/new_relic/agent/instrumentation/sinatra/ignorer.rb +1 -1
  32. data/lib/new_relic/agent/instrumentation/sinatra.rb +1 -1
  33. data/lib/new_relic/agent/instrumentation/thread/instrumentation.rb +1 -4
  34. data/lib/new_relic/agent/instrumentation/view_component/chain.rb +21 -0
  35. data/lib/new_relic/agent/instrumentation/view_component/instrumentation.rb +38 -0
  36. data/lib/new_relic/agent/instrumentation/view_component/prepend.rb +13 -0
  37. data/lib/new_relic/agent/instrumentation/view_component.rb +26 -0
  38. data/lib/new_relic/agent/javascript_instrumentor.rb +0 -1
  39. data/lib/new_relic/agent/new_relic_service/encoders.rb +2 -2
  40. data/lib/new_relic/agent/new_relic_service.rb +8 -6
  41. data/lib/new_relic/agent/obfuscator.rb +0 -2
  42. data/lib/new_relic/agent/pipe_channel_manager.rb +2 -2
  43. data/lib/new_relic/agent/rules_engine/segment_terms_rule.rb +1 -2
  44. data/lib/new_relic/agent/sql_sampler.rb +0 -1
  45. data/lib/new_relic/agent/tracer.rb +4 -3
  46. data/lib/new_relic/agent/transaction/tracing.rb +11 -1
  47. data/lib/new_relic/agent/vm/{mri_vm.rb → c_ruby_vm.rb} +7 -15
  48. data/lib/new_relic/agent/vm.rb +2 -2
  49. data/lib/new_relic/agent/worker_loop.rb +1 -1
  50. data/lib/new_relic/agent.rb +5 -5
  51. data/lib/new_relic/base64.rb +25 -0
  52. data/lib/new_relic/cli/command.rb +6 -4
  53. data/lib/new_relic/constants.rb +2 -0
  54. data/lib/new_relic/control/frameworks/rails.rb +3 -3
  55. data/lib/new_relic/control/instrumentation.rb +1 -1
  56. data/lib/new_relic/local_environment.rb +22 -13
  57. data/lib/new_relic/supportability_helper.rb +1 -1
  58. data/lib/new_relic/version.rb +1 -1
  59. data/lib/tasks/config.rake +1 -1
  60. data/lib/tasks/helpers/config.html.erb +6 -6
  61. data/lib/tasks/helpers/newrelicyml.rb +1 -1
  62. data/newrelic.yml +6 -2
  63. data/newrelic_rpm.gemspec +3 -5
  64. data/test/agent_helper.rb +14 -2
  65. metadata +12 -21
  66. data/bin/newrelic_cmd +0 -7
@@ -0,0 +1,26 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ require_relative 'view_component/instrumentation'
6
+ require_relative 'view_component/chain'
7
+ require_relative 'view_component/prepend'
8
+
9
+ DependencyDetection.defer do
10
+ named :view_component
11
+
12
+ depends_on do
13
+ defined?(ViewComponent) &&
14
+ ViewComponent::Base.method_defined?(:render_in)
15
+ end
16
+
17
+ executes do
18
+ NewRelic::Agent.logger.info('Installing ViewComponent instrumentation')
19
+
20
+ if use_prepend?
21
+ prepend_instrument ViewComponent::Base, NewRelic::Agent::Instrumentation::ViewComponent::Prepend
22
+ else
23
+ chain_instrument NewRelic::Agent::Instrumentation::ViewComponent::Chain
24
+ end
25
+ end
26
+ end
@@ -2,7 +2,6 @@
2
2
  # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
3
  # frozen_string_literal: true
4
4
 
5
- require 'base64'
6
5
  require 'json'
7
6
  require 'new_relic/agent/obfuscator'
8
7
 
@@ -2,10 +2,10 @@
2
2
  # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
3
  # frozen_string_literal: true
4
4
 
5
- require 'base64'
6
5
  require 'json'
7
6
  require 'stringio'
8
7
  require 'zlib'
8
+ require 'new_relic/base64'
9
9
 
10
10
  module NewRelic
11
11
  module Agent
@@ -45,7 +45,7 @@ module NewRelic
45
45
  data = NewRelic::Agent::EncodingNormalizer.normalize_object(data)
46
46
  end
47
47
  json = ::JSON.dump(data)
48
- Base64.encode64(Compressed::Deflate.encode(json))
48
+ NewRelic::Base64.encode64(Compressed::Deflate.encode(json))
49
49
  end
50
50
  end
51
51
  end
@@ -414,7 +414,7 @@ module NewRelic
414
414
  else
415
415
  request = Net::HTTP::Post.new(opts[:uri], headers)
416
416
  end
417
- @audit_logger.log_request_headers(opts[:uri], headers)
417
+ @audit_logger.log_request_headers(filtered_uri(opts[:uri]), headers)
418
418
  request['user-agent'] = user_agent
419
419
  request.content_type = 'application/octet-stream'
420
420
  request.body = opts[:data]
@@ -431,7 +431,7 @@ module NewRelic
431
431
  rescue *CONNECTION_ERRORS => e
432
432
  close_shared_connection
433
433
  if attempts < MAX_ATTEMPTS
434
- ::NewRelic::Agent.logger.debug("Retrying request to #{opts[:collector]}#{opts[:uri]} after #{e}")
434
+ ::NewRelic::Agent.logger.debug("Retrying request to #{opts[:collector]}#{filtered_uri(opts[:uri])} after #{e}")
435
435
  retry
436
436
  else
437
437
  raise ServerConnectionException, "Recoverable error talking to #{@collector} after #{attempts} attempts: #{e}"
@@ -444,7 +444,7 @@ module NewRelic
444
444
 
445
445
  def attempt_request(request, opts)
446
446
  conn = http_connection
447
- ::NewRelic::Agent.logger.debug("Sending request to #{opts[:collector]}#{opts[:uri]} with #{request.method}")
447
+ ::NewRelic::Agent.logger.debug("Sending request to #{opts[:collector]}#{filtered_uri(opts[:uri])} with #{request.method}")
448
448
  conn.request(request)
449
449
  end
450
450
 
@@ -689,9 +689,7 @@ module NewRelic
689
689
 
690
690
  def invoke_remote_send_request(method, payload, data, encoding)
691
691
  uri = remote_method_uri(method)
692
- full_uri = "#{@collector}#{uri}"
693
-
694
- @audit_logger.log_request(full_uri, payload, @marshaller)
692
+ @audit_logger.log_request("#{@collector}#{filtered_uri(uri)}", payload, @marshaller)
695
693
  request_send_ts = Process.clock_gettime(Process::CLOCK_MONOTONIC)
696
694
  response = send_request(:data => data,
697
695
  :uri => uri,
@@ -700,6 +698,10 @@ module NewRelic
700
698
  :endpoint => method)
701
699
  [response, request_send_ts, Process.clock_gettime(Process::CLOCK_MONOTONIC)]
702
700
  end
701
+
702
+ def filtered_uri(uri)
703
+ uri.gsub(license_key, ASTERISK * license_key.size)
704
+ end
703
705
  end
704
706
  end
705
707
  end
@@ -2,8 +2,6 @@
2
2
  # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
3
  # frozen_string_literal: true
4
4
 
5
- # require 'base64'
6
-
7
5
  module NewRelic
8
6
  module Agent
9
7
  class Obfuscator
@@ -2,7 +2,7 @@
2
2
  # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
3
  # frozen_string_literal: true
4
4
 
5
- require 'base64'
5
+ require 'new_relic/base64'
6
6
 
7
7
  module NewRelic
8
8
  module Agent
@@ -257,7 +257,7 @@ module NewRelic
257
257
  Marshal.load(data)
258
258
  rescue StandardError => e
259
259
  ::NewRelic::Agent.logger.error('Failure unmarshalling message from Resque child process', e)
260
- ::NewRelic::Agent.logger.debug(Base64.encode64(data))
260
+ ::NewRelic::Agent.logger.debug(NewRelic::Base64.encode64(data))
261
261
  nil
262
262
  end
263
263
 
@@ -8,7 +8,6 @@ module NewRelic
8
8
  class SegmentTermsRule
9
9
  PREFIX_KEY = 'prefix'.freeze
10
10
  TERMS_KEY = 'terms'.freeze
11
- SEGMENT_PLACEHOLDER = '*'.freeze
12
11
  ADJACENT_PLACEHOLDERS_REGEX = %r{((?:^|/)\*)(?:/\*)*}.freeze
13
12
  ADJACENT_PLACEHOLDERS_REPLACEMENT = '\1'.freeze
14
13
 
@@ -52,7 +51,7 @@ module NewRelic
52
51
  rest = string[@trim_range]
53
52
  leading_slash = rest.slice!(LEADING_SLASH_REGEX)
54
53
  segments = rest.split(SEGMENT_SEPARATOR, -1)
55
- segments.map! { |s| @terms.include?(s) ? s : SEGMENT_PLACEHOLDER }
54
+ segments.map! { |s| @terms.include?(s) ? s : ASTERISK }
56
55
  transformed_suffix = collapse_adjacent_placeholder_segments(segments)
57
56
 
58
57
  "#{@prefix}#{leading_slash}#{transformed_suffix}"
@@ -3,7 +3,6 @@
3
3
  # frozen_string_literal: true
4
4
 
5
5
  require 'zlib'
6
- require 'base64'
7
6
  require 'digest/md5'
8
7
 
9
8
  module NewRelic
@@ -418,16 +418,17 @@ module NewRelic
418
418
  NewRelic::Agent.config[:'instrumentation.thread.tracing']
419
419
  end
420
420
 
421
- def thread_block_with_current_transaction(segment_name:, parent: nil, &block)
421
+ def thread_block_with_current_transaction(segment_name: nil, parent: nil, &block)
422
422
  parent ||= current_segment
423
423
  current_txn = ::Thread.current[:newrelic_tracer_state]&.current_transaction if ::Thread.current[:newrelic_tracer_state]&.is_execution_traced?
424
424
  proc do |*args|
425
425
  begin
426
426
  if current_txn && !current_txn.finished?
427
427
  NewRelic::Agent::Tracer.state.current_transaction = current_txn
428
+ ::Thread.current[:newrelic_thread_span_parent] = parent
428
429
  current_txn.async = true
429
- segment_name += "/Thread#{::Thread.current.object_id}/Fiber#{::Fiber.current.object_id}" if NewRelic::Agent.config[:'thread_ids_enabled']
430
- segment = NewRelic::Agent::Tracer.start_segment(name: segment_name, parent: parent)
430
+ segment_name = "#{segment_name}/Thread#{::Thread.current.object_id}/Fiber#{::Fiber.current.object_id}" if NewRelic::Agent.config[:'thread_ids_enabled']
431
+ segment = NewRelic::Agent::Tracer.start_segment(name: segment_name, parent: parent) if segment_name
431
432
  end
432
433
  NewRelic::Agent::Tracer.capture_segment_error(segment) do
433
434
  yield(*args)
@@ -22,7 +22,7 @@ module NewRelic
22
22
 
23
23
  def add_segment(segment, parent = nil)
24
24
  segment.transaction = self
25
- segment.parent = parent || current_segment
25
+ segment.parent = parent || thread_starting_span || current_segment
26
26
  set_current_segment(segment)
27
27
  if @segments.length < segment_limit
28
28
  @segments << segment
@@ -39,6 +39,16 @@ module NewRelic
39
39
  segment.transaction_assigned
40
40
  end
41
41
 
42
+ def thread_starting_span
43
+ # if the previous current segment was in another thread, use the thread local parent
44
+ if ::Thread.current[:newrelic_thread_span_parent] &&
45
+ current_segment &&
46
+ current_segment.starting_segment_key != NewRelic::Agent::Tracer.current_segment_key
47
+
48
+ ::Thread.current[:newrelic_thread_span_parent]
49
+ end
50
+ end
51
+
42
52
  def segment_complete(segment)
43
53
  # if parent was in another thread, remove the current_segment entry for this thread
44
54
  if segment.parent && segment.parent.starting_segment_key != NewRelic::Agent::Tracer.current_segment_key
@@ -8,7 +8,7 @@ require 'new_relic/agent/vm/snapshot'
8
8
  module NewRelic
9
9
  module Agent
10
10
  module VM
11
- class MriVM
11
+ class CRubyVM
12
12
  def snapshot
13
13
  snap = Snapshot.new
14
14
  gather_stats(snap)
@@ -24,7 +24,7 @@ module NewRelic
24
24
 
25
25
  def gather_gc_stats(snap)
26
26
  gather_gc_runs(snap) if supports?(:gc_runs)
27
- gather_derived_stats(snap) if GC.respond_to?(:stat)
27
+ gather_derived_stats(snap)
28
28
  end
29
29
 
30
30
  def gather_gc_runs(snap)
@@ -33,19 +33,11 @@ module NewRelic
33
33
 
34
34
  def gather_derived_stats(snap)
35
35
  stat = GC.stat
36
- snap.total_allocated_object = derive_from_gc_stats(%i[total_allocated_objects total_allocated_object], stat)
37
- snap.major_gc_count = derive_from_gc_stats(:major_gc_count, stat)
38
- snap.minor_gc_count = derive_from_gc_stats(:minor_gc_count, stat)
39
- snap.heap_live = derive_from_gc_stats(%i[heap_live_slots heap_live_slot heap_live_num], stat)
40
- snap.heap_free = derive_from_gc_stats(%i[heap_free_slots heap_free_slot heap_free_num], stat)
41
- end
42
-
43
- def derive_from_gc_stats(keys, stat)
44
- Array(keys).each do |key|
45
- value = stat[key]
46
- return value if value
47
- end
48
- nil
36
+ snap.total_allocated_object = stat.fetch(:total_allocated_objects, nil)
37
+ snap.major_gc_count = stat.fetch(:major_gc_count, nil)
38
+ snap.minor_gc_count = stat.fetch(:minor_gc_count, nil)
39
+ snap.heap_live = stat.fetch(:heap_live_slots, nil)
40
+ snap.heap_free = stat.fetch(:heap_free_slots, nil)
49
41
  end
50
42
 
51
43
  def gather_gc_time(snap)
@@ -3,7 +3,7 @@
3
3
  # frozen_string_literal: true
4
4
 
5
5
  require 'new_relic/language_support'
6
- require 'new_relic/agent/vm/mri_vm'
6
+ require 'new_relic/agent/vm/c_ruby_vm'
7
7
  require 'new_relic/agent/vm/jruby_vm'
8
8
 
9
9
  module NewRelic
@@ -21,7 +21,7 @@ module NewRelic
21
21
  if NewRelic::LanguageSupport.jruby?
22
22
  JRubyVM.new
23
23
  else
24
- MriVM.new
24
+ CRubyVM.new
25
25
  end
26
26
  end
27
27
  end
@@ -88,7 +88,7 @@ module NewRelic
88
88
  raise
89
89
  rescue => e
90
90
  # Don't blow out the stack for anything that hasn't already propagated
91
- ::NewRelic::Agent.logger.error('Error running task in Agent Worker Loop:', e)
91
+ ::NewRelic::Agent.logger.error('Error running task in agent worker loop:', e)
92
92
  end
93
93
  end
94
94
  end
@@ -252,7 +252,7 @@ module NewRelic
252
252
 
253
253
  # @!group Recording custom errors
254
254
 
255
- # Set a filter to be applied to errors that the Ruby Agent will
255
+ # Set a filter to be applied to errors that the Ruby agent will
256
256
  # track. The block should evaluate to the exception to track
257
257
  # (which could be different from the original exception) or nil to
258
258
  # ignore this exception.
@@ -391,13 +391,13 @@ module NewRelic
391
391
 
392
392
  # @!group Manual agent configuration and startup/shutdown
393
393
 
394
- # Call this to manually start the Agent in situations where the Agent does
394
+ # Call this to manually start the agent in situations where the agent does
395
395
  # not auto-start.
396
396
  #
397
- # When the app environment loads, so does the Agent. However, the
398
- # Agent will only connect to the service if a web front-end is found. If
397
+ # When the app environment loads, so does the agent. However, the
398
+ # agent will only connect to the service if a web front-end is found. If
399
399
  # you want to selectively monitor ruby processes that don't use
400
- # web plugins, then call this method in your code and the Agent
400
+ # web plugins, then call this method in your code and the agent
401
401
  # will fire up and start reporting to the service.
402
402
  #
403
403
  # Options are passed in as overrides for values in the
@@ -0,0 +1,25 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ module NewRelic
6
+ module Base64
7
+ extend self
8
+
9
+ def encode64(bin)
10
+ [bin].pack('m')
11
+ end
12
+
13
+ def decode64(str)
14
+ str.unpack1('m')
15
+ end
16
+
17
+ def strict_encode64(bin)
18
+ [bin].pack('m0')
19
+ end
20
+
21
+ def strict_decode64(str)
22
+ str.unpack1('m0')
23
+ end
24
+ end
25
+ end
@@ -60,11 +60,13 @@ module NewRelic
60
60
  extra = []
61
61
  options = ARGV.options do |opts|
62
62
  script_name = File.basename($0)
63
- # TODO: MAJOR VERSION - remove newrelic_cmd, deprecated since version 2.13
64
- if /newrelic_cmd$/.match?(script_name)
65
- $stdout.puts "warning: the 'newrelic_cmd' script has been renamed 'newrelic'"
66
- script_name = 'newrelic'
63
+
64
+ # TODO: MAJOR VERSION - remove newrelic, deprecated since version x.xx
65
+ if /newrelic$/.match?(script_name)
66
+ $stdout.puts "warning: the 'newrelic' script has been renamed 'newrelic_rpm'"
67
+ script_name = 'newrelic_rpm'
67
68
  end
69
+
68
70
  opts.banner = "Usage: #{script_name} [ #{@command_names.join(' | ')} ] [options]"
69
71
  opts.separator("use '#{script_name} <command> -h' to see detailed command options")
70
72
  opts
@@ -3,6 +3,8 @@
3
3
  # frozen_string_literal: true
4
4
 
5
5
  module NewRelic
6
+ ASTERISK = '*'
7
+
6
8
  PRIORITY_PRECISION = 6
7
9
 
8
10
  EMPTY_ARRAY = [].freeze
@@ -74,7 +74,7 @@ module NewRelic
74
74
  # Might not be running if it does not think mongrel, thin,
75
75
  # passenger, etc. is running, if it thinks it's a rake task, or
76
76
  # if the agent_enabled is false.
77
- ::NewRelic::Agent.logger.info('New Relic Agent not running. Skipping browser monitoring and agent hooks.')
77
+ ::NewRelic::Agent.logger.info('New Relic agent not running. Skipping browser monitoring and agent hooks.')
78
78
  else
79
79
  install_browser_monitoring(rails_config)
80
80
  install_agent_hooks(rails_config)
@@ -92,9 +92,9 @@ module NewRelic
92
92
  return unless NewRelic::Rack::AgentHooks.needed?
93
93
 
94
94
  config.middleware.use(NewRelic::Rack::AgentHooks)
95
- ::NewRelic::Agent.logger.debug('Installed New Relic Agent Hooks middleware')
95
+ ::NewRelic::Agent.logger.debug('Installed New Relic agent hooks middleware')
96
96
  rescue => e
97
- ::NewRelic::Agent.logger.warn('Error installing New Relic Agent Hooks middleware', e)
97
+ ::NewRelic::Agent.logger.warn('Error installing New Relic agent hooks middleware', e)
98
98
  end
99
99
  end
100
100
 
@@ -70,7 +70,7 @@ module NewRelic
70
70
  def rails_32_deprecation
71
71
  return unless defined?(Rails::VERSION) && Gem::Version.new(Rails::VERSION::STRING) <= Gem::Version.new('3.2')
72
72
 
73
- deprecation_msg = 'The Ruby Agent is dropping support for Rails 3.2 ' \
73
+ deprecation_msg = 'The Ruby agent is dropping support for Rails 3.2 ' \
74
74
  'in a future major release. Please upgrade your Rails version to continue receiving support. ' \
75
75
 
76
76
  Agent.logger.log_once(
@@ -74,6 +74,7 @@ module NewRelic
74
74
  unicorn
75
75
  webrick
76
76
  fastcgi
77
+ falcon
77
78
  ]
78
79
  while dispatchers.any? && @discovered_dispatcher.nil?
79
80
  send('check_for_' + (dispatchers.shift))
@@ -126,16 +127,24 @@ module NewRelic
126
127
  end
127
128
 
128
129
  def check_for_unicorn
129
- if (defined?(::Unicorn) && defined?(::Unicorn::HttpServer)) && NewRelic::LanguageSupport.object_space_usable?
130
- v = find_class_in_object_space(::Unicorn::HttpServer)
131
- @discovered_dispatcher = :unicorn if v
132
- end
130
+ return unless (defined?(::Unicorn) && defined?(::Unicorn::HttpServer)) &&
131
+ NewRelic::LanguageSupport.object_space_usable?
132
+
133
+ v = find_class_in_object_space(::Unicorn::HttpServer)
134
+ @discovered_dispatcher = :unicorn if v
133
135
  end
134
136
 
135
137
  def check_for_puma
136
- if defined?(::Puma) && File.basename($0) == 'puma'
137
- @discovered_dispatcher = :puma
138
- end
138
+ return unless defined?(::Puma) && File.basename($0) == 'puma'
139
+
140
+ @discovered_dispatcher = :puma
141
+ end
142
+
143
+ def check_for_falcon
144
+ return unless defined?(::Falcon::Server) &&
145
+ NewRelic::LanguageSupport.object_space_usable?
146
+
147
+ @discovered_dispatcher = :falcon if find_class_in_object_space(::Falcon::Server)
139
148
  end
140
149
 
141
150
  def check_for_delayed_job
@@ -178,15 +187,15 @@ module NewRelic
178
187
  end
179
188
 
180
189
  def check_for_litespeed
181
- if caller.pop.include?('fcgi-bin/RailsRunner.rb')
182
- @discovered_dispatcher = :litespeed
183
- end
190
+ return unless caller.pop.include?('fcgi-bin/RailsRunner.rb')
191
+
192
+ @discovered_dispatcher = :litespeed
184
193
  end
185
194
 
186
195
  def check_for_passenger
187
- if defined?(::PhusionPassenger)
188
- @discovered_dispatcher = :passenger
189
- end
196
+ return unless defined?(::PhusionPassenger)
197
+
198
+ @discovered_dispatcher = :passenger
190
199
  end
191
200
 
192
201
  public
@@ -80,7 +80,7 @@ module NewRelic
80
80
  "Expected #{klass} for `#{name}` but got #{arg.class}"
81
81
 
82
82
  NewRelic::Agent.logger.warn(message)
83
- nil
83
+ false
84
84
  end
85
85
  end
86
86
  end
@@ -6,7 +6,7 @@
6
6
  module NewRelic
7
7
  module VERSION # :nodoc:
8
8
  MAJOR = 9
9
- MINOR = 6
9
+ MINOR = 7
10
10
  TINY = 0
11
11
 
12
12
  STRING = "#{MAJOR}.#{MINOR}.#{TINY}"
@@ -19,7 +19,7 @@ namespace :newrelic do
19
19
  DISABLING => 'Use these settings to toggle instrumentation types during agent startup.',
20
20
  ATTRIBUTES => '[Attributes](/docs/features/agent-attributes) are key-value pairs containing information that determines the properties of an event or transaction. These key-value pairs can be viewed within transaction traces in APM, traced errors in APM, transaction events in dashboards, and page views in dashboards. You can customize exactly which attributes will be sent to each of these destinations',
21
21
  'transaction_tracer' => 'The [transaction traces](/docs/apm/traces/transaction-traces/transaction-traces) feature collects detailed information from a selection of transactions, including a summary of the calling sequence, a breakdown of time spent, and a list of SQL queries and their query plans (on mysql and postgresql). Available features depend on your New Relic subscription level.',
22
- 'error_collector' => "The agent collects and reports all uncaught exceptions by default. These configuration options allow you to customize the error collection.\n\nFor information on ignored and expected errors, [see this page on Error Analytics in APM](/docs/agents/manage-apm-agents/agent-data/manage-errors-apm-collect-ignore-or-mark-expected/). To set expected errors via the `NewRelic::Agent.notice_error` Ruby method, [consult the Ruby Agent API](/docs/agents/ruby-agent/api-guides/sending-handled-errors-new-relic/).",
22
+ 'error_collector' => "The agent collects and reports all uncaught exceptions by default. These configuration options allow you to customize the error collection.\n\nFor information on ignored and expected errors, [see this page on Error Analytics in APM](/docs/agents/manage-apm-agents/agent-data/manage-errors-apm-collect-ignore-or-mark-expected/). To set expected errors via the `NewRelic::Agent.notice_error` Ruby method, [consult the Ruby agent API](/docs/agents/ruby-agent/api-guides/sending-handled-errors-new-relic/).",
23
23
  'browser_monitoring' => "The browser monitoring [page load timing](/docs/browser/new-relic-browser/page-load-timing/page-load-timing-process) feature (sometimes referred to as real user monitoring or RUM) gives you insight into the performance real users are experiencing with your website. This is accomplished by measuring the time it takes for your users' browsers to download and render your web pages by injecting a small amount of JavaScript code into the header and footer of each page.",
24
24
  'application_logging' => "The Ruby agent supports [APM logs in context](/docs/apm/new-relic-apm/getting-started/get-started-logs-context). For some tips on configuring logs for the Ruby agent, see [Configure Ruby logs in context](/docs/logs/logs-context/configure-logs-context-ruby).\n\nAvailable logging-related config options include:",
25
25
  'analytics_events' => '[New Relic dashboards](/docs/query-your-data/explore-query-data/dashboards/introduction-new-relic-one-dashboards) is a resource to gather and visualize data about your software and what it says about your business. With it you can quickly and easily create real-time dashboards to get immediate answers about end-user experiences, clickstreams, mobile activities, and server transactions.'
@@ -14,7 +14,7 @@ redirects:
14
14
 
15
15
  <CONTRIBUTOR_NOTE>
16
16
  This file is automatically generated from values defined in `lib/new_relic/agent/configuration/default_source.rb`.
17
- All changes should be made directly to `default_source.rb.`
17
+ Make all changes directly to `default_source.rb.`
18
18
  Submit PRs or raise issues at: https://github.com/newrelic/newrelic-ruby-agent
19
19
  </CONTRIBUTOR_NOTE>
20
20
 
@@ -42,9 +42,9 @@ In other words, environment variables override all other configuration settings
42
42
 
43
43
  ## View and edit config file options [#Edit]
44
44
 
45
- The Ruby agent's `newrelic.yml` is a standard YAML configuration file. It typically includes a `Defaults` section at the top, plus sections below for each application environment; for example, `Development`, `Testing`, and `Production`.
45
+ The Ruby agent's `newrelic.yml` is a standard YAML configuration file. It typically includes a `Defaults` section at the top, plus sections below for each application environment (`Development`, `Test`, `Staging`, and `Production`).
46
46
 
47
- The Ruby agent determines which section of the `newrelic.yml` config file to read from by looking at certain environment variables to derive the application's environment. This can be useful, for example, when you want to use `info` for the `log_level` config setting in your production environment, and you want more verbose `log_level` config settings (such as `debug` in your development environment.
47
+ The Ruby agent determines which section of the `newrelic.yml` config file to read from by looking at certain environment variables to derive the application's environment. This can be useful when you want to use `info` for the `log_level` config setting in your production environment, and you want more verbose `log_level` config settings (such as `debug`) in your development environment.
48
48
 
49
49
  Here is an example `newrelic.yml` config file:
50
50
 
@@ -60,7 +60,7 @@ development:
60
60
  log_level: debug
61
61
  ```
62
62
 
63
- For non-Rails apps, the Ruby agent looks for the following environment variables, in this order, to determine the application environment:
63
+ The Ruby agent looks for the following environment variables, in this order, to find the application environment:
64
64
 
65
65
  1. `NEW_RELIC_ENV`
66
66
  2. `RUBY_ENV`
@@ -68,9 +68,9 @@ For non-Rails apps, the Ruby agent looks for the following environment variables
68
68
  4. `APP_ENV`
69
69
  5. `RACK_ENV`
70
70
 
71
- If the Ruby agent does not detect values for any of those environment variables, it will default the application environment to `development` and read from the `development` section of the `newrelic.yml` config file.
71
+ If the Ruby agent doesn't detect values for any of those environment variables, it will default the application environment to `development` and read from the `development` section of the `newrelic.yml` config file.
72
72
 
73
- When running the Ruby agent in a Rails app, the agent first looks for the `NEW_RELIC_ENV` environment variable to determine the application environment and which section of the `newrelic.yml` to use. If `NEW_RELIC_ENV` is not present, the agent uses the Rails environment (`RAILS_ENV` or `RAILS.env`, depending on the version of Rails) .
73
+ When running the Ruby agent in a Rails app, the agent first looks for the `NEW_RELIC_ENV` environment variable to determine the application environment and which section of the `newrelic.yml` to use. If `NEW_RELIC_ENV` is not present, the agent uses the Rails environment (`RAILS_ENV`).
74
74
 
75
75
  When you edit the config file, be sure to:
76
76
 
@@ -16,7 +16,7 @@ module NewRelicYML
16
16
 
17
17
  HEADER = <<~HEADER
18
18
  #
19
- # This file configures the New Relic Agent. New Relic monitors Ruby, Java,
19
+ # This file configures the New Relic agent. New Relic monitors Ruby, Java,
20
20
  # .NET, PHP, Python, Node, and Go applications with deep visibility and low
21
21
  # overhead. For more information, visit www.newrelic.com.
22
22
 
data/newrelic.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  #
2
- # This file configures the New Relic Agent. New Relic monitors Ruby, Java,
2
+ # This file configures the New Relic agent. New Relic monitors Ruby, Java,
3
3
  # .NET, PHP, Python, Node, and Go applications with deep visibility and low
4
4
  # overhead. For more information, visit www.newrelic.com.
5
5
 
@@ -341,7 +341,7 @@ common: &default_settings
341
341
  # embedded service within another framework and the agent is detecting the Sinatra
342
342
  # app and skipping the at_exit handler as a result. Sinatra classically runs the
343
343
  # entire application in an at_exit block and would otherwise misbehave if the
344
- # Agent's at_exit handler was also installed in those circumstances. Note:
344
+ # agent's at_exit handler was also installed in those circumstances. Note:
345
345
  # send_data_on_exit should also be set to true in tandem with this setting.
346
346
  # force_install_exit_handler: false
347
347
 
@@ -535,6 +535,10 @@ common: &default_settings
535
535
  # prepend, chain, disabled.
536
536
  # instrumentation.typhoeus: auto
537
537
 
538
+ # Controls auto-instrumentation of ViewComponent at startup. May be one of: auto,
539
+ # prepend, chain, disabled.
540
+ # instrumentation.view_component: auto
541
+
538
542
  # A dictionary of label names and values that will be applied to the data sent
539
543
  # from this agent. May also be expressed as a semicolon-delimited ; string of
540
544
  # colon-separated : pairs. For example, Server:One;Data Center:Primary.
data/newrelic_rpm.gemspec CHANGED
@@ -21,8 +21,8 @@ Gem::Specification.new do |s|
21
21
  https://github.com/newrelic/newrelic-ruby-agent/
22
22
  EOS
23
23
  s.email = 'support@newrelic.com'
24
- # TODO: MAJOR VERSION - remove newrelic_cmd, deprecated since version 2.13
25
- s.executables = %w[newrelic_cmd newrelic nrdebug]
24
+ # TODO: MAJOR VERSION - remove newrelic, deprecated since version xxx.
25
+ s.executables = %w[newrelic_rpm newrelic nrdebug]
26
26
  s.extra_rdoc_files = [
27
27
  'CHANGELOG.md',
28
28
  'LICENSE',
@@ -50,8 +50,6 @@ Gem::Specification.new do |s|
50
50
  s.require_paths = ['lib']
51
51
  s.summary = 'New Relic Ruby Agent'
52
52
 
53
- s.add_dependency 'base64'
54
-
55
53
  s.add_development_dependency 'bundler'
56
54
  s.add_development_dependency 'feedjira', '3.2.1' unless ENV['CI'] || RUBY_VERSION < '2.5' # for Gabby
57
55
  s.add_development_dependency 'httparty' unless ENV['CI'] # for perf tests and Gabby
@@ -62,7 +60,7 @@ Gem::Specification.new do |s|
62
60
  s.add_development_dependency 'rack'
63
61
  s.add_development_dependency 'rake', '12.3.3'
64
62
 
65
- s.add_development_dependency 'rubocop', '1.54' unless ENV['CI'] && RUBY_VERSION < '3.0.0'
63
+ s.add_development_dependency 'rubocop', '1.57.2' unless ENV['CI'] && RUBY_VERSION < '3.0.0'
66
64
  s.add_development_dependency 'rubocop-ast', '1.28.1' unless ENV['CI'] && RUBY_VERSION < '3.0.0'
67
65
  s.add_development_dependency 'rubocop-minitest', '0.27.0' unless ENV['CI'] && RUBY_VERSION < '3.0.0'
68
66
  s.add_development_dependency 'rubocop-performance', '1.16.0' unless ENV['CI'] && RUBY_VERSION < '3.0.0'
data/test/agent_helper.rb CHANGED
@@ -845,7 +845,7 @@ ensure
845
845
  end
846
846
 
847
847
  def json_dump_and_encode(object)
848
- Base64.encode64(JSON.dump(object))
848
+ NewRelic::Base64.encode64(JSON.dump(object))
849
849
  end
850
850
 
851
851
  def get_last_analytics_event
@@ -871,7 +871,7 @@ def load_cross_agent_test(name)
871
871
  test_file_path = File.join(cross_agent_tests_dir, "#{name}.json")
872
872
  data = File.read(test_file_path)
873
873
  data.gsub!('callCount', 'call_count')
874
- data = JSON.load(data)
874
+ data = JSON.parse(data)
875
875
  data.each { |testcase| testcase['testname'].tr!(' ', '_') if String === testcase['testname'] }
876
876
  data
877
877
  end
@@ -1025,3 +1025,15 @@ def defer_testing_to_min_supported_rails(test_file, min_rails_version, supports_
1025
1025
  puts "Skipping tests in #{File.basename(test_file)} because Rails >= #{min_rails_version} is unavailable" if ENV['VERBOSE_TEST_OUTPUT']
1026
1026
  end
1027
1027
  end
1028
+
1029
+ def first_call_for(subject)
1030
+ items = $collector.calls_for(subject)
1031
+
1032
+ if defined?(JRUBY_VERSION)
1033
+ refute_predicate items.size, :zero?, "Expected at least one call for '#{subject}'"
1034
+ else
1035
+ assert_equal 1, items.size, "Expected exactly one call for '#{subject}'"
1036
+ end
1037
+
1038
+ items.first
1039
+ end