newrelic_rpm 9.9.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 (219) hide show
  1. checksums.yaml +4 -4
  2. data/.build_ignore +1 -0
  3. data/CHANGELOG.md +463 -1
  4. data/CONTRIBUTING.md +2 -2
  5. data/README.md +16 -17
  6. data/Rakefile +1 -1
  7. data/lib/boot/strap.rb +102 -0
  8. data/lib/new_relic/agent/agent.rb +6 -0
  9. data/lib/new_relic/agent/agent_helpers/connect.rb +3 -0
  10. data/lib/new_relic/agent/agent_helpers/harvest.rb +3 -0
  11. data/lib/new_relic/agent/agent_helpers/shutdown.rb +3 -0
  12. data/lib/new_relic/agent/agent_helpers/start_worker_thread.rb +1 -0
  13. data/lib/new_relic/agent/agent_helpers/startup.rb +7 -0
  14. data/lib/new_relic/agent/agent_logger.rb +1 -0
  15. data/lib/new_relic/agent/aws.rb +68 -0
  16. data/lib/new_relic/agent/configuration/default_source.rb +603 -105
  17. data/lib/new_relic/agent/configuration/environment_source.rb +5 -1
  18. data/lib/new_relic/agent/configuration/manager.rb +28 -2
  19. data/lib/new_relic/agent/configuration/yaml_source.rb +7 -2
  20. data/lib/new_relic/agent/database/obfuscation_helpers.rb +11 -11
  21. data/lib/new_relic/agent/database/obfuscator.rb +1 -0
  22. data/lib/new_relic/agent/database.rb +41 -1
  23. data/lib/new_relic/agent/database_adapter.rb +1 -1
  24. data/lib/new_relic/agent/datastores/redis.rb +1 -1
  25. data/lib/new_relic/agent/distributed_tracing/cross_app_tracing.rb +1 -1
  26. data/lib/new_relic/agent/distributed_tracing.rb +4 -2
  27. data/lib/new_relic/agent/error_collector.rb +37 -10
  28. data/lib/new_relic/agent/external.rb +2 -0
  29. data/lib/new_relic/agent/health_check.rb +136 -0
  30. data/lib/new_relic/agent/http_clients/uri_util.rb +1 -1
  31. data/lib/new_relic/agent/instrumentation/action_dispatch.rb +1 -1
  32. data/lib/new_relic/agent/instrumentation/action_dispatch_subscriber.rb +1 -1
  33. data/lib/new_relic/agent/instrumentation/action_mailbox.rb +1 -1
  34. data/lib/new_relic/agent/instrumentation/action_mailer.rb +1 -1
  35. data/lib/new_relic/agent/instrumentation/active_job.rb +1 -1
  36. data/lib/new_relic/agent/instrumentation/active_job_subscriber.rb +6 -2
  37. data/lib/new_relic/agent/instrumentation/active_merchant.rb +0 -13
  38. data/lib/new_relic/agent/instrumentation/active_record.rb +7 -12
  39. data/lib/new_relic/agent/instrumentation/active_record_helper.rb +7 -3
  40. data/lib/new_relic/agent/instrumentation/active_record_notifications.rb +11 -9
  41. data/lib/new_relic/agent/instrumentation/active_record_prepend.rb +2 -2
  42. data/lib/new_relic/agent/instrumentation/active_record_subscriber.rb +9 -16
  43. data/lib/new_relic/agent/instrumentation/active_support_broadcast_logger.rb +0 -2
  44. data/lib/new_relic/agent/instrumentation/active_support_logger.rb +0 -2
  45. data/lib/new_relic/agent/instrumentation/async_http.rb +2 -3
  46. data/lib/new_relic/agent/instrumentation/aws_sdk_firehose/chain.rb +21 -0
  47. data/lib/new_relic/agent/instrumentation/aws_sdk_firehose/instrumentation.rb +66 -0
  48. data/lib/new_relic/agent/instrumentation/aws_sdk_firehose/prepend.rb +15 -0
  49. data/lib/new_relic/agent/instrumentation/aws_sdk_firehose.rb +22 -0
  50. data/lib/new_relic/agent/instrumentation/aws_sdk_kinesis/chain.rb +21 -0
  51. data/lib/new_relic/agent/instrumentation/aws_sdk_kinesis/instrumentation.rb +91 -0
  52. data/lib/new_relic/agent/instrumentation/aws_sdk_kinesis/prepend.rb +15 -0
  53. data/lib/new_relic/agent/instrumentation/aws_sdk_kinesis.rb +22 -0
  54. data/lib/new_relic/agent/instrumentation/aws_sdk_lambda/chain.rb +33 -0
  55. data/lib/new_relic/agent/instrumentation/aws_sdk_lambda/instrumentation.rb +93 -0
  56. data/lib/new_relic/agent/instrumentation/aws_sdk_lambda/prepend.rb +23 -0
  57. data/lib/new_relic/agent/instrumentation/aws_sdk_lambda.rb +23 -0
  58. data/lib/new_relic/agent/instrumentation/aws_sqs/chain.rb +37 -0
  59. data/lib/new_relic/agent/instrumentation/aws_sqs/instrumentation.rb +67 -0
  60. data/lib/new_relic/agent/instrumentation/aws_sqs/prepend.rb +21 -0
  61. data/lib/new_relic/agent/instrumentation/aws_sqs.rb +23 -0
  62. data/lib/new_relic/agent/instrumentation/bunny/instrumentation.rb +14 -0
  63. data/lib/new_relic/agent/instrumentation/bunny.rb +3 -4
  64. data/lib/new_relic/agent/instrumentation/concurrent_ruby.rb +1 -3
  65. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +4 -0
  66. data/lib/new_relic/agent/instrumentation/curb.rb +4 -5
  67. data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +0 -23
  68. data/lib/new_relic/agent/instrumentation/dynamodb/chain.rb +27 -0
  69. data/lib/new_relic/agent/instrumentation/dynamodb/instrumentation.rb +64 -0
  70. data/lib/new_relic/agent/instrumentation/dynamodb/prepend.rb +19 -0
  71. data/lib/new_relic/agent/instrumentation/dynamodb.rb +23 -0
  72. data/lib/new_relic/agent/instrumentation/elasticsearch/chain.rb +1 -2
  73. data/lib/new_relic/agent/instrumentation/elasticsearch/instrumentation.rb +53 -7
  74. data/lib/new_relic/agent/instrumentation/elasticsearch.rb +1 -3
  75. data/lib/new_relic/agent/instrumentation/ethon.rb +1 -5
  76. data/lib/new_relic/agent/instrumentation/excon.rb +1 -17
  77. data/lib/new_relic/agent/instrumentation/fiber/chain.rb +1 -1
  78. data/lib/new_relic/agent/instrumentation/fiber/prepend.rb +1 -1
  79. data/lib/new_relic/agent/instrumentation/fiber.rb +0 -2
  80. data/lib/new_relic/agent/instrumentation/grape/instrumentation.rb +0 -3
  81. data/lib/new_relic/agent/instrumentation/grape.rb +1 -1
  82. data/lib/new_relic/agent/instrumentation/grpc/client/instrumentation.rb +0 -1
  83. data/lib/new_relic/agent/instrumentation/httpclient.rb +1 -5
  84. data/lib/new_relic/agent/instrumentation/httprb.rb +0 -1
  85. data/lib/new_relic/agent/instrumentation/httpx/instrumentation.rb +1 -1
  86. data/lib/new_relic/agent/instrumentation/httpx.rb +1 -5
  87. data/lib/new_relic/agent/instrumentation/logger.rb +1 -3
  88. data/lib/new_relic/agent/instrumentation/logstasher/chain.rb +21 -0
  89. data/lib/new_relic/agent/instrumentation/logstasher/instrumentation.rb +24 -0
  90. data/lib/new_relic/agent/instrumentation/logstasher/prepend.rb +13 -0
  91. data/lib/new_relic/agent/instrumentation/logstasher.rb +25 -0
  92. data/lib/new_relic/agent/instrumentation/memcache/dalli.rb +1 -1
  93. data/lib/new_relic/agent/instrumentation/memcache/helper.rb +2 -2
  94. data/lib/new_relic/agent/instrumentation/memcache/instrumentation.rb +1 -1
  95. data/lib/new_relic/agent/instrumentation/memcache/prepend.rb +1 -1
  96. data/lib/new_relic/agent/instrumentation/memcache.rb +0 -1
  97. data/lib/new_relic/agent/instrumentation/mongodb_command_subscriber.rb +1 -1
  98. data/lib/new_relic/agent/instrumentation/net_http/instrumentation.rb +3 -3
  99. data/lib/new_relic/agent/instrumentation/net_http.rb +2 -1
  100. data/lib/new_relic/agent/instrumentation/notifications_subscriber.rb +0 -2
  101. data/lib/new_relic/agent/instrumentation/opensearch/chain.rb +21 -0
  102. data/lib/new_relic/agent/instrumentation/opensearch/instrumentation.rb +66 -0
  103. data/lib/{tasks/instrumentation_generator/templates/instrumentation.tt → new_relic/agent/instrumentation/opensearch/prepend.rb} +4 -4
  104. data/lib/new_relic/agent/instrumentation/opensearch.rb +23 -0
  105. data/lib/new_relic/agent/instrumentation/padrino.rb +3 -3
  106. data/lib/new_relic/agent/instrumentation/rack/instrumentation.rb +3 -0
  107. data/lib/new_relic/agent/instrumentation/rails_notifications/action_controller.rb +9 -5
  108. data/lib/new_relic/agent/instrumentation/rake.rb +1 -2
  109. data/lib/new_relic/agent/instrumentation/rdkafka/chain.rb +72 -0
  110. data/lib/new_relic/agent/instrumentation/rdkafka/instrumentation.rb +70 -0
  111. data/lib/new_relic/agent/instrumentation/rdkafka/prepend.rb +67 -0
  112. data/lib/new_relic/agent/instrumentation/rdkafka.rb +25 -0
  113. data/lib/new_relic/agent/instrumentation/redis/cluster_middleware.rb +26 -0
  114. data/lib/new_relic/agent/instrumentation/redis/constants.rb +2 -2
  115. data/lib/new_relic/agent/instrumentation/redis/instrumentation.rb +14 -11
  116. data/lib/new_relic/agent/instrumentation/redis/middleware.rb +3 -0
  117. data/lib/new_relic/agent/instrumentation/redis.rb +11 -5
  118. data/lib/new_relic/agent/instrumentation/resque.rb +8 -6
  119. data/lib/new_relic/agent/instrumentation/roda.rb +5 -5
  120. data/lib/new_relic/agent/instrumentation/ruby_kafka/chain.rb +55 -0
  121. data/lib/new_relic/agent/instrumentation/ruby_kafka/instrumentation.rb +67 -0
  122. data/lib/new_relic/agent/instrumentation/ruby_kafka/prepend.rb +60 -0
  123. data/lib/new_relic/agent/instrumentation/ruby_kafka.rb +25 -0
  124. data/lib/new_relic/agent/instrumentation/ruby_openai.rb +2 -2
  125. data/lib/new_relic/agent/instrumentation/sidekiq/extensions/delay_extensions.rb +24 -0
  126. data/lib/new_relic/agent/instrumentation/sidekiq/extensions/delayed_class.rb +2 -2
  127. data/lib/new_relic/agent/instrumentation/sidekiq.rb +9 -15
  128. data/lib/new_relic/agent/instrumentation/sinatra.rb +3 -19
  129. data/lib/new_relic/agent/instrumentation/stripe.rb +1 -1
  130. data/lib/new_relic/agent/instrumentation/stripe_subscriber.rb +22 -1
  131. data/lib/new_relic/agent/instrumentation/thread.rb +0 -2
  132. data/lib/new_relic/agent/instrumentation/tilt.rb +0 -4
  133. data/lib/new_relic/agent/instrumentation/typhoeus/instrumentation.rb +2 -2
  134. data/lib/new_relic/agent/instrumentation/typhoeus.rb +0 -1
  135. data/lib/new_relic/agent/instrumentation/view_component/instrumentation.rb +11 -5
  136. data/lib/new_relic/agent/instrumentation/view_component.rb +0 -2
  137. data/lib/new_relic/agent/javascript_instrumentor.rb +2 -3
  138. data/lib/new_relic/agent/llm/chat_completion_summary.rb +1 -1
  139. data/lib/new_relic/agent/llm/embedding.rb +1 -1
  140. data/lib/new_relic/agent/local_log_decorator.rb +20 -3
  141. data/lib/new_relic/agent/log_event_aggregator.rb +119 -28
  142. data/lib/new_relic/agent/logging.rb +1 -1
  143. data/lib/new_relic/agent/messaging.rb +16 -5
  144. data/lib/new_relic/agent/method_tracer.rb +3 -0
  145. data/lib/new_relic/agent/monitors/inbound_request_monitor.rb +1 -1
  146. data/lib/new_relic/agent/monitors/synthetics_monitor.rb +1 -1
  147. data/lib/new_relic/agent/new_relic_service/json_marshaller.rb +2 -2
  148. data/lib/new_relic/agent/new_relic_service.rb +8 -2
  149. data/lib/new_relic/agent/opentelemetry/context/propagation/trace_propagator.rb +66 -0
  150. data/lib/new_relic/agent/opentelemetry/context/propagation.rb +15 -0
  151. data/lib/{tasks/instrumentation_generator/templates/Envfile.tt → new_relic/agent/opentelemetry/context.rb} +9 -5
  152. data/lib/new_relic/agent/opentelemetry/trace/span.rb +31 -0
  153. data/lib/new_relic/agent/opentelemetry/trace/tracer.rb +129 -0
  154. data/lib/new_relic/agent/opentelemetry/trace/tracer_provider.rb +18 -0
  155. data/lib/new_relic/agent/opentelemetry/trace.rb +15 -0
  156. data/lib/new_relic/agent/opentelemetry/transaction_patch.rb +69 -0
  157. data/lib/new_relic/agent/opentelemetry_bridge.rb +32 -0
  158. data/lib/new_relic/agent/parameter_filtering.rb +1 -1
  159. data/lib/new_relic/agent/samplers/cpu_sampler.rb +1 -1
  160. data/lib/new_relic/agent/samplers/memory_sampler.rb +1 -1
  161. data/lib/new_relic/agent/serverless_handler.rb +247 -12
  162. data/lib/new_relic/agent/serverless_handler_event_sources.json +155 -0
  163. data/lib/new_relic/agent/serverless_handler_event_sources.rb +49 -0
  164. data/lib/new_relic/agent/span_event_primitive.rb +16 -11
  165. data/lib/new_relic/agent/system_info.rb +14 -0
  166. data/lib/new_relic/agent/threading/backtrace_node.rb +10 -1
  167. data/lib/new_relic/agent/tracer.rb +1 -1
  168. data/lib/new_relic/agent/transaction/abstract_segment.rb +2 -1
  169. data/lib/new_relic/agent/transaction/datastore_segment.rb +1 -1
  170. data/lib/new_relic/agent/transaction/distributed_tracer.rb +3 -3
  171. data/lib/new_relic/agent/transaction/external_request_segment.rb +0 -10
  172. data/lib/new_relic/agent/transaction/message_broker_segment.rb +4 -1
  173. data/lib/new_relic/agent/transaction/request_attributes.rb +14 -7
  174. data/lib/new_relic/agent/transaction/trace_context.rb +34 -5
  175. data/lib/new_relic/agent/transaction/tracing.rb +3 -3
  176. data/lib/new_relic/agent/transaction.rb +4 -7
  177. data/lib/new_relic/agent/transaction_time_aggregator.rb +1 -1
  178. data/lib/new_relic/agent/utilization/ecs.rb +22 -0
  179. data/lib/new_relic/agent/utilization/ecs_v4.rb +22 -0
  180. data/lib/new_relic/agent/utilization_data.rb +40 -5
  181. data/lib/new_relic/agent/vm/c_ruby_vm.rb +3 -3
  182. data/lib/new_relic/agent.rb +124 -2
  183. data/lib/new_relic/constants.rb +1 -0
  184. data/lib/new_relic/control/frameworks/grape.rb +14 -0
  185. data/lib/new_relic/control/frameworks/padrino.rb +14 -0
  186. data/lib/new_relic/control/frameworks/rails4.rb +1 -3
  187. data/lib/new_relic/control/instance_methods.rb +6 -0
  188. data/lib/new_relic/control/instrumentation.rb +1 -1
  189. data/lib/new_relic/control/private_instance_methods.rb +4 -0
  190. data/lib/new_relic/control/security_interface.rb +57 -0
  191. data/lib/new_relic/control.rb +1 -1
  192. data/lib/new_relic/dependency_detection.rb +11 -14
  193. data/lib/new_relic/environment_report.rb +2 -2
  194. data/lib/new_relic/helper.rb +22 -0
  195. data/lib/new_relic/language_support.rb +3 -1
  196. data/lib/new_relic/local_environment.rb +1 -4
  197. data/lib/new_relic/rack/browser_monitoring.rb +20 -8
  198. data/lib/new_relic/version.rb +1 -1
  199. data/lib/sequel/extensions/new_relic_instrumentation.rb +3 -2
  200. data/lib/tasks/config.rake +7 -3
  201. data/lib/tasks/gha.rake +31 -0
  202. data/lib/tasks/helpers/config.html.erb +3 -2
  203. data/lib/tasks/helpers/format.rb +1 -1
  204. data/lib/tasks/helpers/newrelicyml.rb +80 -13
  205. data/newrelic.yml +425 -162
  206. data/newrelic_rpm.gemspec +3 -1
  207. data/test/agent_helper.rb +24 -2
  208. metadata +91 -22
  209. data/lib/tasks/instrumentation_generator/README.md +0 -63
  210. data/lib/tasks/instrumentation_generator/TODO.md +0 -33
  211. data/lib/tasks/instrumentation_generator/instrumentation.thor +0 -121
  212. data/lib/tasks/instrumentation_generator/templates/chain.tt +0 -21
  213. data/lib/tasks/instrumentation_generator/templates/chain_method.tt +0 -7
  214. data/lib/tasks/instrumentation_generator/templates/dependency_detection.tt +0 -29
  215. data/lib/tasks/instrumentation_generator/templates/instrumentation_method.tt +0 -3
  216. data/lib/tasks/instrumentation_generator/templates/newrelic.yml.tt +0 -19
  217. data/lib/tasks/instrumentation_generator/templates/prepend.tt +0 -13
  218. data/lib/tasks/instrumentation_generator/templates/prepend_method.tt +0 -3
  219. data/lib/tasks/instrumentation_generator/templates/test.tt +0 -15
