newrelic_rpm 9.1.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 (360) hide show
  1. checksums.yaml +4 -4
  2. data/.build_ignore +27 -0
  3. data/CHANGELOG.md +841 -7
  4. data/CONTRIBUTING.md +2 -9
  5. data/README.md +25 -22
  6. data/Rakefile +2 -2
  7. data/bin/newrelic +3 -9
  8. data/bin/newrelic_rpm +15 -0
  9. data/init.rb +2 -2
  10. data/lib/boot/strap.rb +102 -0
  11. data/lib/new_relic/agent/agent.rb +11 -2
  12. data/lib/new_relic/agent/agent_helpers/connect.rb +13 -8
  13. data/lib/new_relic/agent/agent_helpers/harvest.rb +3 -0
  14. data/lib/new_relic/agent/agent_helpers/shutdown.rb +4 -1
  15. data/lib/new_relic/agent/agent_helpers/special_startup.rb +1 -1
  16. data/lib/new_relic/agent/agent_helpers/start_worker_thread.rb +4 -3
  17. data/lib/new_relic/agent/agent_helpers/startup.rb +11 -3
  18. data/lib/new_relic/agent/agent_logger.rb +3 -1
  19. data/lib/new_relic/agent/attribute_filter.rb +3 -3
  20. data/lib/new_relic/agent/attribute_pre_filtering.rb +109 -0
  21. data/lib/new_relic/agent/aws.rb +68 -0
  22. data/lib/new_relic/agent/configuration/default_source.rb +918 -166
  23. data/lib/new_relic/agent/configuration/environment_source.rb +15 -3
  24. data/lib/new_relic/agent/configuration/high_security_source.rb +1 -0
  25. data/lib/new_relic/agent/configuration/manager.rb +72 -11
  26. data/lib/new_relic/agent/configuration/security_policy_source.rb +11 -0
  27. data/lib/new_relic/agent/configuration/yaml_source.rb +22 -2
  28. data/lib/new_relic/agent/connect/request_builder.rb +1 -1
  29. data/lib/new_relic/agent/custom_event_aggregator.rb +27 -1
  30. data/lib/new_relic/agent/database/obfuscation_helpers.rb +11 -11
  31. data/lib/new_relic/agent/database/obfuscator.rb +1 -0
  32. data/lib/new_relic/agent/database.rb +41 -1
  33. data/lib/new_relic/agent/database_adapter.rb +1 -1
  34. data/lib/new_relic/agent/datastores/mongo/metric_translator.rb +1 -1
  35. data/lib/new_relic/agent/datastores/redis.rb +1 -1
  36. data/lib/new_relic/agent/distributed_tracing/cross_app_tracing.rb +1 -1
  37. data/lib/new_relic/agent/distributed_tracing/distributed_trace_payload.rb +4 -8
  38. data/lib/new_relic/agent/distributed_tracing.rb +5 -3
  39. data/lib/new_relic/agent/error_collector.rb +40 -11
  40. data/lib/new_relic/agent/event_loop.rb +1 -1
  41. data/lib/new_relic/agent/external.rb +2 -0
  42. data/lib/new_relic/agent/harvester.rb +1 -1
  43. data/lib/new_relic/agent/health_check.rb +136 -0
  44. data/lib/new_relic/agent/http_clients/abstract.rb +4 -0
  45. data/lib/new_relic/agent/http_clients/async_http_wrappers.rb +80 -0
  46. data/lib/new_relic/agent/http_clients/curb_wrappers.rb +1 -3
  47. data/lib/new_relic/agent/http_clients/ethon_wrappers.rb +109 -0
  48. data/lib/new_relic/agent/http_clients/excon_wrappers.rb +0 -3
  49. data/lib/new_relic/agent/http_clients/http_rb_wrappers.rb +1 -3
  50. data/lib/new_relic/agent/http_clients/httpclient_wrappers.rb +0 -3
  51. data/lib/new_relic/agent/http_clients/httpx_wrappers.rb +91 -0
  52. data/lib/new_relic/agent/http_clients/net_http_wrappers.rb +1 -4
  53. data/lib/new_relic/agent/http_clients/typhoeus_wrappers.rb +0 -3
  54. data/lib/new_relic/agent/http_clients/uri_util.rb +1 -1
  55. data/lib/new_relic/agent/instrumentation/action_controller_other_subscriber.rb +1 -1
  56. data/lib/new_relic/agent/instrumentation/action_dispatch.rb +1 -1
  57. data/lib/new_relic/agent/instrumentation/action_dispatch_subscriber.rb +1 -1
  58. data/lib/new_relic/agent/instrumentation/action_mailbox.rb +1 -1
  59. data/lib/new_relic/agent/instrumentation/action_mailer.rb +1 -1
  60. data/lib/new_relic/agent/instrumentation/active_job.rb +1 -1
  61. data/lib/new_relic/agent/instrumentation/active_job_subscriber.rb +6 -2
  62. data/lib/new_relic/agent/instrumentation/active_merchant.rb +3 -16
  63. data/lib/new_relic/agent/instrumentation/active_record.rb +8 -13
  64. data/lib/new_relic/agent/instrumentation/active_record_helper.rb +8 -5
  65. data/lib/new_relic/agent/instrumentation/active_record_notifications.rb +13 -10
  66. data/lib/new_relic/agent/instrumentation/active_record_prepend.rb +2 -2
  67. data/lib/new_relic/agent/instrumentation/active_record_subscriber.rb +9 -16
  68. data/lib/new_relic/agent/instrumentation/active_support_broadcast_logger/chain.rb +69 -0
  69. data/lib/new_relic/agent/instrumentation/active_support_broadcast_logger/instrumentation.rb +17 -0
  70. data/lib/new_relic/agent/instrumentation/active_support_broadcast_logger/prepend.rb +37 -0
  71. data/lib/new_relic/agent/instrumentation/active_support_broadcast_logger.rb +21 -0
  72. data/lib/new_relic/agent/instrumentation/active_support_logger/instrumentation.rb +4 -0
  73. data/lib/new_relic/agent/instrumentation/active_support_logger.rb +3 -3
  74. data/lib/new_relic/agent/instrumentation/async_http/chain.rb +23 -0
  75. data/lib/new_relic/agent/instrumentation/async_http/instrumentation.rb +37 -0
  76. data/lib/new_relic/agent/instrumentation/async_http/prepend.rb +15 -0
  77. data/lib/new_relic/agent/instrumentation/async_http.rb +27 -0
  78. data/lib/new_relic/agent/instrumentation/aws_sdk_firehose/chain.rb +21 -0
  79. data/lib/new_relic/agent/instrumentation/aws_sdk_firehose/instrumentation.rb +66 -0
  80. data/lib/new_relic/agent/instrumentation/aws_sdk_firehose/prepend.rb +15 -0
  81. data/lib/new_relic/agent/instrumentation/aws_sdk_firehose.rb +22 -0
  82. data/lib/new_relic/agent/instrumentation/aws_sdk_kinesis/chain.rb +21 -0
  83. data/lib/new_relic/agent/instrumentation/aws_sdk_kinesis/instrumentation.rb +91 -0
  84. data/lib/new_relic/agent/instrumentation/aws_sdk_kinesis/prepend.rb +15 -0
  85. data/lib/new_relic/agent/instrumentation/aws_sdk_kinesis.rb +22 -0
  86. data/lib/new_relic/agent/instrumentation/aws_sdk_lambda/chain.rb +33 -0
  87. data/lib/new_relic/agent/instrumentation/aws_sdk_lambda/instrumentation.rb +93 -0
  88. data/lib/new_relic/agent/instrumentation/aws_sdk_lambda/prepend.rb +23 -0
  89. data/lib/new_relic/agent/instrumentation/aws_sdk_lambda.rb +23 -0
  90. data/lib/new_relic/agent/instrumentation/aws_sqs/chain.rb +37 -0
  91. data/lib/new_relic/agent/instrumentation/aws_sqs/instrumentation.rb +67 -0
  92. data/lib/new_relic/agent/instrumentation/aws_sqs/prepend.rb +21 -0
  93. data/lib/new_relic/agent/instrumentation/aws_sqs.rb +23 -0
  94. data/lib/new_relic/agent/instrumentation/bunny/chain.rb +1 -1
  95. data/lib/new_relic/agent/instrumentation/bunny/instrumentation.rb +23 -0
  96. data/lib/new_relic/agent/instrumentation/bunny.rb +4 -5
  97. data/lib/new_relic/agent/instrumentation/concurrent_ruby/chain.rb +1 -1
  98. data/lib/new_relic/agent/instrumentation/concurrent_ruby/instrumentation.rb +3 -4
  99. data/lib/new_relic/agent/instrumentation/concurrent_ruby/prepend.rb +1 -1
  100. data/lib/new_relic/agent/instrumentation/concurrent_ruby.rb +2 -3
  101. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +5 -2
  102. data/lib/new_relic/agent/instrumentation/curb/instrumentation.rb +4 -0
  103. data/lib/new_relic/agent/instrumentation/curb.rb +4 -5
  104. data/lib/new_relic/agent/instrumentation/delayed_job/chain.rb +1 -0
  105. data/lib/new_relic/agent/instrumentation/delayed_job/instrumentation.rb +3 -0
  106. data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +0 -23
  107. data/lib/new_relic/agent/instrumentation/dynamodb/chain.rb +27 -0
  108. data/lib/new_relic/agent/instrumentation/dynamodb/instrumentation.rb +64 -0
  109. data/lib/new_relic/agent/instrumentation/dynamodb/prepend.rb +19 -0
  110. data/lib/new_relic/agent/instrumentation/dynamodb.rb +23 -0
  111. data/lib/new_relic/agent/instrumentation/elasticsearch/chain.rb +2 -3
  112. data/lib/new_relic/agent/instrumentation/elasticsearch/instrumentation.rb +65 -10
  113. data/lib/new_relic/agent/instrumentation/elasticsearch.rb +2 -4
  114. data/lib/new_relic/agent/instrumentation/ethon/chain.rb +39 -0
  115. data/lib/new_relic/agent/instrumentation/ethon/instrumentation.rb +105 -0
  116. data/lib/new_relic/agent/instrumentation/ethon/prepend.rb +35 -0
  117. data/lib/new_relic/agent/instrumentation/ethon.rb +35 -0
  118. data/lib/new_relic/agent/instrumentation/excon/middleware.rb +3 -0
  119. data/lib/new_relic/agent/instrumentation/excon.rb +1 -17
  120. data/lib/new_relic/agent/instrumentation/fiber/chain.rb +11 -4
  121. data/lib/new_relic/agent/instrumentation/fiber/instrumentation.rb +2 -6
  122. data/lib/new_relic/agent/instrumentation/fiber/prepend.rb +10 -3
  123. data/lib/new_relic/agent/instrumentation/fiber.rb +1 -3
  124. data/lib/new_relic/agent/instrumentation/grape/instrumentation.rb +4 -3
  125. data/lib/new_relic/agent/instrumentation/grape.rb +1 -1
  126. data/lib/new_relic/agent/instrumentation/grpc/client/chain.rb +1 -1
  127. data/lib/new_relic/agent/instrumentation/grpc/client/instrumentation.rb +5 -2
  128. data/lib/new_relic/agent/instrumentation/grpc/client/prepend.rb +1 -1
  129. data/lib/new_relic/agent/instrumentation/grpc/client/request_wrapper.rb +1 -1
  130. data/lib/new_relic/agent/instrumentation/grpc/server/instrumentation.rb +5 -1
  131. data/lib/new_relic/agent/instrumentation/grpc_client.rb +2 -2
  132. data/lib/new_relic/agent/instrumentation/grpc_server.rb +2 -2
  133. data/lib/new_relic/agent/instrumentation/httpclient/instrumentation.rb +4 -0
  134. data/lib/new_relic/agent/instrumentation/httpclient.rb +1 -5
  135. data/lib/new_relic/agent/instrumentation/httprb/instrumentation.rb +4 -0
  136. data/lib/new_relic/agent/instrumentation/httprb.rb +0 -1
  137. data/lib/new_relic/agent/instrumentation/httpx/chain.rb +20 -0
  138. data/lib/new_relic/agent/instrumentation/httpx/instrumentation.rb +51 -0
  139. data/lib/new_relic/agent/instrumentation/httpx/prepend.rb +15 -0
  140. data/lib/new_relic/agent/instrumentation/httpx.rb +23 -0
  141. data/lib/new_relic/agent/instrumentation/logger/instrumentation.rb +3 -0
  142. data/lib/new_relic/agent/instrumentation/logger.rb +1 -3
  143. data/lib/new_relic/agent/instrumentation/logstasher/chain.rb +21 -0
  144. data/lib/new_relic/agent/instrumentation/logstasher/instrumentation.rb +24 -0
  145. data/lib/new_relic/agent/instrumentation/logstasher/prepend.rb +13 -0
  146. data/lib/new_relic/agent/instrumentation/logstasher.rb +25 -0
  147. data/lib/new_relic/agent/instrumentation/memcache/dalli.rb +4 -2
  148. data/lib/new_relic/agent/instrumentation/memcache/helper.rb +2 -2
  149. data/lib/new_relic/agent/instrumentation/memcache/instrumentation.rb +13 -4
  150. data/lib/new_relic/agent/instrumentation/memcache/prepend.rb +4 -2
  151. data/lib/new_relic/agent/instrumentation/memcache.rb +4 -5
  152. data/lib/new_relic/agent/instrumentation/mongodb_command_subscriber.rb +3 -5
  153. data/lib/new_relic/agent/instrumentation/net_http/instrumentation.rb +13 -3
  154. data/lib/new_relic/agent/instrumentation/net_http.rb +2 -1
  155. data/lib/new_relic/agent/instrumentation/notifications_subscriber.rb +4 -2
  156. data/lib/new_relic/agent/instrumentation/opensearch/chain.rb +21 -0
  157. data/lib/new_relic/agent/instrumentation/opensearch/instrumentation.rb +66 -0
  158. data/lib/new_relic/agent/instrumentation/opensearch/prepend.rb +13 -0
  159. data/lib/new_relic/agent/instrumentation/opensearch.rb +23 -0
  160. data/lib/new_relic/agent/instrumentation/padrino/instrumentation.rb +4 -0
  161. data/lib/new_relic/agent/instrumentation/padrino.rb +3 -3
  162. data/lib/new_relic/agent/instrumentation/queue_time.rb +1 -1
  163. data/lib/new_relic/agent/instrumentation/rack/instrumentation.rb +9 -0
  164. data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +4 -0
  165. data/lib/new_relic/agent/instrumentation/rails_notifications/action_cable.rb +1 -1
  166. data/lib/new_relic/agent/instrumentation/rails_notifications/action_controller.rb +10 -5
  167. data/lib/new_relic/agent/instrumentation/rake/instrumentation.rb +4 -0
  168. data/lib/new_relic/agent/instrumentation/rake.rb +1 -2
  169. data/lib/new_relic/agent/instrumentation/rdkafka/chain.rb +72 -0
  170. data/lib/new_relic/agent/instrumentation/rdkafka/instrumentation.rb +70 -0
  171. data/lib/new_relic/agent/instrumentation/rdkafka/prepend.rb +67 -0
  172. data/lib/new_relic/agent/instrumentation/rdkafka.rb +25 -0
  173. data/lib/new_relic/agent/instrumentation/redis/cluster_middleware.rb +26 -0
  174. data/lib/new_relic/agent/instrumentation/redis/constants.rb +2 -2
  175. data/lib/new_relic/agent/instrumentation/redis/instrumentation.rb +18 -11
  176. data/lib/new_relic/agent/instrumentation/redis/middleware.rb +3 -0
  177. data/lib/new_relic/agent/instrumentation/redis.rb +11 -5
  178. data/lib/new_relic/agent/instrumentation/resque/instrumentation.rb +4 -0
  179. data/lib/new_relic/agent/instrumentation/resque.rb +8 -6
  180. data/lib/new_relic/agent/instrumentation/roda/chain.rb +43 -0
  181. data/lib/new_relic/agent/instrumentation/roda/ignorer.rb +45 -0
  182. data/lib/new_relic/agent/instrumentation/roda/instrumentation.rb +68 -0
  183. data/lib/new_relic/agent/instrumentation/roda/prepend.rb +24 -0
  184. data/lib/new_relic/agent/instrumentation/roda/roda_transaction_namer.rb +29 -0
  185. data/lib/new_relic/agent/instrumentation/roda.rb +36 -0
  186. data/lib/new_relic/agent/instrumentation/ruby_kafka/chain.rb +55 -0
  187. data/lib/new_relic/agent/instrumentation/ruby_kafka/instrumentation.rb +67 -0
  188. data/lib/new_relic/agent/instrumentation/ruby_kafka/prepend.rb +60 -0
  189. data/lib/new_relic/agent/instrumentation/ruby_kafka.rb +25 -0
  190. data/lib/new_relic/agent/instrumentation/ruby_openai/chain.rb +36 -0
  191. data/lib/new_relic/agent/instrumentation/ruby_openai/instrumentation.rb +196 -0
  192. data/lib/new_relic/agent/instrumentation/ruby_openai/prepend.rb +20 -0
  193. data/lib/new_relic/agent/instrumentation/ruby_openai.rb +35 -0
  194. data/lib/new_relic/agent/instrumentation/sequel.rb +1 -1
  195. data/lib/new_relic/agent/instrumentation/sidekiq/client.rb +4 -0
  196. data/lib/new_relic/agent/instrumentation/sidekiq/extensions/delay_extensions.rb +24 -0
  197. data/lib/new_relic/agent/instrumentation/sidekiq/extensions/delayed_class.rb +2 -2
  198. data/lib/new_relic/agent/instrumentation/sidekiq/server.rb +26 -3
  199. data/lib/new_relic/agent/instrumentation/sidekiq.rb +13 -16
  200. data/lib/new_relic/agent/instrumentation/sinatra/ignorer.rb +1 -1
  201. data/lib/new_relic/agent/instrumentation/sinatra/instrumentation.rb +4 -0
  202. data/lib/new_relic/agent/instrumentation/sinatra/transaction_namer.rb +1 -3
  203. data/lib/new_relic/agent/instrumentation/sinatra.rb +3 -19
  204. data/lib/new_relic/agent/instrumentation/stripe.rb +28 -0
  205. data/lib/new_relic/agent/instrumentation/stripe_subscriber.rb +98 -0
  206. data/lib/new_relic/agent/instrumentation/thread/chain.rb +1 -1
  207. data/lib/new_relic/agent/instrumentation/thread/instrumentation.rb +1 -5
  208. data/lib/new_relic/agent/instrumentation/thread/prepend.rb +1 -1
  209. data/lib/new_relic/agent/instrumentation/thread.rb +0 -2
  210. data/lib/new_relic/agent/instrumentation/tilt/instrumentation.rb +4 -0
  211. data/lib/new_relic/agent/instrumentation/tilt.rb +0 -4
  212. data/lib/new_relic/agent/instrumentation/typhoeus/instrumentation.rb +7 -3
  213. data/lib/new_relic/agent/instrumentation/typhoeus.rb +0 -1
  214. data/lib/new_relic/agent/instrumentation/view_component/chain.rb +21 -0
  215. data/lib/new_relic/agent/instrumentation/view_component/instrumentation.rb +45 -0
  216. data/lib/{tasks/instrumentation_generator/templates/instrumentation.tt → new_relic/agent/instrumentation/view_component/prepend.rb} +4 -4
  217. data/lib/new_relic/agent/instrumentation/view_component.rb +24 -0
  218. data/lib/new_relic/agent/javascript_instrumentor.rb +2 -4
  219. data/lib/new_relic/agent/llm/chat_completion_message.rb +25 -0
  220. data/lib/new_relic/agent/llm/chat_completion_summary.rb +66 -0
  221. data/lib/new_relic/agent/llm/embedding.rb +60 -0
  222. data/lib/new_relic/agent/llm/llm_event.rb +95 -0
  223. data/lib/new_relic/agent/llm/response_headers.rb +80 -0
  224. data/lib/new_relic/agent/llm.rb +49 -0
  225. data/lib/new_relic/agent/local_log_decorator.rb +20 -3
  226. data/lib/new_relic/agent/log_event_aggregator.rb +149 -26
  227. data/lib/new_relic/agent/log_event_attributes.rb +115 -0
  228. data/lib/new_relic/agent/logging.rb +5 -5
  229. data/lib/new_relic/agent/messaging.rb +18 -7
  230. data/lib/new_relic/agent/method_tracer.rb +4 -1
  231. data/lib/new_relic/agent/method_tracer_helpers.rb +26 -5
  232. data/lib/new_relic/agent/monitors/inbound_request_monitor.rb +1 -1
  233. data/lib/new_relic/agent/monitors/synthetics_monitor.rb +12 -1
  234. data/lib/new_relic/agent/new_relic_service/encoders.rb +2 -2
  235. data/lib/new_relic/agent/new_relic_service/json_marshaller.rb +2 -2
  236. data/lib/new_relic/agent/new_relic_service.rb +61 -28
  237. data/lib/new_relic/agent/obfuscator.rb +0 -2
  238. data/lib/new_relic/agent/opentelemetry/context/propagation/trace_propagator.rb +66 -0
  239. data/lib/new_relic/agent/opentelemetry/context/propagation.rb +15 -0
  240. data/lib/{tasks/instrumentation_generator/templates/Envfile.tt → new_relic/agent/opentelemetry/context.rb} +9 -5
  241. data/lib/new_relic/agent/opentelemetry/trace/span.rb +31 -0
  242. data/lib/new_relic/agent/opentelemetry/trace/tracer.rb +129 -0
  243. data/lib/new_relic/agent/opentelemetry/trace/tracer_provider.rb +18 -0
  244. data/lib/new_relic/agent/opentelemetry/trace.rb +15 -0
  245. data/lib/new_relic/agent/opentelemetry/transaction_patch.rb +69 -0
  246. data/lib/new_relic/agent/opentelemetry_bridge.rb +32 -0
  247. data/lib/new_relic/agent/parameter_filtering.rb +1 -1
  248. data/lib/new_relic/agent/pipe_channel_manager.rb +2 -2
  249. data/lib/new_relic/agent/pipe_service.rb +1 -1
  250. data/lib/new_relic/agent/rules_engine/segment_terms_rule.rb +1 -2
  251. data/lib/new_relic/agent/rules_engine.rb +1 -1
  252. data/lib/new_relic/agent/sampler.rb +1 -0
  253. data/lib/new_relic/agent/samplers/cpu_sampler.rb +1 -1
  254. data/lib/new_relic/agent/samplers/memory_sampler.rb +1 -1
  255. data/lib/new_relic/agent/serverless_handler.rb +406 -0
  256. data/lib/new_relic/agent/serverless_handler_event_sources.json +155 -0
  257. data/lib/new_relic/agent/serverless_handler_event_sources.rb +49 -0
  258. data/lib/new_relic/agent/span_event_primitive.rb +32 -15
  259. data/lib/new_relic/agent/sql_sampler.rb +0 -1
  260. data/lib/new_relic/agent/system_info.rb +40 -0
  261. data/lib/new_relic/agent/threading/agent_thread.rb +1 -2
  262. data/lib/new_relic/agent/threading/backtrace_node.rb +10 -1
  263. data/lib/new_relic/agent/tracer.rb +16 -16
  264. data/lib/new_relic/agent/transaction/abstract_segment.rb +103 -41
  265. data/lib/new_relic/agent/transaction/datastore_segment.rb +1 -1
  266. data/lib/new_relic/agent/transaction/distributed_tracer.rb +3 -3
  267. data/lib/new_relic/agent/transaction/distributed_tracing.rb +7 -8
  268. data/lib/new_relic/agent/transaction/external_request_segment.rb +5 -12
  269. data/lib/new_relic/agent/transaction/message_broker_segment.rb +5 -3
  270. data/lib/new_relic/agent/transaction/request_attributes.rb +54 -11
  271. data/lib/new_relic/agent/transaction/trace_context.rb +34 -5
  272. data/lib/new_relic/agent/transaction/tracing.rb +20 -4
  273. data/lib/new_relic/agent/transaction.rb +38 -13
  274. data/lib/new_relic/agent/transaction_error_primitive.rb +39 -19
  275. data/lib/new_relic/agent/transaction_event_primitive.rb +19 -0
  276. data/lib/new_relic/agent/transaction_time_aggregator.rb +1 -1
  277. data/lib/new_relic/agent/utilization/ecs.rb +22 -0
  278. data/lib/new_relic/agent/utilization/ecs_v4.rb +22 -0
  279. data/lib/new_relic/agent/utilization/gcp.rb +1 -3
  280. data/lib/new_relic/agent/utilization/vendor.rb +5 -7
  281. data/lib/new_relic/agent/utilization_data.rb +40 -5
  282. data/lib/new_relic/agent/vm/{mri_vm.rb → c_ruby_vm.rb} +10 -18
  283. data/lib/new_relic/agent/vm.rb +2 -2
  284. data/lib/new_relic/agent/worker_loop.rb +1 -1
  285. data/lib/new_relic/agent.rb +286 -17
  286. data/lib/new_relic/base64.rb +25 -0
  287. data/lib/new_relic/cli/command.rb +6 -3
  288. data/lib/new_relic/constants.rb +8 -0
  289. data/lib/new_relic/control/class_methods.rb +1 -7
  290. data/lib/new_relic/control/frameworks/grape.rb +14 -0
  291. data/lib/new_relic/control/frameworks/padrino.rb +14 -0
  292. data/lib/new_relic/control/frameworks/rails.rb +17 -5
  293. data/lib/new_relic/control/frameworks/rails4.rb +1 -3
  294. data/lib/new_relic/control/frameworks/roda.rb +20 -0
  295. data/lib/new_relic/control/instance_methods.rb +13 -0
  296. data/lib/new_relic/control/instrumentation.rb +2 -16
  297. data/lib/new_relic/control/private_instance_methods.rb +4 -0
  298. data/lib/new_relic/control/security_interface.rb +57 -0
  299. data/lib/new_relic/control.rb +1 -1
  300. data/lib/new_relic/dependency_detection.rb +25 -13
  301. data/lib/new_relic/environment_report.rb +2 -2
  302. data/lib/new_relic/helper.rb +22 -0
  303. data/lib/new_relic/language_support.rb +12 -1
  304. data/lib/new_relic/latest_changes.rb +1 -1
  305. data/lib/new_relic/local_environment.rb +31 -18
  306. data/lib/new_relic/noticed_error.rb +5 -2
  307. data/lib/new_relic/rack/agent_hooks.rb +1 -1
  308. data/lib/new_relic/rack/agent_middleware.rb +0 -16
  309. data/lib/new_relic/rack/browser_monitoring.rb +29 -13
  310. data/lib/new_relic/supportability_helper.rb +5 -1
  311. data/lib/new_relic/thread_local_storage.rb +31 -0
  312. data/lib/new_relic/traced_thread.rb +2 -3
  313. data/lib/new_relic/version.rb +1 -1
  314. data/lib/sequel/extensions/new_relic_instrumentation.rb +4 -3
  315. data/lib/tasks/bump_version.rake +21 -0
  316. data/lib/tasks/config.rake +11 -5
  317. data/lib/tasks/coverage_report.rake +1 -1
  318. data/lib/tasks/gha.rake +31 -0
  319. data/lib/tasks/helpers/config.html.erb +94 -0
  320. data/lib/tasks/helpers/format.rb +11 -7
  321. data/lib/tasks/helpers/newrelicyml.rb +211 -0
  322. data/lib/tasks/helpers/version_bump.rb +62 -0
  323. data/lib/tasks/newrelic.rb +1 -0
  324. data/lib/tasks/newrelicyml.rake +13 -0
  325. data/lib/tasks/tests.rake +71 -0
  326. data/newrelic.yml +657 -251
  327. data/newrelic_rpm.gemspec +17 -10
  328. data/test/agent_helper.rb +38 -4
  329. metadata +230 -44
  330. data/.gitignore +0 -43
  331. data/.project +0 -23
  332. data/.rubocop.yml +0 -1909
  333. data/.rubocop_todo.yml +0 -61
  334. data/.simplecov +0 -15
  335. data/.snyk +0 -11
  336. data/.yardopts +0 -27
  337. data/Brewfile +0 -12
  338. data/DOCKER.md +0 -167
  339. data/Dockerfile +0 -10
  340. data/Guardfile +0 -26
  341. data/bin/newrelic_cmd +0 -6
  342. data/config/database.yml +0 -5
  343. data/config.dot +0 -278
  344. data/docker-compose.yml +0 -107
  345. data/lefthook.yml +0 -9
  346. data/lib/new_relic/agent/range_extensions.rb +0 -27
  347. data/lib/tasks/helpers/removers.rb +0 -33
  348. data/lib/tasks/instrumentation_generator/README.md +0 -63
  349. data/lib/tasks/instrumentation_generator/TODO.md +0 -33
  350. data/lib/tasks/instrumentation_generator/instrumentation.thor +0 -121
  351. data/lib/tasks/instrumentation_generator/templates/chain.tt +0 -22
  352. data/lib/tasks/instrumentation_generator/templates/chain_method.tt +0 -8
  353. data/lib/tasks/instrumentation_generator/templates/dependency_detection.tt +0 -29
  354. data/lib/tasks/instrumentation_generator/templates/instrumentation_method.tt +0 -3
  355. data/lib/tasks/instrumentation_generator/templates/newrelic.yml.tt +0 -19
  356. data/lib/tasks/instrumentation_generator/templates/prepend.tt +0 -13
  357. data/lib/tasks/instrumentation_generator/templates/prepend_method.tt +0 -3
  358. data/lib/tasks/instrumentation_generator/templates/test.tt +0 -15
  359. data/lib/tasks/multiverse.rake +0 -6
  360. data/lib/tasks/multiverse.rb +0 -83
