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
@@ -5,8 +5,8 @@
5
5
  # NOTE: there are multiple implementations of the Memcached client in Ruby,
6
6
  # each with slightly different APIs and semantics.
7
7
  # See:
8
- # http://www.deveiate.org/code/Ruby-MemCache/ (Gem: Ruby-MemCache)
9
- # http://seattlerb.rubyforge.org/memcache-client/ (Gem: memcache-client)
8
+ # https://rubygems.org/gems/Ruby-MemCache (Gem: Ruby-MemCache)
9
+ # https://github.com/mperham/memcache-client (Gem: memcache-client)
10
10
  # https://github.com/mperham/dalli (Gem: dalli)
11
11
 
12
12
  require_relative 'memcache/helper'
@@ -58,7 +58,7 @@ DependencyDetection.defer do
58
58
  prepend_instrument client_class, instrumenting_module, 'MemcachedDalli'
59
59
  end
60
60
  else
61
- chain_instrument NewRelic::Agent::Instrumentation::Memcache::Dalli
61
+ chain_instrument NewRelic::Agent::Instrumentation::Memcache::Dalli, 'MemcachedDalli'
62
62
  end
63
63
  end
64
64
  end
@@ -74,14 +74,13 @@ DependencyDetection.defer do
74
74
  depends_on { NewRelic::Agent::Instrumentation::Memcache::DalliCAS.should_instrument? }
75
75
 
76
76
  executes do
77
- NewRelic::Agent.logger.info('Installing Dalli CAS Client Memcache instrumentation')
78
77
  if use_prepend?
79
78
  prepend_module = NewRelic::Agent::Instrumentation::Memcache::Prepend
80
79
  prepend_module.dalli_cas_prependers do |client_class, instrumenting_module|
81
80
  prepend_instrument client_class, instrumenting_module, 'MemcachedDalliCAS'
82
81
  end
83
82
  else
84
- chain_instrument NewRelic::Agent::Instrumentation::Memcache::DalliCAS
83
+ chain_instrument NewRelic::Agent::Instrumentation::Memcache::DalliCAS, 'MemcachedDalliCAS'
85
84
  end
86
85
  end
87
86
  end
@@ -21,7 +21,7 @@ module NewRelic
21
21
  end
22
22
  end
23
23
 
24
- ERROR_KEYS = %w[ writeErrors writeConcernError writeConcernErrors ].freeze
24
+ ERROR_KEYS = %w[writeErrors writeConcernError writeConcernErrors].freeze
25
25
 
26
26
  def error_key_present?(event)
27
27
  if reply = event.reply
@@ -106,7 +106,7 @@ module NewRelic
106
106
  )
107
107
  end
108
108
 
109
- UNKNOWN = 'unknown'.freeze
109
+ UNKNOWN = NewRelic::UNKNOWN_LOWER
110
110
  LOCALHOST = 'localhost'.freeze
111
111
 
112
112
  def host_from_address(address)
@@ -131,10 +131,8 @@ module NewRelic
131
131
  UNKNOWN
132
132
  end
133
133
 
134
- SLASH = '/'.freeze
135
-
136
134
  def unix_domain_socket?(host)
137
- host.start_with?(SLASH)
135
+ host.start_with?(NewRelic::SLASH)
138
136
  end
139
137
  end
140
138
  end
@@ -6,7 +6,11 @@ module NewRelic
6
6
  module Agent
7
7
  module Instrumentation
8
8
  module NetHTTP
9
+ INSTRUMENTATION_NAME = NewRelic::Agent.base_name(name)
10
+
9
11
  def request_with_tracing(request)
12
+ NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)
13
+
10
14
  wrapped_request = NewRelic::Agent::HTTPClients::NetHTTPRequest.new(self, request)
11
15
 
