newrelic_rpm 9.17.0 → 9.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. checksums.yaml +4 -4
  2. data/.build_ignore +1 -0
  3. data/CHANGELOG.md +105 -1
  4. data/lib/new_relic/agent/agent.rb +2 -0
  5. data/lib/new_relic/agent/agent_helpers/connect.rb +3 -3
  6. data/lib/new_relic/agent/agent_helpers/harvest.rb +3 -3
  7. data/lib/new_relic/agent/agent_helpers/shutdown.rb +1 -1
  8. data/lib/new_relic/agent/agent_helpers/start_worker_thread.rb +1 -1
  9. data/lib/new_relic/agent/agent_helpers/startup.rb +4 -4
  10. data/lib/new_relic/agent/configuration/default_source.rb +145 -120
  11. data/lib/new_relic/agent/configuration/manager.rb +5 -2
  12. data/lib/new_relic/agent/configuration/yaml_source.rb +4 -4
  13. data/lib/new_relic/agent/database.rb +1 -1
  14. data/lib/new_relic/agent/database_adapter.rb +1 -1
  15. data/lib/new_relic/agent/datastores/redis.rb +1 -1
  16. data/lib/new_relic/agent/distributed_tracing/cross_app_tracing.rb +1 -1
  17. data/lib/new_relic/agent/distributed_tracing.rb +2 -0
  18. data/lib/new_relic/agent/external.rb +2 -0
  19. data/lib/new_relic/agent/http_clients/uri_util.rb +1 -1
  20. data/lib/new_relic/agent/instrumentation/action_dispatch.rb +1 -1
  21. data/lib/new_relic/agent/instrumentation/action_dispatch_subscriber.rb +1 -1
  22. data/lib/new_relic/agent/instrumentation/action_mailbox.rb +1 -1
  23. data/lib/new_relic/agent/instrumentation/action_mailer.rb +1 -1
  24. data/lib/new_relic/agent/instrumentation/active_job.rb +1 -1
  25. data/lib/new_relic/agent/instrumentation/active_job_subscriber.rb +6 -2
  26. data/lib/new_relic/agent/instrumentation/active_record.rb +6 -4
  27. data/lib/new_relic/agent/instrumentation/active_record_helper.rb +2 -2
  28. data/lib/new_relic/agent/instrumentation/active_record_notifications.rb +11 -9
  29. data/lib/new_relic/agent/instrumentation/active_record_prepend.rb +2 -2
  30. data/lib/new_relic/agent/instrumentation/async_http.rb +1 -1
  31. data/lib/new_relic/agent/instrumentation/aws_sdk_kinesis/instrumentation.rb +1 -1
  32. data/lib/new_relic/agent/instrumentation/concurrent_ruby.rb +1 -1
  33. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +4 -0
  34. data/lib/new_relic/agent/instrumentation/curb.rb +1 -1
  35. data/lib/new_relic/agent/instrumentation/elasticsearch/chain.rb +1 -2
  36. data/lib/new_relic/agent/instrumentation/elasticsearch/instrumentation.rb +1 -0
  37. data/lib/new_relic/agent/instrumentation/elasticsearch.rb +1 -1
  38. data/lib/new_relic/agent/instrumentation/ethon.rb +1 -1
  39. data/lib/new_relic/agent/instrumentation/excon.rb +1 -1
  40. data/lib/new_relic/agent/instrumentation/fiber/chain.rb +1 -1
  41. data/lib/new_relic/agent/instrumentation/fiber/prepend.rb +1 -1
  42. data/lib/new_relic/agent/instrumentation/httpclient.rb +1 -4
  43. data/lib/new_relic/agent/instrumentation/httpx/instrumentation.rb +1 -1
  44. data/lib/new_relic/agent/instrumentation/httpx.rb +1 -1
  45. data/lib/new_relic/agent/instrumentation/logstasher.rb +1 -1
  46. data/lib/new_relic/agent/instrumentation/memcache/dalli.rb +1 -1
  47. data/lib/new_relic/agent/instrumentation/memcache/helper.rb +2 -2
  48. data/lib/new_relic/agent/instrumentation/memcache/instrumentation.rb +1 -1
  49. data/lib/new_relic/agent/instrumentation/memcache/prepend.rb +1 -1
  50. data/lib/new_relic/agent/instrumentation/mongodb_command_subscriber.rb +1 -1
  51. data/lib/new_relic/agent/instrumentation/net_http/instrumentation.rb +3 -3
  52. data/lib/new_relic/agent/instrumentation/net_http.rb +2 -1
  53. data/lib/new_relic/agent/instrumentation/notifications_subscriber.rb +0 -2
  54. data/lib/new_relic/agent/instrumentation/rake.rb +1 -1
  55. data/lib/new_relic/agent/instrumentation/rdkafka/chain.rb +2 -2
  56. data/lib/new_relic/agent/instrumentation/rdkafka/prepend.rb +2 -2
  57. data/lib/new_relic/agent/instrumentation/redis/constants.rb +2 -2
  58. data/lib/new_relic/agent/instrumentation/resque.rb +2 -2
  59. data/lib/new_relic/agent/instrumentation/roda.rb +1 -1
  60. data/lib/new_relic/agent/instrumentation/ruby_kafka/prepend.rb +1 -1
  61. data/lib/new_relic/agent/instrumentation/ruby_openai.rb +2 -2
  62. data/lib/new_relic/agent/instrumentation/sidekiq/extensions/delay_extensions.rb +24 -0
  63. data/lib/new_relic/agent/instrumentation/sidekiq/extensions/delayed_class.rb +1 -1
  64. data/lib/new_relic/agent/instrumentation/sidekiq.rb +9 -1
  65. data/lib/new_relic/agent/instrumentation/stripe.rb +1 -1
  66. data/lib/new_relic/agent/instrumentation/typhoeus/instrumentation.rb +2 -2
  67. data/lib/new_relic/agent/llm/chat_completion_summary.rb +1 -1
  68. data/lib/new_relic/agent/llm/embedding.rb +1 -1
  69. data/lib/new_relic/agent/local_log_decorator.rb +1 -1
  70. data/lib/new_relic/agent/logging.rb +1 -1
  71. data/lib/new_relic/agent/messaging.rb +5 -0
  72. data/lib/new_relic/agent/method_tracer.rb +3 -0
  73. data/lib/new_relic/agent/monitors/inbound_request_monitor.rb +1 -1
  74. data/lib/new_relic/agent/monitors/synthetics_monitor.rb +1 -1
  75. data/lib/new_relic/agent/new_relic_service/json_marshaller.rb +2 -2
  76. data/lib/new_relic/agent/new_relic_service.rb +2 -2
  77. data/lib/new_relic/agent/opentelemetry/context/propagation/trace_propagator.rb +66 -0
  78. data/lib/new_relic/agent/opentelemetry/context/propagation.rb +15 -0
  79. data/lib/{tasks/instrumentation_generator/templates/Envfile.tt → new_relic/agent/opentelemetry/context.rb} +9 -5
  80. data/lib/new_relic/agent/opentelemetry/trace/span.rb +31 -0
  81. data/lib/new_relic/agent/opentelemetry/trace/tracer.rb +129 -0
  82. data/lib/new_relic/agent/opentelemetry/trace/tracer_provider.rb +18 -0
  83. data/lib/new_relic/agent/opentelemetry/trace.rb +15 -0
  84. data/lib/new_relic/agent/opentelemetry/transaction_patch.rb +69 -0
  85. data/lib/new_relic/agent/opentelemetry_bridge.rb +32 -0
  86. data/lib/new_relic/agent/parameter_filtering.rb +1 -1
  87. data/lib/new_relic/agent/samplers/cpu_sampler.rb +1 -1
  88. data/lib/new_relic/agent/samplers/memory_sampler.rb +1 -1
  89. data/lib/new_relic/agent/serverless_handler.rb +7 -1
  90. data/lib/new_relic/agent/span_event_primitive.rb +8 -1
  91. data/lib/new_relic/agent/tracer.rb +1 -1
  92. data/lib/new_relic/agent/transaction/abstract_segment.rb +2 -1
  93. data/lib/new_relic/agent/transaction/datastore_segment.rb +1 -1
  94. data/lib/new_relic/agent/transaction/distributed_tracer.rb +3 -3
  95. data/lib/new_relic/agent/transaction/message_broker_segment.rb +1 -1
  96. data/lib/new_relic/agent/transaction/request_attributes.rb +1 -6
  97. data/lib/new_relic/agent/transaction/trace_context.rb +33 -4
  98. data/lib/new_relic/agent/transaction/tracing.rb +3 -3
  99. data/lib/new_relic/agent/transaction.rb +2 -1
  100. data/lib/new_relic/agent/transaction_time_aggregator.rb +1 -1
  101. data/lib/new_relic/agent/utilization/ecs.rb +22 -0
  102. data/lib/new_relic/agent/utilization/ecs_v4.rb +22 -0
  103. data/lib/new_relic/agent/utilization_data.rb +40 -5
  104. data/lib/new_relic/agent/vm/c_ruby_vm.rb +3 -3
  105. data/lib/new_relic/agent.rb +28 -0
  106. data/lib/new_relic/constants.rb +1 -0
  107. data/lib/new_relic/control/instance_methods.rb +5 -0
  108. data/lib/new_relic/control/instrumentation.rb +1 -1
  109. data/lib/new_relic/dependency_detection.rb +0 -1
  110. data/lib/new_relic/helper.rb +7 -0
  111. data/lib/new_relic/version.rb +1 -1
  112. data/lib/sequel/extensions/new_relic_instrumentation.rb +1 -1
  113. data/lib/tasks/helpers/newrelicyml.rb +6 -2
  114. data/newrelic.yml +80 -43
  115. data/newrelic_rpm.gemspec +1 -1
  116. metadata +17 -19
  117. data/lib/tasks/instrumentation_generator/README.md +0 -63
  118. data/lib/tasks/instrumentation_generator/TODO.md +0 -33
  119. data/lib/tasks/instrumentation_generator/instrumentation.thor +0 -130
  120. data/lib/tasks/instrumentation_generator/templates/chain.tt +0 -21
  121. data/lib/tasks/instrumentation_generator/templates/chain_method.tt +0 -7
  122. data/lib/tasks/instrumentation_generator/templates/dependency_detection.tt +0 -32
  123. data/lib/tasks/instrumentation_generator/templates/instrumentation.tt +0 -13
  124. data/lib/tasks/instrumentation_generator/templates/instrumentation_method.tt +0 -3
  125. data/lib/tasks/instrumentation_generator/templates/newrelic.yml.tt +0 -19
  126. data/lib/tasks/instrumentation_generator/templates/prepend.tt +0 -13
  127. data/lib/tasks/instrumentation_generator/templates/prepend_method.tt +0 -3
  128. data/lib/tasks/instrumentation_generator/templates/test.tt +0 -15