@@ -8,21 +8,28 @@ module NewRelic
8
8
  module Agent
9
9
  class Transaction
10
10
  class RequestAttributes
11
- attr_reader :request_path, :referer, :accept, :content_length, :content_type,
12
- :host, :port, :user_agent, :request_method
11
+ # the HTTP standard has "referrer" mispelled as "referer"
12
+ attr_reader :accept, :content_length, :content_type, :host, :other_headers, :port, :referer, :request_method,
13
+ :request_path, :user_agent
13
14
 
14
15
  HTTP_ACCEPT_HEADER_KEY = 'HTTP_ACCEPT'.freeze
15
16
 
17
+ BASE_HEADERS = %w[CONTENT_LENGTH CONTENT_TYPE HTTP_ACCEPT HTTP_REFERER HTTP_USER_AGENT PATH_INFO REMOTE_HOST
18
+ REQUEST_METHOD REQUEST_URI SERVER_PORT].freeze
19
+
20
+ ATTRIBUTE_PREFIX = 'request.headers.'
21
+
16
22
  def initialize(request)
17
23
  @request_path = path_from_request(request)
18
24
  @referer = referer_from_request(request)
19
25
  @accept = attribute_from_env(request, HTTP_ACCEPT_HEADER_KEY)
20
26
  @content_length = content_length_from_request(request)