12
16
  segment = NewRelic::Agent::Tracer.start_external_request_segment(
@@ -17,7 +21,7 @@ module NewRelic
17
21
 
18
22
  begin
19
23
  response = nil
20
- segment.add_request_headers(wrapped_request)
24
+ segment&.add_request_headers(wrapped_request)
21
25
 
22
26
  # RUBY-1244 Disable further tracing in request to avoid double
23
27
  # counting if connection wasn't started (which calls request again).
@@ -28,10 +32,16 @@ module NewRelic
28
32
  end
29
33
 
30
34
  wrapped_response = NewRelic::Agent::HTTPClients::NetHTTPResponse.new(response)
31
- segment.process_response_headers(wrapped_response)
35
+
36
+ if NewRelic::Agent::LLM.openai_parent?(segment)
37
+ NewRelic::Agent::LLM.populate_openai_response_headers(wrapped_response, segment&.parent)
38
+ end
39
+
40
+ segment&.process_response_headers(wrapped_response)
41
+
32
42
  response
33
43
  ensure
34
- segment.finish
44
+ segment&.finish
35
45
  end
36
46
  end
37
47
  end
@@ -19,7 +19,8 @@ DependencyDetection.defer do
19
19
 
20
20
  # Airbrake uses method chaining on Net::HTTP in versions < 10.0.2 (10.0.2 updated to prepend for Net:HTTP)
21
21
  conflicts_with_prepend do
22
- defined?(Airbrake) && defined?(Airbrake::AIRBRAKE_VERSION) && Gem::Version.create(Airbrake::AIRBRAKE_VERSION) < Gem::Version.create('10.0.2')
22
+ defined?(Airbrake) && defined?(Airbrake::AIRBRAKE_VERSION) &&
23
+ NewRelic::Helper.version_satisfied?(Airbrake::AIRBRAKE_VERSION, '<', '10.0.2')
23
24
  end
24
25
 
25
26
  conflicts_with_prepend do
@@ -16,8 +16,6 @@ module NewRelic
16
16
  end
17
17
 
18
18
  def self.find_all_subscribers
19
- # TODO: need to talk to Rails core about an API for this,
20
- # rather than digging through Listener ivars
21
19
  instance_variable_names = [:@subscribers, :@string_subscribers, :@other_subscribers]
22
20
  all_subscribers = []
23
21
 
@@ -47,6 +45,10 @@ module NewRelic
47
45
  end
48
46
  end
49
47
 
48
+ # The agent doesn't use the traditional ActiveSupport::Notifications.subscribe
49
+ # pattern due to threading issues discovered on initial instrumentation.
50
+ # Instead we define a #start and #finish method, which Rails responds to.
51
+ # See: https://github.com/rails/rails/issues/12069
50
52
  def start(name, id, payload)
51
53
  return unless state.is_execution_traced?
52
54
 
@@ -0,0 +1,21 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ module NewRelic::Agent::Instrumentation
6
+ module OpenSearch::Chain
7
+ def self.instrument!
8
+ ::OpenSearch::Transport::Client.class_eval do
9
+ include NewRelic::Agent::Instrumentation::OpenSearch
10
+
11
+ alias_method(:perform_request_without_tracing, :perform_request)
12
+
13
+ def perform_request(*args)
14
+ perform_request_with_tracing(*args) do
15
+ perform_request_without_tracing(*args)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,66 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ module NewRelic::Agent::Instrumentation
6
+ module OpenSearch
7
+ PRODUCT_NAME = 'OpenSearch'
8
+ OPERATION = 'perform_request'
9
+ OPERATION_PATTERN = %r{/lib/opensearch/api/(?!.+#{OPERATION})}
10
+ INSTANCE_METHOD_PATTERN = /:in (?:`|')(?:.+#)?([^']+)'\z/
11
+ INSTRUMENTATION_NAME = NewRelic::Agent.base_name(name)
12
+
13
+ def perform_request_with_tracing(_method, _path, params = NewRelic::EMPTY_HASH, body = nil, _headers = nil, _opts = nil, &_block)
14
+ return yield unless NewRelic::Agent::Tracer.tracing_enabled?
15
+
16
+ segment = NewRelic::Agent::Tracer.start_datastore_segment(
17
+ product: PRODUCT_NAME,
18
+ operation: nr_operation || OPERATION,
19
+ host: nr_hosts[:host],
20
+ port_path_or_id: nr_hosts[:port],
21
+ database_name: nr_cluster_name
22
+ )
23
+ begin
24
+ NewRelic::Agent::Tracer.capture_segment_error(segment) { yield }
25
+ ensure
26
+ if segment
27
+ segment.notice_nosql_statement(nr_reported_query(body || params))
28
+ segment.finish
29
+ end
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ # See Elasticsearch instrumentation for explanation on Ruby 3.4 changes to match instance method
36
+ def nr_operation
37
+ location = caller_locations.detect { |loc| loc.to_s.match?(OPERATION_PATTERN) }
38
+ return unless location && location.to_s =~ INSTANCE_METHOD_PATTERN
39
+
40
+ Regexp.last_match(1)
41
+ end
42
+
43
+ def nr_reported_query(query)
44
+ return unless NewRelic::Agent.config[:'opensearch.capture_queries']
45
+ return query unless NewRelic::Agent.config[:'opensearch.obfuscate_queries']
46
+
47
+ NewRelic::Agent::Datastores::NosqlObfuscator.obfuscate_statement(query)
48
+ end
49
+
50
+ def nr_cluster_name
51
+ return @nr_cluster_name if defined?(@nr_cluster_name)
52
+ return if nr_hosts.empty?
53
+
54
+ NewRelic::Agent.disable_all_tracing do
55
+ @nr_cluster_name ||= perform_request('GET', '/').body['cluster_name']
56
+ end
57
+ rescue StandardError => e
58
+ NewRelic::Agent.logger.error('Failed to get cluster name for OpenSearch', e)
59
+ nil
60
+ end
61
+
62
+ def nr_hosts
63
+ @nr_hosts ||= (transport.hosts.first || NewRelic::EMPTY_HASH)
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,13 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ module NewRelic::Agent::Instrumentation
6
+ module OpenSearch::Prepend
7
+ include NewRelic::Agent::Instrumentation::OpenSearch
8
+
9
+ def perform_request(*args)
10
+ perform_request_with_tracing(*args) { super }
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,23 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ require_relative 'opensearch/instrumentation'
6
+ require_relative 'opensearch/chain'
7
+ require_relative 'opensearch/prepend'
8
+
9
+ DependencyDetection.defer do
10
+ named :opensearch
11
+
12
+ depends_on do
13
+ defined?(OpenSearch)
14
+ end
15
+
16
+ executes do
17
+ if use_prepend?
18
+ prepend_instrument OpenSearch::Transport::Client, NewRelic::Agent::Instrumentation::OpenSearch::Prepend
19
+ else
20
+ chain_instrument NewRelic::Agent::Instrumentation::OpenSearch::Chain
21
+ end
22
+ end
23
+ end
@@ -4,7 +4,11 @@
4
4
 
5
5
  module NewRelic::Agent::Instrumentation
6
6
  module Padrino
7
+ INSTRUMENTATION_NAME = NewRelic::Agent.base_name(name)
8
+
7
9
  def invoke_route_with_tracing(*args)
10
+ NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)
11
+
8
12
  begin
9
13
  env['newrelic.last_route'] = args[0].original_path
10
14
  rescue => e
@@ -22,11 +22,11 @@ DependencyDetection.defer do
22
22
  depends_on { defined?(Padrino) && defined?(Padrino::Routing::InstanceMethods) }
23
23
 
24
24
  executes do
25
- NewRelic::Agent.logger.info('Installing Padrino instrumentation')
25
+ supportability_name = NewRelic::Agent::Instrumentation::Padrino::INSTRUMENTATION_NAME
26
26
  if use_prepend?
27
- prepend_instrument Padrino::Application, NewRelic::Agent::Instrumentation::PadrinoTracer::Prepend
27
+ prepend_instrument Padrino::Application, NewRelic::Agent::Instrumentation::PadrinoTracer::Prepend, supportability_name
28
28
  else
29
- chain_instrument NewRelic::Agent::Instrumentation::PadrinoTracer::Chain
29
+ chain_instrument NewRelic::Agent::Instrumentation::PadrinoTracer::Chain, supportability_name
30
30
  end
31
31
  end
32
32
  end
@@ -5,7 +5,7 @@
5
5
  module NewRelic
6
6
  module Agent
7
7
  module Instrumentation
8
- # https://newrelic.com/docs/features/tracking-front-end-time
8
+ # https://docs.newrelic.com/docs/features/tracking-front-end-time
9
9
  # Record queue time metrics based on any of three headers
10
10
  # which can be set on the request.
11
11
  module QueueTime
@@ -6,11 +6,14 @@ module NewRelic
6
6
  module Agent
7
7
  module Instrumentation
8
8
  module RackBuilder
9
+ INSTRUMENTATION_NAME = 'Rack'
10
+
9
11
  def self.track_deferred_detection(builder_class)
10
12
  class << builder_class
11
13
  attr_accessor :_nr_deferred_detection_ran
12
14
  end
13
15
  builder_class._nr_deferred_detection_ran = false
16
+ NewRelic::Control::SecurityInterface.instance.wait = true
14
17
  end
15
18
 
16
19
  def deferred_dependency_check
@@ -19,6 +22,8 @@ module NewRelic
19
22
  NewRelic::Agent.logger.info('Doing deferred dependency-detection before Rack startup')
20
23
  DependencyDetection.detect!
21
24
  self.class._nr_deferred_detection_ran = true
25
+ NewRelic::Control::SecurityInterface.instance.wait = false
26
+ NewRelic::Control::SecurityInterface.instance.init_agent
22
27
  end
23
28
 
24
29
  def check_for_late_instrumentation(app)
@@ -51,6 +56,8 @@ module NewRelic
51
56
  def run_with_tracing(app)
52
57
  return yield(app) unless middleware_instrumentation_enabled?
53
58
 
59
+ NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)
60
+
54
61
  yield(::NewRelic::Agent::Instrumentation::MiddlewareProxy.wrap(app, true))
55
62
  end
56
63
 
@@ -58,6 +65,8 @@ module NewRelic
58
65
  return if middleware_class.nil?
59
66
  return yield(middleware_class) unless middleware_instrumentation_enabled?
60
67
 
68
+ NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)
69
+
61
70
  yield(::NewRelic::Agent::Instrumentation::MiddlewareProxy.for_class(middleware_class))
62
71
  end
63
72
  end
@@ -9,6 +9,8 @@ module NewRelic
9
9
  module Instrumentation
10
10
  module Rails3
11
11
  module ActionController
12
+ INSTRUMENTATION_NAME = NewRelic::Agent.base_name(name)
13
+
12
14
  # determine the path that is used in the metric name for
13
15
  # the called controller action
14
16
  def newrelic_metric_path(action_name_override = nil)
@@ -21,6 +23,8 @@ module NewRelic
21
23
  end
22
24
 
23
25
  def process_action(*args) # THREAD_LOCAL_ACCESS
26
+ NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)
27
+
24
28
  munged_params = NewRelic::Agent::ParameterFiltering.filter_rails_request_parameters(request.filtered_parameters)
25
29
  perform_action_with_newrelic_trace(:category => :controller,
26
30
  :name => self.action_name,
@@ -25,7 +25,7 @@ DependencyDetection.defer do
25
25
 
26
26
  executes do
27
27
  # enumerate the specific events we want so that we do not get unexpected additions in the future
28
- ActiveSupport::Notifications.subscribe(/\A(?:perform_action|transmit|broadcast)\.action_cable\z/,
28
+ ActiveSupport::Notifications.subscribe(/\A(?:perform_action|transmit.*|broadcast)\.action_cable\z/,
29
29
  NewRelic::Agent::Instrumentation::ActionCableSubscriber.new)
30
30
 
31
31
  ActiveSupport.on_load(:action_cable) do
@@ -32,14 +32,19 @@ DependencyDetection.defer do
32
32
  NewRelic::Agent::Instrumentation::ActionControllerSubscriber \
33
33
  .subscribe(/^process_action.action_controller$/)
34
34
 
35
- subs = %w[send_file
36
- send_data
37
- redirect_to
35
+ subs = %w[exist_fragment?
36
+ expire_fragment
38
37
  halted_callback
39
- unpermitted_parameters]
38
+ read_fragment
39
+ redirect_to
40
+ send_data
41
+ send_file
42
+ send_stream
43
+ write_fragment
44
+ unpermitted_parameters].map { |s| Regexp.escape(s) }
40
45
 
41
46
  # have to double escape period because its going from string -> regex
42
47
  NewRelic::Agent::Instrumentation::ActionControllerOtherSubscriber \
43
- .subscribe(Regexp.new("^(#{subs.join('|')})\\.action_controller$"))
48
+ .subscribe(Regexp.new("^(?:#{subs.join('|')})\\.action_controller$"))
44
49
  end
45
50
  end
@@ -7,11 +7,15 @@ module NewRelic
7
7
  module Instrumentation
8
8
  module Rake
9
9
  module Tracer
10
+ INSTRUMENTATION_NAME = 'Rake'
11
+
10
12
  def invoke_with_newrelic_tracing(*args)
11
13
  unless NewRelic::Agent::Instrumentation::Rake.should_trace?(name)
12
14
  return yield
13
15
  end
14
16
 
17
+ NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)
18
+
15
19
  begin
16
20
  timeout = NewRelic::Agent.config[:'rake.connect_timeout']
17
21
  NewRelic::Agent.instance.wait_on_connect(timeout)
@@ -12,12 +12,11 @@ DependencyDetection.defer do
12
12
  configure_with :rake
13
13
 
14
14
  depends_on { defined?(Rake) && defined?(Rake::VERSION) }
15
- depends_on { Gem::Version.new(Rake::VERSION) >= Gem::Version.new('10.0.0') }
15
+ depends_on { NewRelic::Helper.version_satisfied?(Rake::VERSION, '>=', '10.0.0') }
16
16
  depends_on { NewRelic::Agent.config[:'rake.tasks'].any? }
17
17
  depends_on { NewRelic::Agent::Instrumentation::Rake.safe_from_third_party_gem? }
18
18
 
19
19
  executes do
20
- NewRelic::Agent.logger.info('Installing Rake instrumentation')
21
20
  NewRelic::Agent.logger.debug("Instrumenting Rake tasks: #{NewRelic::Agent.config[:'rake.tasks']}")
22
21
  end
23
22
 
@@ -0,0 +1,72 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ require_relative 'instrumentation'
6
+
7
+ module NewRelic::Agent::Instrumentation
8
+ module Rdkafka::Chain
9
+ def self.instrument!
10
+ ::Rdkafka::Producer.class_eval do
11
+ include NewRelic::Agent::Instrumentation::Rdkafka
12
+
13
+ alias_method(:produce_without_new_relic, :produce)
14
+
15
+ def produce(**kwargs)
16
+ produce_with_new_relic(kwargs) do |headers|
17
+ kwargs[:headers] = headers
18
+ produce_without_new_relic(**kwargs)
19
+ end
20
+ end
21
+ end
22
+
23
+ ::Rdkafka::Consumer.class_eval do
24
+ include NewRelic::Agent::Instrumentation::Rdkafka
25
+
26
+ alias_method(:each_without_new_relic, :each)
27
+
28
+ def each(**kwargs)
29
+ each_without_new_relic(**kwargs) do |message|
30
+ each_with_new_relic(message) do
31
+ yield(message)
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ ::Rdkafka::Config.class_eval do
38
+ include NewRelic::Agent::Instrumentation::RdkafkaConfig
39
+
40
+ alias_method(:producer_without_new_relic, :producer)
41
+ alias_method(:consumer_without_new_relic, :consumer)
42
+
43
+ if NewRelic::Helper.version_satisfied?(::Rdkafka::VERSION, '>=', '0.16.0') ||
44
+ NewRelic::Helper.version_satisfied?(RUBY_VERSION, '>=', '2.7.0')
45
+ def producer(**kwargs)
46
+ producer_without_new_relic(**kwargs).tap do |producer|
47
+ set_nr_config(producer)
48
+ end
49
+ end
50
+
51
+ def consumer(**kwargs)
52
+ consumer_without_new_relic(**kwargs).tap do |consumer|
53
+ set_nr_config(consumer)
54
+ end
55
+ end
56
+ else
57
+ def producer
58
+ producer_without_new_relic.tap do |producer|
59
+ set_nr_config(producer)
60
+ end
61
+ end
62
+
63
+ def consumer
64
+ consumer_without_new_relic.tap do |consumer|
65
+ set_nr_config(consumer)
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,70 @@
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/messaging'
6
+
7
+ module NewRelic::Agent::Instrumentation
8
+ module Rdkafka
9
+ MESSAGING_LIBRARY = 'Kafka'
10
+ PRODUCE = 'Produce'
11
+ CONSUME = 'Consume'
12
+
13
+ INSTRUMENTATION_NAME = 'Rdkafka'
14
+
15
+ def produce_with_new_relic(*args)
16
+ NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)
17
+
18
+ topic_name = args[0][:topic]
19
+ segment = NewRelic::Agent::Tracer.start_message_broker_segment(
20
+ action: :produce,
21
+ library: MESSAGING_LIBRARY,
22
+ destination_type: :topic,
23
+ destination_name: topic_name
24
+ )
25
+ create_kafka_metrics(action: PRODUCE, topic: topic_name)
26
+
27
+ headers = args[0][:headers] || {}
28
+ ::NewRelic::Agent::DistributedTracing.insert_distributed_trace_headers(headers)
29
+
30
+ NewRelic::Agent::Tracer.capture_segment_error(segment) { yield(headers) }
31
+ ensure
32
+ segment&.finish
33
+ end
34
+
35
+ def each_with_new_relic(message)
36
+ NewRelic::Agent.record_instrumentation_invocation(INSTRUMENTATION_NAME)
37
+
38
+ headers = message&.headers || {}
39
+ topic_name = message&.topic
40
+
41
+ NewRelic::Agent::Messaging.wrap_message_broker_consume_transaction(
42
+ library: MESSAGING_LIBRARY,
43
+ destination_type: :topic,
44
+ destination_name: topic_name,
45
+ headers: headers,
46
+ action: :consume
47
+ ) do
48
+ create_kafka_metrics(action: CONSUME, topic: topic_name)
49
+ yield
50
+ end
51
+ end
52
+
53
+ def create_kafka_metrics(action:, topic:)
54
+ hosts = []
55
+ # both 'bootstrap.servers' and 'metadata.broker.list' are valid ways to specify the Kafka server
56
+ hosts << @nr_config[:'bootstrap.servers'] if @nr_config[:'bootstrap.servers']
57
+ hosts << @nr_config[:'metadata.broker.list'] if @nr_config[:'metadata.broker.list']
58
+ hosts.each do |host|
59
+ NewRelic::Agent.record_metric("MessageBroker/Kafka/Nodes/#{host}/#{action}/#{topic}", 1)
60
+ NewRelic::Agent.record_metric("MessageBroker/Kafka/Nodes/#{host}", 1)
61
+ end
62
+ end
63
+ end
64
+
65
+ module RdkafkaConfig
66
+ def set_nr_config(producer_or_consumer)
67
+ producer_or_consumer.instance_variable_set(:@nr_config, self)
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,67 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ require_relative 'instrumentation'
6
+
7
+ module NewRelic::Agent::Instrumentation
8
+ module RdkafkaProducer
9
+ module Prepend
10
+ include NewRelic::Agent::Instrumentation::Rdkafka
11
+
12
+ def produce(**kwargs)
13
+ produce_with_new_relic(kwargs) do |headers|
14
+ kwargs[:headers] = headers
15
+ super
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ module RdkafkaConsumer
22
+ module Prepend
23
+ include NewRelic::Agent::Instrumentation::Rdkafka
24
+
25
+ def each
26
+ super do |message|
27
+ each_with_new_relic(message) do
28
+ yield(message)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ module RdkafkaConfig
36
+ module Prepend
37
+ include NewRelic::Agent::Instrumentation::RdkafkaConfig
38
+
39
+ if (defined?(::Rdkafka) && NewRelic::Helper.version_satisfied?(::Rdkafka::VERSION, '>=', '0.16.0')) ||
40
+ NewRelic::Helper.version_satisfied?(RUBY_VERSION, '>=', '2.7.0')
41
+ def producer(**kwargs)
42
+ super.tap do |producer|
43
+ set_nr_config(producer)
44
+ end
45
+ end
46
+
47
+ def consumer(**kwargs)
48
+ super.tap do |consumer|
49
+ set_nr_config(consumer)
50
+ end
51
+ end
52
+ else # older versions
53
+ def producer
54
+ super.tap do |producer|
55
+ set_nr_config(producer)
56
+ end
57
+ end
58
+
59
+ def consumer
60
+ super.tap do |consumer|
61
+ set_nr_config(consumer)
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,25 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ DependencyDetection.defer do
6
+ named :rdkafka
7
+
8
+ depends_on do
9
+ defined?(Rdkafka)
10
+ end
11
+
12
+ executes do
13
+ require_relative 'rdkafka/instrumentation'
14
+ require_relative 'rdkafka/chain'
15
+ require_relative 'rdkafka/prepend'
16
+
17
+ if use_prepend?
18
+ prepend_instrument Rdkafka::Config, NewRelic::Agent::Instrumentation::RdkafkaConfig::Prepend
19
+ prepend_instrument Rdkafka::Producer, NewRelic::Agent::Instrumentation::RdkafkaProducer::Prepend
20
+ prepend_instrument Rdkafka::Consumer, NewRelic::Agent::Instrumentation::RdkafkaConsumer::Prepend
21
+ else
22
+ chain_instrument NewRelic::Agent::Instrumentation::Rdkafka::Chain
23
+ end
24
+ end
25
+ end