@@ -247,7 +247,7 @@ module NewRelic
247
247
  log_error('start_segment', exception)
248
248
  end
249
249
 
250
- UNKNOWN = 'Unknown'.freeze
250
+ UNKNOWN = NewRelic::UNKNOWN
251
251
  OTHER = 'other'.freeze
252
252
 
253
253
  # Creates and starts a datastore segment used to time
@@ -19,7 +19,7 @@ module NewRelic
19
19
  # after its parent. We will use the optimized exclusive duration
20
20
  # calculation in all other cases.
21
21
  #
22
- attr_reader :start_time, :end_time, :duration, :exclusive_duration, :guid, :starting_segment_key
22
+ attr_reader :start_time, :end_time, :duration, :exclusive_duration, :guid, :starting_segment_key, :thread_id
23
23
  attr_accessor :name, :parent, :children_time, :transaction, :transaction_name, :llm_event
24
24
  attr_writer :record_metrics, :record_scoped_metric, :record_on_finish
25
25
  attr_reader :noticed_error
@@ -30,6 +30,7 @@ module NewRelic
30
30
  def initialize(name = nil, start_time = nil)
31
31
  @name = name
32
32
  @starting_segment_key = NewRelic::Agent::Tracer.current_segment_key
33
+ @thread_id = Thread.current.object_id
33
34
  @transaction_name = nil