21
- @content_type = attribute_from_request(request, :content_type)
27
+ @content_type = content_type_attribute_from_request(request)
22
28
  @host = attribute_from_request(request, :host)
23
29
  @port = port_from_request(request)
24
30
  @user_agent = attribute_from_request(request, :user_agent)
25
31
  @request_method = attribute_from_request(request, :request_method)
32
+ @other_headers = other_headers_from_request(request)
26
33
  end
27
34
 
28
35
  def assign_agent_attributes(txn)
@@ -31,14 +38,12 @@ module NewRelic
31
38
  AttributeFilter::DST_ERROR_COLLECTOR
32
39
 
33
40
  if referer
34
- txn.add_agent_attribute(:'request.headers.referer', referer, AttributeFilter::DST_ERROR_COLLECTOR)
41
+ destinations = allow_other_headers? ? default_destinations : AttributeFilter::DST_ERROR_COLLECTOR
42
+ txn.add_agent_attribute(:'request.headers.referer', referer, destinations)
35
43
  end
36
44
 
37
45
  if request_path
38
- txn.add_agent_attribute(:'request.uri',
39
- request_path,
40
- AttributeFilter::DST_TRANSACTION_TRACER |
41
- AttributeFilter::DST_ERROR_COLLECTOR)
46
+ txn.add_agent_attribute(:'request.uri', request_path, default_destinations)
42
47
  end