@@ -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
@@ -23,7 +23,6 @@ module NewRelic
23
23
  MISSING_STATUS_CODE = 'MissingHTTPStatusCode'
24
24
 
25
25
  attr_reader :library, :uri, :procedure, :http_status_code
26
- attr_writer :record_agent_attributes
27
26
 
28
27
  def initialize(library, uri, procedure, start_time = nil) # :nodoc:
29
28
  @library = library
@@ -32,7 +31,6 @@ module NewRelic
32
31
  @host_header = nil
33
32
  @app_data = nil
34
33
  @http_status_code = nil
35
- @record_agent_attributes = false
36
34
  super(nil, nil, start_time)
37
35
  end
38
36
 
@@ -44,14 +42,6 @@ module NewRelic
44
42
  @host_header || uri.host
45
43
  end
46
44
 
47
- # By default external request segments only have errors and the http
48
- # url recorded as agent attributes. To have all the agent attributes
49
- # recorded, use the attr_writer like so `segment.record_agent_attributes = true`
50
- # See: SpanEventPrimitive#for_external_request_segment
51
- def record_agent_attributes?
52
- @record_agent_attributes
53
- end
54
-
55
45
  # This method adds New Relic request headers to a given request made to an
56
46
  # external API and checks to see if a host header is used for the request.