34
35
  @transaction = nil
35
36
  @guid = NewRelic::Agent::GuidGenerator.generate_guid
@@ -11,7 +11,7 @@ module NewRelic
11
11
  module Agent
12
12
  class Transaction
13
13
  class DatastoreSegment < Segment
14
- UNKNOWN = 'unknown'.freeze
14
+ UNKNOWN = NewRelic::UNKNOWN_LOWER
15
15
 
16
16
  attr_reader :product, :operation, :collection, :sql_statement, :nosql_statement, :host, :port_path_or_id
17
17
  attr_accessor :database_name, :record_sql
@@ -35,7 +35,7 @@ module NewRelic
35
35
  end
36
36
 
37
37
  def caller_transport_type
38
- @caller_transport_type ||= 'Unknown'
38
+ @caller_transport_type ||= NewRelic::UNKNOWN
39
39
  end
40
40
 
41
41
  def accept_transport_type_from_api(value)
@@ -127,7 +127,7 @@ module NewRelic
127
127
  def consume_message_synthetics_headers(headers)
128
128
  synthetics_header = headers[CrossAppTracing::NR_MESSAGE_BROKER_SYNTHETICS_HEADER]
129
129
  if synthetics_header and
130
- incoming_payload = ::JSON.load(deobfuscate(synthetics_header)) and
130
+ incoming_payload = ::JSON.parse(deobfuscate(synthetics_header)) and
131
131
  SyntheticsMonitor.is_valid_payload?(incoming_payload) and
132
132
  SyntheticsMonitor.is_supported_version?(incoming_payload) and
133
133
  SyntheticsMonitor.is_trusted?(incoming_payload)
@@ -167,7 +167,7 @@ module NewRelic
167
167
  return unless CrossAppTracing.trusted_valid_cross_app_id?(decoded_id)
168
168
 
169
169
  txn_header = headers[CrossAppTracing::NR_MESSAGE_BROKER_TXN_HEADER]
170
- txn_info = ::JSON.load(deobfuscate(txn_header))
170
+ txn_info = ::JSON.parse(deobfuscate(txn_header))
171
171
  payload = CrossAppPayload.new(decoded_id, transaction, txn_info)