43
48
 
44
49
  if accept
@@ -64,6 +69,14 @@ module NewRelic
64
69
  if request_method
65
70
  txn.add_agent_attribute(:'request.method', request_method, default_destinations)
66
71
  end
72
+
73
+ if port && allow_other_headers?
74
+ txn.add_agent_attribute(:'request.headers.port', port, default_destinations)
75
+ end
76
+
77
+ other_headers.each do |header, value|
78
+ txn.add_agent_attribute(header, value, default_destinations)
79
+ end
67
80
  end
68
81
 
69
82
  private
@@ -85,12 +98,10 @@ module NewRelic
85
98
  # rails construct the PATH_INFO enviroment variable improperly and we're generally
86
99
  # being defensive.
87
100
 
88
- ROOT_PATH = '/'.freeze
89
-
90
101
  def path_from_request(request)
91
102
  path = attribute_from_request(request, :path) || ''
92
103
  path = HTTPClients::URIUtil.strip_query_string(path)
93
- path.empty? ? ROOT_PATH : path
104
+ path.empty? ? NewRelic::ROOT : path
94
105
  end
95
106
 
96
107
  def content_length_from_request(request)
@@ -111,11 +122,43 @@ module NewRelic
111
122
  end
112
123
  end
113
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
+
114
137
  def attribute_from_env(request, key)