57
47
  # If a host header is used, it updates the segment name to match the host
@@ -15,13 +15,15 @@ module NewRelic
15
15
  PRODUCE = 'Produce'.freeze
16
16
  QUEUE = 'Queue'.freeze
17
17
  PURGE = 'Purge'.freeze
18
+ STREAM = 'Stream'.freeze
18
19
  TEMP = 'Temp'.freeze
19
20
  TOPIC = 'Topic'.freeze
20
- UNKNOWN = 'Unknown'.freeze
21
+ UNKNOWN = NewRelic::UNKNOWN
21
22
 
22
23
  DESTINATION_TYPES = [
23
24
  :exchange,
24
25
  :queue,
26
+ :stream,
25
27
  :topic,
26
28
  :temporary_queue,
27
29
  :temporary_topic,
@@ -37,6 +39,7 @@ module NewRelic
37
39
  TYPES = {
38
40
  exchange: EXCHANGE,
39
41
  temporary_queue: QUEUE,
42
+ stream: STREAM,
40
43
  queue: QUEUE,
41
44
  temporary_topic: TOPIC,
42
45
  topic: TOPIC,
@@ -24,7 +24,7 @@ module NewRelic
24
24
  @referer = referer_from_request(request)
25
25
  @accept = attribute_from_env(request, HTTP_ACCEPT_HEADER_KEY)
26
26
  @content_length = content_length_from_request(request)
27
- @content_type = attribute_from_request(request, :content_type)
27
+ @content_type = content_type_attribute_from_request(request)
28
28
  @host = attribute_from_request(request, :host)
29
29
  @port = port_from_request(request)
30
30
  @user_agent = attribute_from_request(request, :user_agent)
@@ -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
@@ -127,6 +122,18 @@ module NewRelic
127
122
  end
128
123
  end
129
124
 
125
+ def content_type_attribute_from_request(request)
126
+ # Rails 7.0 changed the behavior of `content_type`. We want just the MIME type, so use `media_type` if available.
127
+ # https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#actiondispatch-request-content-type-now-returns-content-type-header-as-it-is
128
+ content_type = if request.respond_to?(:media_type)
129
+ :media_type
130
+ elsif request.respond_to?(:content_type)
131
+ :content_type
132
+ end
133
+
134
+ request.send(content_type) if content_type
135
+ end
136
+
130
137
  def attribute_from_env(request, key)
131
138
  if env = attribute_from_request(request, :env)
132
139
  env[key]
@@ -95,7 +95,7 @@ module NewRelic
95
95
 
96
96
  def create_trace_state_payload
97
97
  unless Agent.config[:'distributed_tracing.enabled']
98
- NewRelic::Agent.logger.warn('Not configured to create WC3 trace context payload')
98
+ NewRelic::Agent.logger.warn('Not configured to create W3C trace context payload')
99
99
  return
100
100
  end
101
101
 
@@ -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?
@@ -816,13 +817,9 @@ module NewRelic
816
817
  end
817
818
 
818
819
  def had_error_affecting_apdex?
819
- @exceptions.each do |exception, options|
820
- ignored = NewRelic::Agent.instance.error_collector.error_is_ignored?(exception)
821
- expected = options[:expected]
822
-
823
- return true unless ignored || expected
820
+ @exceptions.each.any? do |exception, options|
821
+ NewRelic::Agent.instance.error_collector.error_affects_apdex?(exception, options)
824
822
  end
825
- false
826
823
  end
827
824
 
828
825
  def apdex_bucket(duration, current_apdex_t)
@@ -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