172
172
 
173
173
  @cross_app_payload = payload
@@ -18,7 +18,7 @@ module NewRelic
18
18
  STREAM = 'Stream'.freeze
19
19
  TEMP = 'Temp'.freeze
20
20
  TOPIC = 'Topic'.freeze
21
- UNKNOWN = 'Unknown'.freeze
21
+ UNKNOWN = NewRelic::UNKNOWN
22
22
 
23
23
  DESTINATION_TYPES = [
24
24
  :exchange,
@@ -43,12 +43,7 @@ module NewRelic
43
43
  end
44
44
 
45
45
  if request_path
46
- destinations = if allow_other_headers?
47
- default_destinations
48
- else
49
- AttributeFilter::DST_TRANSACTION_TRACER | AttributeFilter::DST_ERROR_COLLECTOR
50
- end
51
- txn.add_agent_attribute(:'request.uri', request_path, destinations)
46
+ txn.add_agent_attribute(:'request.uri', request_path, default_destinations)
52
47
  end
53
48
 
54
49
  if accept
@@ -136,10 +136,8 @@ module NewRelic
136
136
 
137
137
  transaction.distributed_tracer.parent_transaction_id = payload.transaction_id
138
138
 
139
- unless payload.sampled.nil?
140
- transaction.sampled = payload.sampled
141
- transaction.priority = payload.priority if payload.priority
142
- end
139
+ determine_sampling_decision(payload, header_data.trace_parent['trace_flags'])
140
+
143
141
  NewRelic::Agent.increment_metric(ACCEPT_SUCCESS_METRIC)
144
142
  true
145
143
  rescue => e
@@ -148,6 +146,37 @@ module NewRelic
148
146
  false
149
147
  end
150
148
 
149
+ def determine_sampling_decision(payload, trace_flags)
150
+ if trace_flags == '01'
151
+ set_priority_and_sampled(NewRelic::Agent.config[:'distributed_tracing.sampler.remote_parent_sampled'], payload)
152
+ elsif trace_flags == '00'
153
+ set_priority_and_sampled(NewRelic::Agent.config[:'distributed_tracing.sampler.remote_parent_not_sampled'], payload)
154
+ else
155
+ use_nr_tracestate_sampled(payload)
156
+ end
157
+ rescue
158
+ use_nr_tracestate_sampled(payload)
159
+ end
160
+
161
+ def use_nr_tracestate_sampled(payload)
162
+ unless payload.sampled.nil?
163
+ transaction.sampled = payload.sampled
164
+ transaction.priority = payload.priority if payload.priority
165
+ end
166
+ end
167
+
168
+ def set_priority_and_sampled(config, payload)
169
+ if config == 'always_on'
170
+ transaction.sampled = true
171
+ transaction.priority = 2.0
172
+ elsif config == 'always_off'
173
+ transaction.sampled = false
174
+ transaction.priority = 0
175
+ else # default
176
+ use_nr_tracestate_sampled(payload)
177
+ end
178
+ end
179
+
151
180
  def ignore_trace_context?
152
181
  if trace_context_header_data
153
182
  NewRelic::Agent.increment_metric(IGNORE_MULTIPLE_ACCEPT_METRIC)
@@ -25,7 +25,7 @@ module NewRelic
25
25
  segment.parent = parent || thread_starting_span || current_segment
26
26
  set_current_segment(segment)
27
27
  if @segments.length < segment_limit
28
- @segments << segment
28
+ @segment_lock.synchronize { @segments << segment }
29
29
  else
30
30
  segment.record_on_finish = true
31
31
  ::NewRelic::Agent.logger.debug("Segment limit of #{segment_limit} reached, ceasing collection.")
@@ -51,7 +51,7 @@ module NewRelic
51
51
 
52
52
  def segment_complete(segment)
53
53
  # if parent was in another thread, remove the current_segment entry for this thread
54
- if segment.parent && segment.parent.starting_segment_key != NewRelic::Agent::Tracer.current_segment_key
54
+ if segment.parent&.starting_segment_key != NewRelic::Agent::Tracer.current_segment_key
55
55
  remove_current_segment_by_thread_id(NewRelic::Agent::Tracer.current_segment_key)
56
56
  else
57
57
  set_current_segment(segment.parent)
@@ -65,7 +65,7 @@ module NewRelic
65
65
  private
66
66
 
67
67
  def finalize_segments
68
- segments.each { |s| s.finalize }
68
+ @segment_lock.synchronize { segments.each { |s| s&.finalize } }
69
69
  end
70
70
 
71
71
  WEB_TRANSACTION_TOTAL_TIME = 'WebTransactionTotalTime'.freeze
@@ -215,6 +215,7 @@ module NewRelic
215
215
  @nesting_max_depth = 0
216
216
  @current_segment_by_thread = {}
217
217
  @current_segment_lock = Mutex.new
218
+ @segment_lock = Mutex.new
218
219
  @segments = []
219
220
 
220
221
  self.default_name = options[:transaction_name]
@@ -437,7 +438,7 @@ module NewRelic
437
438
  end
438
439
 
439
440
  def initial_segment
440
- segments.first
441
+ segments&.first
441
442
  end
442
443
 
443
444
  def finished?
@@ -150,7 +150,7 @@ module NewRelic
150
150
  # rubocop:disable Style/SafeNavigation
151
151
  transaction_name = transaction_name = Tracer.current_transaction &&
152
152
  Tracer.current_transaction.best_name ||
153
- 'unknown'
153
+ NewRelic::UNKNOWN_LOWER
154
154
  # rubocop:enable Style/SafeNavigation
155
155
  NewRelic::Agent.logger.warn("Unable to calculate elapsed transaction time for #{transaction_name}")
156
156
  end
@@ -0,0 +1,22 @@
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 'new_relic/agent/utilization/vendor'
6
+
7
+ module NewRelic
8
+ module Agent
9
+ module Utilization
10
+ class ECS < Vendor
11
+ vendor_name 'ecs'
12
+ endpoint ENV['ECS_CONTAINER_METADATA_URI'] || ''
13
+ headers 'Metadata' => 'true'
14
+ keys %w[DockerId]
15
+
16
+ def transform_key(key)
17
+ 'ecs' + key
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
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 'new_relic/agent/utilization/vendor'
6
+
7
+ module NewRelic
8
+ module Agent
9
+ module Utilization
10
+ class ECSV4 < Vendor
11
+ vendor_name 'ecs_v4'
12
+ endpoint ENV['ECS_CONTAINER_METADATA_URI_V4'] || ''
13
+ headers 'Metadata' => 'true'
14
+ keys %w[DockerId]
15
+
16
+ def transform_key(key)
17
+ 'ecs' + key
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -6,6 +6,8 @@ require 'new_relic/agent/utilization/aws'
6
6
  require 'new_relic/agent/utilization/gcp'
7
7
  require 'new_relic/agent/utilization/azure'
8
8
  require 'new_relic/agent/utilization/pcf'
9
+ require 'new_relic/agent/utilization/ecs'
10
+ require 'new_relic/agent/utilization/ecs_v4'
9
11
 
10
12
  module NewRelic
11
13
  module Agent
@@ -84,18 +86,51 @@ module NewRelic
84
86
  result
85
87
  end
86
88
 
89
+ def append_ecs_info(collector_hash)
90
+ return unless Agent.config[:'utilization.detect_aws']
91
+
92
+ Thread.new do
93
+ # try v4 first, and only try unversioned endpoint if v4 fails
94
+ ecs = Utilization::ECSV4.new
95
+ if ecs.detect
96
+ collector_hash[:vendors] ||= {}
97
+ collector_hash[:vendors][:ecs] = ecs.metadata
98
+ else
99
+ ecs = Utilization::ECS.new
100
+ if ecs.detect
101
+ collector_hash[:vendors] ||= {}
102
+ collector_hash[:vendors][:ecs] = ecs.metadata
103
+ end
104
+ end
105
+ end
106
+ end
107
+
87
108
  def append_vendor_info(collector_hash)
109
+ threads = []
110
+ complete = false
111
+
112
+ # ecs needs be checked even if AWS check succeeds
113
+ ecs_thread = append_ecs_info(collector_hash)
114
+
88
115
  VENDORS.each_pair do |klass, config_option|
89
116
  next unless Agent.config[config_option]
90
117
 
91
- vendor = klass.new
118
+ threads << Thread.new do
119
+ vendor = klass.new
92
120
 
93
- if vendor.detect
94
- collector_hash[:vendors] ||= {}
95
- collector_hash[:vendors][vendor.vendor_name.to_sym] = vendor.metadata
96
- break
121
+ if vendor.detect
122
+ collector_hash[:vendors] ||= {}
123
+ collector_hash[:vendors][vendor.vendor_name.to_sym] = vendor.metadata
124
+
125
+ complete = true
126
+ end
97
127
  end
98
128
  end
129
+
130
+ while complete == false && threads.any?(&:alive?)
131
+ sleep 0.01
132
+ end
133
+ ecs_thread&.join
99
134
  end
100
135
 
101
136
  def append_docker_info(collector_hash)
@@ -61,7 +61,7 @@ module NewRelic
61
61
  end
62
62
 
63
63
  def gather_constant_cache_invalidations
64
- RubyVM.stat[RUBY_VERSION >= '3.2.0' ? :constant_cache_invalidations : :global_constant_state]
64
+ RubyVM.stat[NewRelic::Helper.version_satisfied?(RUBY_VERSION, '>=', '3.2.0') ? :constant_cache_invalidations : :global_constant_state]
65
65
  end
66
66
 
67
67
  def gather_constant_cache_misses
@@ -86,9 +86,9 @@ module NewRelic
86
86
  when :gc_total_time
87
87
  NewRelic::LanguageSupport.gc_profiler_enabled?
88
88
  when :method_cache_invalidations
89
- RUBY_VERSION < '3.0.0'
89
+ NewRelic::Helper.version_satisfied?(RUBY_VERSION, '<', '3.0.0')
90
90
  when :constant_cache_misses
91
- RUBY_VERSION >= '3.2.0'
91
+ NewRelic::Helper.version_satisfied?(RUBY_VERSION, '>=', '3.2.0')
92
92
  else
93
93
  false
94
94
  end
@@ -293,6 +293,7 @@ module NewRelic
293
293
  #
294
294
  # This method is safe to use from any thread.
295
295
  #
296
+ # @!scope class
296
297
  # @api public
297
298
  def record_metric(metric_name, value) # THREAD_LOCAL_ACCESS
298
299
  record_api_supportability_metric(:record_metric)
@@ -333,6 +334,7 @@ module NewRelic
333
334
  #
334
335
  # This method is safe to use from any thread.
335
336
  #
337
+ # @!scope class
336
338
  # @api public
337
339
  #
338
340
  def increment_metric(metric_name, amount = 1) # THREAD_LOCAL_ACCESS
@@ -360,6 +362,7 @@ module NewRelic
360
362
  #
361
363
  # Return the new block or the existing filter Proc if no block is passed.
362
364
  #
365
+ # @!scope class
363
366
  # @api public
364
367
  #
365
368
  def ignore_error_filter(&block)
@@ -398,6 +401,7 @@ module NewRelic
398
401
  # them if you are calling <code>notice_error</code> outside a
399
402
  # transaction.
400
403
  #
404
+ # @!scope class
401
405
  # @api public
402
406
  #
403
407
  def notice_error(exception, options = {})
@@ -435,6 +439,7 @@ module NewRelic
435
439
  # :'error.expected' => Whether (true) or not (false) the error was expected
436
440
  # :options => The options hash passed to `NewRelic::Agent.notice_error`
437
441
  #
442
+ # @!scope class
438
443
  # @api public
439
444
  #
440
445
  def set_error_group_callback(callback_proc)
@@ -474,6 +479,7 @@ module NewRelic
474
479
  # may be strings, symbols, numeric values or
475
480
  # booleans.
476
481
  #
482
+ # @!scope class
477
483
  # @api public
478
484
  #
479
485
  def record_custom_event(event_type, event_attrs)
@@ -506,6 +512,7 @@ module NewRelic
506
512
  # @param [optional, Hash] Set of key-value pairs to store any other
507
513
  # desired data to submit with the feedback event.
508
514
  #
515
+ # @!scope class
509
516
  # @api public
510
517
  #
511
518
  def record_llm_feedback_event(trace_id:,
@@ -559,6 +566,7 @@ module NewRelic
559
566
  # :model => [String] The name of the LLM model
560
567
  # :content => [String] The message content or prompt
561
568
  #
569
+ # @!scope class
562
570
  # @api public
563
571
  #
564
572
  def set_llm_token_count_callback(callback_proc)
@@ -591,6 +599,7 @@ module NewRelic
591
599
  # file logger. The setting for the newrelic.yml section to use
592
600
  # (ie, RAILS_ENV) can be overridden with an :env argument.
593
601
  #
602
+ # @!scope class
594
603
  # @api public
595
604
  #
596
605
  def manual_start(options = {})
@@ -623,6 +632,7 @@ module NewRelic
623
632
  # connection, this tells me to only try it once so this method returns
624
633
  # quickly if there is some kind of latency with the server.
625
634
  #
635
+ # @!scope class
626
636
  # @api public
627
637
  #
628
638
  def after_fork(options = {})
@@ -636,6 +646,7 @@ module NewRelic
636
646
  #
637
647
  # @param options [Hash] Unused options Hash, for back compatibility only
638
648
  #
649
+ # @!scope class
639
650
  # @api public
640
651
  #
641
652
  def shutdown(options = {})
@@ -646,6 +657,7 @@ module NewRelic
646
657
  # Clear out any data the agent has buffered but has not yet transmitted
647
658
  # to the collector.
648
659
  #
660
+ # @!scope class
649
661
  # @api public
650
662
  def drop_buffered_data
651
663
  # the following line needs else branch coverage
@@ -660,6 +672,7 @@ module NewRelic
660
672
  # register instrumentation than just loading the files directly,
661
673
  # although that probably also works.
662
674
  #
675
+ # @!scope class
663
676
  # @api public
664
677
  #
665
678
  def add_instrumentation(file_pattern)
@@ -669,6 +682,7 @@ module NewRelic
669
682
 
670
683
  # Require agent testing helper methods
671
684
  #
685
+ # @!scope class
672
686
  # @api public
673
687
  def require_test_helper
674
688
  record_api_supportability_metric(:require_test_helper)
@@ -689,6 +703,7 @@ module NewRelic
689
703
  # my_obfuscator(sql)
690
704
  # end
691
705
  #
706
+ # @!scope class
692
707
  # @api public
693
708
  #
694
709
  def set_sql_obfuscator(type = :replace, &block)
@@ -704,6 +719,7 @@ module NewRelic
704
719
  # traced errors, transaction traces, Insights events, slow SQL traces,
705
720
  # or RUM injection will happen for this transaction.
706
721
  #
722
+ # @!scope class
707
723
  # @api public
708
724
  #
709
725
  def ignore_transaction
@@ -714,6 +730,7 @@ module NewRelic
714
730
  # This method disables the recording of Apdex metrics in the current
715
731
  # transaction.
716
732
  #
733
+ # @!scope class
717
734
  # @api public
718
735
  #
719
736
  def ignore_apdex
@@ -724,6 +741,7 @@ module NewRelic
724
741
  # This method disables browser monitoring javascript injection in the
725
742
  # current transaction.
726
743
  #
744
+ # @!scope class
727
745
  # @api public
728
746
  #
729
747
  def ignore_enduser
@@ -736,6 +754,7 @@ module NewRelic
736
754
  # track of the first entry point and turn on tracing again after
737
755
  # leaving that block. This uses the thread local Tracer::State.
738
756
  #
757
+ # @!scope class
739
758
  # @api public
740
759
  #
741
760
  def disable_all_tracing
@@ -760,6 +779,7 @@ module NewRelic
760
779
  # ...
761
780
  # end
762
781
  #
782
+ # @!scope class
763
783
  # @api public
764
784
  #
765
785
  def disable_sql_recording
@@ -798,6 +818,7 @@ module NewRelic
798
818
  # may be strings, symbols, numeric values or
799
819
  # booleans.
800
820
  #
821
+ # @!scope class
801
822
  # @api public
802
823
  #
803
824
  def add_custom_attributes(params) # THREAD_LOCAL_ACCESS
@@ -838,6 +859,7 @@ module NewRelic
838
859
  # booleans.
839
860
  #
840
861
  # @see https://docs.newrelic.com/docs/using-new-relic/welcome-new-relic/get-started/glossary#span
862
+ # @!scope class
841
863
  # @api public
842
864
  def add_custom_span_attributes(params)
843
865
  record_api_supportability_metric(:add_custom_span_attributes)
@@ -879,6 +901,7 @@ module NewRelic
879
901
  #
880
902
  # Attribute pairs with empty or nil contents
881
903
  # will be dropped.
904
+ # @!scope class
882
905
  # @api public
883
906
  def add_custom_log_attributes(params)
884
907
  record_api_supportability_metric(:add_custom_log_attributes)
@@ -894,6 +917,7 @@ module NewRelic
894
917
  #
895
918
  # @param [String] user_id The user id to add to the current transaction attributes
896
919
  #
920
+ # @!scope class
897
921
  # @api public
898
922
  def set_user_id(user_id)
899
923
  record_api_supportability_metric(:set_user_id)
@@ -937,6 +961,7 @@ module NewRelic
937
961
  #
938
962
  # The default category is the same as the running transaction.
939
963
  #
964
+ # @!scope class
940
965
  # @api public
941
966
  #
942
967
  def set_transaction_name(name, options = {})
@@ -947,6 +972,7 @@ module NewRelic
947
972
  # Get the name of the current running transaction. This is useful if you
948
973
  # want to modify the default name.
949
974
  #
975
+ # @!scope class
950
976
  # @api public
951
977
  #
952
978
  def get_transaction_name # THREAD_LOCAL_ACCESS
@@ -1018,6 +1044,7 @@ module NewRelic
1018
1044
  # * entity.guid - The guid of the current entity.
1019
1045
  # * hostname - The fully qualified hostname.
1020
1046
  #
1047
+ # @!scope class
1021
1048
  # @api public
1022
1049
  def linking_metadata
1023
1050
  metadata = Hash.new
@@ -1044,6 +1071,7 @@ module NewRelic
1044
1071
  #
1045
1072
  # @param [String] nonce The nonce to use in the javascript tag for browser instrumentation
1046
1073
  #
1074
+ # @!scope class
1047
1075
  # @api public
1048
1076
  #
1049
1077
  def browser_timing_header(nonce = nil)
@@ -16,6 +16,7 @@ module NewRelic
16
16
  HTTP = 'HTTP'
17
17
  HTTPS = 'HTTPS'
18
18
  UNKNOWN = 'Unknown'
19
+ UNKNOWN_LOWER = 'unknown'
19
20
 
20
21
  FORMAT_NON_RACK = 0
21
22
  FORMAT_RACK = 1
@@ -74,6 +74,7 @@ module NewRelic
74
74
  NewRelic::Agent.agent = NewRelic::Agent::Agent.instance
75
75
  init_instrumentation
76
76
  init_security_agent
77
+ report_agent_version_metric
77
78
  end
78
79
 
79
80
  def determine_env(options)
@@ -171,6 +172,10 @@ module NewRelic
171
172
  def stdout
172
173
  STDOUT
173
174
  end
175
+
176
+ def report_agent_version_metric
177
+ NewRelic::Agent.record_metric_once("Supportability/AgentVersion/newrelic_rpm/#{NewRelic::VERSION::STRING}")
178
+ end
174
179
  end
175
180
  include InstanceMethods
176
181
  end
@@ -68,7 +68,7 @@ module NewRelic
68
68
  end
69
69
 
70
70
  def rails_32_deprecation
71
- return unless defined?(Rails::VERSION) && Gem::Version.new(Rails::VERSION::STRING) <= Gem::Version.new('3.2')
71
+ return unless defined?(Rails::VERSION) && NewRelic::Helper.version_satisfied?(Rails::VERSION::STRING, '<=', '3.2')
72
72
 
73
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. ' \
@@ -179,7 +179,6 @@ module DependencyDetection
179
179
  # logs the resolved value during debug mode.
180
180
  def fetch_config_value(key)
181
181
  valid_value = valid_config_value(::NewRelic::Agent.config[key].to_s.to_sym)
182
- ::NewRelic::Agent.logger.debug("Using #{valid_value} configuration value for #{self.name} to configure instrumentation")
183
182
  return valid_value
184
183
  end
185
184
 
@@ -83,6 +83,13 @@ module NewRelic
83
83
  end
84
84
  end
85
85
 
86
+ def version_satisfied?(left, operator, right)
87
+ left = Gem::Version.new(left) unless left.is_a?(Gem::Version)
88
+ right = Gem::Version.new(right) unless right.is_a?(Gem::Version)
89
+
90
+ left.public_send(operator, right)
91
+ end
92
+
86
93
  # Bundler version 2.5.12 deprecated all_specs and added installed_specs.
87
94
  # To support newer Bundler versions, try to use installed_specs first,
88
95
  # then fall back to all_specs.
@@ -6,7 +6,7 @@
6
6
  module NewRelic
7
7
  module VERSION # :nodoc:
8
8
  MAJOR = 9
9
- MINOR = 17
9
+ MINOR = 21
10
10
  TINY = 0
11
11
 
12
12
  STRING = "#{MAJOR}.#{MINOR}.#{TINY}"
@@ -79,7 +79,7 @@ module Sequel
79
79
 
80
80
  THREAD_SAFE_CONNECTION_POOL_CLASSES = [
81
81
  (defined?(::Sequel::ThreadedConnectionPool) && ::Sequel::ThreadedConnectionPool),
82
- (defined?(::Sequel::TimedQueueConnectionPool) && RUBY_VERSION >= '3.2' && ::Sequel::TimedQueueConnectionPool)
82
+ (defined?(::Sequel::TimedQueueConnectionPool) && NewRelic::Helper.version_satisfied?(RUBY_VERSION, '>=', '3.2') && ::Sequel::TimedQueueConnectionPool)
83
83
  ].compact.freeze
84
84
 
85
85
  def explainer_for(sql)
@@ -141,6 +141,8 @@ module NewRelicYML
141
141
  description.gsub!(/<InlinePopover type="(.*)" \/>/, '\1')
142
142
  # remove hyperlinks
143
143
  description.gsub!(/\[([^\]]+)\]\([^\)]+\)/, '\1')
144
+ # delete lines with code fences including the language
145
+ description.gsub!(/```[a-zA-Z0-9_]*\n(.*?)```/m, '\1')
144
146
  # remove single pairs of backticks
145
147
  description.gsub!(/`([^`]+)`/, '\1')
146
148
  # removed href links
@@ -150,11 +152,13 @@ module NewRelicYML
150
152
  end
151
153
 
152
154
  def self.format_description(description)
155
+ # remove all tab characters
156
+ description.delete!("\t")
153
157
  # remove leading and trailing whitespace
154
158
  description.strip!
155
159
  # wrap text after 80 characters, assuming we're at one tabstop's (two
156
- # spaces') level of indentation already
157
- description.gsub!(/(.{1,78})(\s+|\Z)/, "\\1\n")
160
+ # spaces') level of indentation already, keep leading whitespace
161
+ description.gsub!(/(.{1,78})(\s|\Z)/, "\\1\n")
158
162
  # add hashtags to lines
159
163
  description = description.split("\n").map { |line| " # #{line}" }.join("\n")
160
164