115
138
  if env = attribute_from_request(request, :env)
116
139
  env[key]
117
140
  end
118
141
  end
142
+
143
+ def allow_other_headers?
144
+ NewRelic::Agent.config[:allow_all_headers] && !NewRelic::Agent.config[:high_security]
145
+ end
146
+
147
+ def other_headers_from_request(request)
148
+ # confirm that `request` is an instance of `Rack::Request` by checking
149
+ # for #each_header
150
+ return NewRelic::EMPTY_HASH unless allow_other_headers? && request.respond_to?(:each_header)
151
+
152
+ request.each_header.with_object({}) do |(header, value), hash|
153
+ next if BASE_HEADERS.include?(header)
154
+
155
+ hash[formatted_header(header)] = value
156
+ end
157
+ end
158
+
159
+ def formatted_header(raw_name)
160
+ "#{ATTRIBUTE_PREFIX}#{NewRelic::LanguageSupport.camelize_with_first_letter_downcased(raw_name)}".to_sym
161
+ end
119
162
  end
120
163
  end
121
164
  end
@@ -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)
@@ -22,20 +22,36 @@ 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
- @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.")
32
+
33
+ if finished?
34
+ ::NewRelic::Agent.logger.debug("Transaction #{best_name} has finished but segments still being created, resetting state.")
35
+ NewRelic::Agent::Tracer.state.reset
36
+ NewRelic::Agent.record_metric('Supportability/Transaction/SegmentLimitReachedAfterFinished/ResetState', 1)
37
+ end
32
38
  end
33
39
  segment.transaction_assigned
34
40
  end
35
41
 
42
+ def thread_starting_span
43
+ # if the previous current segment was in another thread, use the thread local parent
44
+ if ThreadLocalStorage[:newrelic_thread_span_parent] &&
45
+ current_segment &&
46
+ current_segment.starting_segment_key != NewRelic::Agent::Tracer.current_segment_key
47
+
48
+ ThreadLocalStorage[:newrelic_thread_span_parent]
49
+ end
50
+ end
51
+
36
52
  def segment_complete(segment)
37
53
  # if parent was in another thread, remove the current_segment entry for this thread
38
- 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
39
55
  remove_current_segment_by_thread_id(NewRelic::Agent::Tracer.current_segment_key)
40
56
  else
41
57
  set_current_segment(segment.parent)
@@ -49,7 +65,7 @@ module NewRelic
49
65
  private
50
66
 
51
67
  def finalize_segments
52
- segments.each { |s| s.finalize }
68
+ @segment_lock.synchronize { segments.each { |s| s&.finalize } }
53
69
  end
54
70
 
55
71
  WEB_TRANSACTION_TOTAL_TIME = 'WebTransactionTotalTime'.freeze
@@ -31,11 +31,12 @@ module NewRelic
31
31
  RAKE_PREFIX = "#{OTHER_TRANSACTION_PREFIX}Rake/"
32
32
  MESSAGE_PREFIX = "#{OTHER_TRANSACTION_PREFIX}Message/"
33
33
  RACK_PREFIX = "#{CONTROLLER_PREFIX}Rack/"
34
+ RODA_PREFIX = "#{CONTROLLER_PREFIX}Roda/"
34
35
  SINATRA_PREFIX = "#{CONTROLLER_PREFIX}Sinatra/"
35
36
  GRAPE_PREFIX = "#{CONTROLLER_PREFIX}Grape/"
36
37
  ACTION_CABLE_PREFIX = "#{CONTROLLER_PREFIX}ActionCable/"
37
38
 
38
- WEB_TRANSACTION_CATEGORIES = [:web, :controller, :uri, :rack, :sinatra, :grape, :middleware, :action_cable].freeze
39
+ WEB_TRANSACTION_CATEGORIES = %i[action_cable controller grape middleware rack roda sinatra web uri].freeze
39
40
 
40
41
  MIDDLEWARE_SUMMARY_METRICS = ['Middleware/all'].freeze
41
42
  WEB_SUMMARY_METRIC = 'HttpDispatcher'
@@ -89,7 +90,7 @@ module NewRelic
89
90
  attr_reader :transaction_trace
90
91
 
91
92
  # Fields for tracking synthetics requests
92
- attr_accessor :raw_synthetics_header, :synthetics_payload
93
+ attr_accessor :raw_synthetics_header, :synthetics_payload, :synthetics_info_payload, :raw_synthetics_info_header
93
94
 
94
95
  # Return the currently active transaction, or nil.
95
96
  def self.tl_current
@@ -214,6 +215,7 @@ module NewRelic
214
215
  @nesting_max_depth = 0
215
216
  @current_segment_by_thread = {}
216
217
  @current_segment_lock = Mutex.new
218
+ @segment_lock = Mutex.new
217
219
  @segments = []
218
220
 
219
221
  self.default_name = options[:transaction_name]
@@ -289,7 +291,7 @@ module NewRelic
289
291
  end
290
292
 
291
293
  def sampled?
292
- return unless Agent.config[:'distributed_tracing.enabled']
294
+ return false unless Agent.config[:'distributed_tracing.enabled']
293
295
 
294
296
  if @sampled.nil?
295
297
  @sampled = NewRelic::Agent.instance.adaptive_sampler.sampled?
@@ -436,7 +438,11 @@ module NewRelic
436
438
  end
437
439
 
438
440
  def initial_segment
439
- segments.first
441
+ segments&.first
442
+ end
443
+
444
+ def finished?
445
+ initial_segment&.finished?
440
446
  end
441
447
 
442
448
  def create_initial_segment(options = {})
@@ -515,7 +521,7 @@ module NewRelic
515
521
  end
516
522
 
517
523
  def finish
518
- return unless state.is_execution_traced?
524
+ return unless state.is_execution_traced? && initial_segment
519
525
 
520
526
  @end_time = Process.clock_gettime(Process::CLOCK_REALTIME)
521
527
  @duration = @end_time - @start_time
@@ -541,8 +547,8 @@ module NewRelic
541
547
  end
542
548
 
543
549
  def user_defined_rules_ignore?
544
- return unless request_path
545
- return if (rules = NewRelic::Agent.config[:"rules.ignore_url_regexes"]).empty?
550
+ return false unless request_path
551
+ return false if (rules = NewRelic::Agent.config[:"rules.ignore_url_regexes"]).empty?
546
552
 
547
553
  rules.any? do |rule|
548
554
  request_path.match(rule)
@@ -618,11 +624,24 @@ module NewRelic
618
624
  attributes.add_intrinsic_attribute(:synthetics_resource_id, synthetics_resource_id)
619
625
  attributes.add_intrinsic_attribute(:synthetics_job_id, synthetics_job_id)
620
626
  attributes.add_intrinsic_attribute(:synthetics_monitor_id, synthetics_monitor_id)
627
+ attributes.add_intrinsic_attribute(:synthetics_type, synthetics_info('type'))
628
+ attributes.add_intrinsic_attribute(:synthetics_initiator, synthetics_info('initiator'))
629
+
630
+ synthetics_additional_attributes do |key, value|
631
+ attributes.add_intrinsic_attribute(key, value)
632
+ end
621
633
  end
622
634
 
623
635
  distributed_tracer.assign_intrinsics
624
636
  end
625
637
 
638
+ def synthetics_additional_attributes(&block)
639
+ synthetics_info('attributes')&.each do |k, v|
640
+ new_key = "synthetics_#{NewRelic::LanguageSupport.snakeize(k.to_s)}".to_sym
641
+ yield(new_key, v.to_s)
642
+ end
643
+ end
644
+
626
645
  def calculate_gc_time
627
646
  gc_stop_snapshot = NewRelic::Agent::StatsEngine::GCProfiler.take_snapshot
628
647
  NewRelic::Agent::StatsEngine::GCProfiler.record_delta(gc_start_snapshot, gc_stop_snapshot)
@@ -702,6 +721,10 @@ module NewRelic
702
721
  info[4]
703
722
  end
704
723
 
724
+ def synthetics_info(key)
725
+ synthetics_info_payload[key] if synthetics_info_payload
726
+ end
727
+
705
728
  def append_apdex_perf_zone(payload)
706
729
  if recording_web_transaction?
707
730
  bucket = apdex_bucket(duration, apdex_t)
@@ -725,6 +748,12 @@ module NewRelic
725
748
  payload[:synthetics_resource_id] = synthetics_resource_id
726
749
  payload[:synthetics_job_id] = synthetics_job_id
727
750
  payload[:synthetics_monitor_id] = synthetics_monitor_id
751
+ payload[:synthetics_type] = synthetics_info('type')
752
+ payload[:synthetics_initiator] = synthetics_info('initiator')
753
+
754
+ synthetics_additional_attributes do |key, value|
755
+ payload[key] = value
756
+ end
728
757
  end
729
758
 
730
759
  def merge_metrics
@@ -788,13 +817,9 @@ module NewRelic
788
817
  end
789
818
 
790
819
  def had_error_affecting_apdex?
791
- @exceptions.each do |exception, options|
792
- ignored = NewRelic::Agent.instance.error_collector.error_is_ignored?(exception)
793
- expected = options[:expected]
794
-
795
- return true unless ignored || expected
820
+ @exceptions.each.any? do |exception, options|
821
+ NewRelic::Agent.instance.error_collector.error_affects_apdex?(exception, options)
796
822
  end
797
- false
798
823
  end
799
824
 
800
825
  def apdex_bucket(duration, current_apdex_t)
@@ -16,23 +16,29 @@ module NewRelic
16
16
  module TransactionErrorPrimitive
17
17
  extend self
18
18
 
19
- SAMPLE_TYPE = 'TransactionError'.freeze
20
- TYPE_KEY = 'type'.freeze
21
- ERROR_CLASS_KEY = 'error.class'.freeze
22
- ERROR_MESSAGE_KEY = 'error.message'.freeze
23
- ERROR_EXPECTED_KEY = 'error.expected'.freeze
24
- TIMESTAMP_KEY = 'timestamp'.freeze
25
- PORT_KEY = 'port'.freeze
26
- NAME_KEY = 'transactionName'.freeze
27
- DURATION_KEY = 'duration'.freeze
28
- SAMPLED_KEY = 'sampled'.freeze
29
- GUID_KEY = 'nr.transactionGuid'.freeze
30
- REFERRING_TRANSACTION_GUID_KEY = 'nr.referringTransactionGuid'.freeze
31
- SYNTHETICS_RESOURCE_ID_KEY = 'nr.syntheticsResourceId'.freeze
32
- SYNTHETICS_JOB_ID_KEY = 'nr.syntheticsJobId'.freeze
33
- SYNTHETICS_MONITOR_ID_KEY = 'nr.syntheticsMonitorId'.freeze
34
- PRIORITY_KEY = 'priority'.freeze
35
- SPAN_ID_KEY = 'spanId'.freeze
19
+ SAMPLE_TYPE = 'TransactionError'
20
+ TYPE_KEY = 'type'
21
+ ERROR_CLASS_KEY = 'error.class'
22
+ ERROR_MESSAGE_KEY = 'error.message'
23
+ ERROR_EXPECTED_KEY = 'error.expected'
24
+ TIMESTAMP_KEY = 'timestamp'
25
+ PORT_KEY = 'port'
26
+ NAME_KEY = 'transactionName'
27
+ DURATION_KEY = 'duration'
28
+ SAMPLED_KEY = 'sampled'
29
+ CAT_GUID_KEY = 'nr.transactionGuid'
30
+ CAT_REFERRING_TRANSACTION_GUID_KEY = 'nr.referringTransactionGuid'
31
+ SYNTHETICS_RESOURCE_ID_KEY = 'nr.syntheticsResourceId'
32
+ SYNTHETICS_JOB_ID_KEY = 'nr.syntheticsJobId'
33
+ SYNTHETICS_MONITOR_ID_KEY = 'nr.syntheticsMonitorId'
34
+ SYNTHETICS_TYPE_KEY = 'nr.syntheticsType'
35
+ SYNTHETICS_INITIATOR_KEY = 'nr.syntheticsInitiator'
36
+ SYNTHETICS_KEY_PREFIX = 'nr.synthetics'
37
+ PRIORITY_KEY = 'priority'
38
+ SPAN_ID_KEY = 'spanId'
39
+ GUID_KEY = 'guid'
40
+
41
+ SYNTHETICS_PAYLOAD_EXPECTED = [:synthetics_resource_id, :synthetics_job_id, :synthetics_monitor_id, :synthetics_type, :synthetics_initiator]
36
42
 
37
43
  def create(noticed_error, payload, span_id)
38
44
  [
@@ -52,7 +58,10 @@ module NewRelic
52
58
  }
53
59
 
54
60
  attrs[SPAN_ID_KEY] = span_id if span_id
61
+ # don't use safe navigation - leave off keys with missing values
62
+ # instead of using nil
55
63
  attrs[PORT_KEY] = noticed_error.request_port if noticed_error.request_port
64
+ attrs[GUID_KEY] = noticed_error.transaction_id if noticed_error.transaction_id
56
65
 
57
66
  if payload
58
67
  attrs[NAME_KEY] = payload[:name]
@@ -71,14 +80,25 @@ module NewRelic
71
80
  end
72
81
 
73
82
  def append_synthetics(payload, sample)
83
+ return unless payload[:synthetics_job_id]
84
+
74
85
  sample[SYNTHETICS_RESOURCE_ID_KEY] = payload[:synthetics_resource_id] if payload[:synthetics_resource_id]
75
86
  sample[SYNTHETICS_JOB_ID_KEY] = payload[:synthetics_job_id] if payload[:synthetics_job_id]
76
87
  sample[SYNTHETICS_MONITOR_ID_KEY] = payload[:synthetics_monitor_id] if payload[:synthetics_monitor_id]
88
+ sample[SYNTHETICS_TYPE_KEY] = payload[:synthetics_type] if payload[:synthetics_type]
89
+ sample[SYNTHETICS_INITIATOR_KEY] = payload[:synthetics_initiator] if payload[:synthetics_initiator]
90
+
91
+ payload.each do |k, v|
92
+ next unless k.to_s.start_with?('synthetics_') && !SYNTHETICS_PAYLOAD_EXPECTED.include?(k)
93
+
94
+ new_key = SYNTHETICS_KEY_PREFIX + NewRelic::LanguageSupport.camelize(k.to_s.gsub('synthetics_', ''))
95
+ sample[new_key] = v
96
+ end
77
97
  end
78
98
 
79
99
  def append_cat(payload, sample)
80
- sample[GUID_KEY] = payload[:guid] if payload[:guid]
81
- sample[REFERRING_TRANSACTION_GUID_KEY] = payload[:referring_transaction_guid] if payload[:referring_transaction_guid]
100
+ sample[CAT_GUID_KEY] = payload[:guid] if payload[:guid]
101
+ sample[CAT_REFERRING_TRANSACTION_GUID_KEY] = payload[:referring_transaction_guid] if payload[:referring_transaction_guid]
82
102
  end
83
103
  end
84
104
  end
@@ -38,6 +38,11 @@ module NewRelic
38
38
  SYNTHETICS_RESOURCE_ID_KEY = 'nr.syntheticsResourceId'
39
39
  SYNTHETICS_JOB_ID_KEY = 'nr.syntheticsJobId'
40
40
  SYNTHETICS_MONITOR_ID_KEY = 'nr.syntheticsMonitorId'
41
+ SYNTHETICS_TYPE_KEY = 'nr.syntheticsType'
42
+ SYNTHETICS_INITIATOR_KEY = 'nr.syntheticsInitiator'
43
+ SYNTHETICS_KEY_PREFIX = 'nr.synthetics'
44
+
45
+ SYNTHETICS_PAYLOAD_EXPECTED = [:synthetics_resource_id, :synthetics_job_id, :synthetics_monitor_id, :synthetics_type, :synthetics_initiator]
41
46
 
42
47
  def create(payload)
43
48
  intrinsics = {
@@ -71,9 +76,23 @@ module NewRelic
71
76
  optionally_append(SYNTHETICS_RESOURCE_ID_KEY, :synthetics_resource_id, sample, payload)
72
77
  optionally_append(SYNTHETICS_JOB_ID_KEY, :synthetics_job_id, sample, payload)
73
78
  optionally_append(SYNTHETICS_MONITOR_ID_KEY, :synthetics_monitor_id, sample, payload)
79
+ optionally_append(SYNTHETICS_TYPE_KEY, :synthetics_type, sample, payload)
80
+ optionally_append(SYNTHETICS_INITIATOR_KEY, :synthetics_initiator, sample, payload)
81
+ append_synthetics_info_attributes(sample, payload)
74
82
  append_cat_alternate_path_hashes(sample, payload)
75
83
  end
76
84
 
85
+ def append_synthetics_info_attributes(sample, payload)
86
+ return unless payload.include?(:synthetics_job_id)
87
+
88
+ payload.each do |k, v|
89
+ next unless k.to_s.start_with?('synthetics_') && !SYNTHETICS_PAYLOAD_EXPECTED.include?(k)
90
+
91
+ new_key = SYNTHETICS_KEY_PREFIX + NewRelic::LanguageSupport.camelize(k.to_s.gsub('synthetics_', ''))
92
+ sample[new_key] = v.to_s
93
+ end
94
+ end
95
+
77
96
  def append_cat_alternate_path_hashes(sample, payload)
78
97
  if payload.include?(:cat_alternate_path_hashes)
79
98
  sample[CAT_ALTERNATE_PATH_HASHES_KEY] = payload[:cat_alternate_path_hashes].sort.join(COMMA)
@@ -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
@@ -24,10 +24,8 @@ module NewRelic
24
24
  body
25
25
  end
26
26
 
27
- SLASH = '/'.freeze
28
-
29
27
  def trim_leading(value)
30
- value.split(SLASH).last
28
+ value.split(NewRelic::SLASH).last
31
29
  end
32
30
  end
33
31
  end
@@ -75,14 +75,12 @@ module NewRelic
75
75
  processed_headers = headers
76
76
  raise if processed_headers.value?(:error)
77
77
 
78
- Timeout.timeout(1) do
79
- response = nil
80
- Net::HTTP.start(endpoint.host, endpoint.port) do |http|
81
- req = Net::HTTP::Get.new(endpoint, processed_headers)
82
- response = http.request(req)
83
- end
84
- response
78
+ response = nil
79
+ Net::HTTP.start(endpoint.host, endpoint.port, open_timeout: 1, read_timeout: 1) do |http|
80
+ req = Net::HTTP::Get.new(endpoint, processed_headers)
81
+ response = http.request(req)
85
82
  end
83
+ response
86
84
  rescue
87
85
  NewRelic::Agent.logger.debug("#{vendor_name} environment not detected")
88
86
  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)