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
@@ -19,7 +19,7 @@ module NewRelic
19
19
  def warn_for_yajl
20
20
  if defined?(::Yajl)
21
21
  require 'yajl/version'
22
- if Gem::Version.new(::Yajl::VERSION) < OK_YAJL_VERSION
22
+ if NewRelic::Helper.version_satisfied?(::Yajl::VERSION, '<', OK_YAJL_VERSION)
23
23
  ::NewRelic::Agent.logger.warn("Detected yajl-ruby version #{::Yajl::VERSION} which can cause segfaults with newrelic_rpm's thread profiling features. We strongly recommend you upgrade to the latest yajl-ruby version available.")
24
24
  end
25
25
  end
@@ -42,7 +42,7 @@ module NewRelic
42
42
  return nil
43
43
  end
44
44
 
45
- return_value(::JSON.load(data))
45
+ return_value(::JSON.parse(data))
46
46
  rescue => e
47
47
  ::NewRelic::Agent.logger.debug("#{e.class.name} : #{e.message} encountered loading collector response: #{data}")
48
48
  raise
@@ -3,7 +3,6 @@
3
3
  # frozen_string_literal: true
4
4
 
5
5
  require 'zlib'
6
- require 'timeout'
7
6
  require 'new_relic/agent/audit_logger'
8
7
  require 'new_relic/agent/new_relic_service/encoders'
9
8
  require 'new_relic/agent/new_relic_service/marshaller'
@@ -19,7 +18,13 @@ module NewRelic
19
18
 
20
19
  # These include Errno connection errors, and all indicate that the
21
20
  # underlying TCP connection may be in a bad state.
22
- CONNECTION_ERRORS = [Timeout::Error, EOFError, SystemCallError, SocketError].freeze
21
+ CONNECTION_ERRORS = [Net::OpenTimeout, Net::ReadTimeout, EOFError, SystemCallError, SocketError]
22
+ # TODO: MAJOR VERSION - Net::WriteTimeout wasn't defined until Ruby 2.6.
23
+ # Once support for Ruby 2.5 is dropped, we should simply include
24
+ # Net::WriteTimeout in the connection errors array directly instead
25
+ # of with a conditional
26
+ CONNECTION_ERRORS << Net::WriteTimeout if defined?(Net::WriteTimeout)
27
+ CONNECTION_ERRORS.freeze
23
28
 
24
29
  # The maximum number of times to attempt an HTTP request
25
30
  MAX_ATTEMPTS = 2
@@ -138,6 +143,9 @@ module NewRelic
138
143
  end
139
144
 
140
145
  def metric_data(stats_hash)
146
+ # let the serverless handler handle serialization
147
+ return NewRelic::Agent.agent.serverless_handler.metric_data(stats_hash) if NewRelic::Agent.agent.serverless?
148
+
141
149
  timeslice_start = stats_hash.started_at
142
150
  timeslice_end = stats_hash.harvested_at || Process.clock_gettime(Process::CLOCK_REALTIME)
143
151
  metric_data_array = build_metric_data_array(stats_hash)
@@ -149,6 +157,9 @@ module NewRelic
149
157
  end
150
158
 
151
159
  def error_data(unsent_errors)
160
+ # let the serverless handler handle serialization
161
+ return NewRelic::Agent.agent.serverless_handler.error_data(unsent_errors) if NewRelic::Agent.agent.serverless?
162
+
152
163
  invoke_remote(:error_data, [@agent_id, unsent_errors],
153
164
  :item_count => unsent_errors.size)
154
165
  end
@@ -319,13 +330,15 @@ module NewRelic
319
330
 
320
331
  def start_connection(conn)
321
332
  NewRelic::Agent.logger.debug("Opening TCP connection to #{conn.address}:#{conn.port}")
322
- Timeout.timeout(@request_timeout) { conn.start }
323
- conn
333
+ conn.start
324
334
  end
325
335
 
326
336
  def setup_connection_timeouts(conn)
327
- # We use Timeout explicitly instead of this
328
- conn.read_timeout = nil
337
+ conn.open_timeout = @request_timeout
338
+ conn.read_timeout = @request_timeout
339
+ # TODO: MAJOR VERSION - #write_timeout= requires Ruby 2.6+, so remove
340
+ # the conditional check once support for Ruby 2.5 is dropped
341
+ conn.write_timeout = @request_timeout if conn.respond_to?(:write_timeout=)
329
342
 
330
343
  if conn.respond_to?(:keep_alive_timeout) && NewRelic::Agent.config[:aggressive_keepalive]
331
344
  conn.keep_alive_timeout = NewRelic::Agent.config[:keep_alive_timeout]
@@ -362,8 +375,8 @@ module NewRelic
362
375
  conn = create_http_connection
363
376
  start_connection(conn)
364
377
  conn
365
- rescue Timeout::Error
366
- ::NewRelic::Agent.logger.info('Timeout while attempting to connect. You may need to install system-level CA Certificates, as the ruby agent no longer includes these.')
378
+ rescue Net::OpenTimeout
379
+ ::NewRelic::Agent.logger.info('Timed out while attempting to connect. For SSL issues, you may need to install system-level CA Certificates to be used by Net::HTTP.')
367
380
  raise
368
381
  end
369
382
 
@@ -407,7 +420,7 @@ module NewRelic
407
420
  else
408
421
  request = Net::HTTP::Post.new(opts[:uri], headers)
409
422
  end
410
- @audit_logger.log_request_headers(opts[:uri], headers)
423
+ @audit_logger.log_request_headers(filtered_uri(opts[:uri]), headers)
411
424
  request['user-agent'] = user_agent
412
425
  request.content_type = 'application/octet-stream'
413
426
  request.body = opts[:data]
@@ -424,7 +437,7 @@ module NewRelic
424
437
  rescue *CONNECTION_ERRORS => e
425
438
  close_shared_connection
426
439
  if attempts < MAX_ATTEMPTS
427
- ::NewRelic::Agent.logger.debug("Retrying request to #{opts[:collector]}#{opts[:uri]} after #{e}")
440
+ ::NewRelic::Agent.logger.debug("Retrying request to #{opts[:collector]}#{filtered_uri(opts[:uri])} after #{e}")
428
441
  retry
429
442
  else
430
443
  raise ServerConnectionException, "Recoverable error talking to #{@collector} after #{attempts} attempts: #{e}"
@@ -436,21 +449,21 @@ module NewRelic
436
449
  end
437
450
 
438
451
  def attempt_request(request, opts)
439
- response = nil
440
452
  conn = http_connection
441
- ::NewRelic::Agent.logger.debug("Sending request to #{opts[:collector]}#{opts[:uri]} with #{request.method}")
442
- Timeout.timeout(@request_timeout) do
443
- response = conn.request(request)
444
- end
445
- response
453
+ ::NewRelic::Agent.logger.debug("Sending request to #{opts[:collector]}#{filtered_uri(opts[:uri])} with #{request.method}")
454
+ conn.request(request)
446
455
  end
447
456
 
448
457
  def handle_error_response(response, endpoint)
458
+ NewRelic::Agent.agent&.health_check&.update_status(NewRelic::Agent::HealthCheck::HTTP_ERROR, [response.code, endpoint])
459
+
449
460
  case response
450
461
  when Net::HTTPRequestTimeOut,
451
462
  Net::HTTPTooManyRequests,
452
463
  Net::HTTPInternalServerError,
453
- Net::HTTPServiceUnavailable
464
+ Net::HTTPServiceUnavailable,
465
+ Net::OpenTimeout,
466
+ Net::ReadTimeout
454
467
  handle_server_connection_exception(response, endpoint)
455
468
  when Net::HTTPBadRequest,
456
469
  Net::HTTPForbidden,
@@ -462,7 +475,6 @@ module NewRelic
462
475
  Net::HTTPRequestURITooLong,
463
476
  Net::HTTPUnsupportedMediaType,
464
477
  Net::HTTPExpectationFailed,
465
- Net::HTTPUnsupportedMediaType,
466
478
  Net::HTTPRequestHeaderFieldsTooLarge
467
479
  handle_unrecoverable_server_exception(response, endpoint)
468
480
  when Net::HTTPConflict,
@@ -472,9 +484,20 @@ module NewRelic
472
484
  when Net::HTTPGone
473
485
  handle_gone_response(response, endpoint)
474
486
  else
475
- record_endpoint_attempts_supportability_metrics(endpoint)
476
- record_error_response_supportability_metrics(response.code)
477
- raise UnrecoverableServerException, "#{response.code}: #{response.message}"
487
+ # TODO: MAJOR VERSION - Net::WriteTimeout wasn't defined until
488
+ # Ruby 2.6, so it can't be included in the case statement
489
+ # as a constant and instead needs to be found here. Once
490
+ # support for Ruby 2.5 is dropped, we should have
491
+ # Net::WriteTimeout sit in the 'when' clause above alongside
492
+ # Net::OpenTimeout and Net::ReadTimeout and this entire if/else
493
+ # conditional can be removed.
494
+ if response.respond_to?(:name) && response.name == 'Net::WriteTimeout'
495
+ handle_server_connection_exception(response, endpoint)
496
+ else
497
+ record_endpoint_attempts_supportability_metrics(endpoint)
498
+ record_error_response_supportability_metrics(response.code)
499
+ raise UnrecoverableServerException, "#{response.code}: #{response.message}"
500
+ end
478
501
  end
479
502
  response
480
503
  end
@@ -539,6 +562,8 @@ module NewRelic
539
562
  # enough to be worth compressing, and handles any errors the
540
563
  # server may return
541
564
  def invoke_remote(method, payload = [], options = {})
565
+ return NewRelic::Agent.agent.serverless_handler.store_payload(method, payload) if NewRelic::Agent.agent.serverless?
566
+
542
567
  start_ts = Process.clock_gettime(Process::CLOCK_MONOTONIC)
543
568
  request_send_ts, response_check_ts = nil
544
569
  data, encoding, size, serialize_finish_ts = marshal_payload(method, payload, options)
@@ -546,8 +571,10 @@ module NewRelic
546
571
  response, request_send_ts, response_check_ts = invoke_remote_send_request(method, payload, data, encoding)
547
572
  @marshaller.load(decompress_response(response))
548
573
  ensure
549
- record_timing_supportability_metrics(method, start_ts, serialize_finish_ts, request_send_ts, response_check_ts)
550
- record_size_supportability_metrics(method, size, options[:item_count]) if size
574
+ unless NewRelic::Agent.agent.serverless?
575
+ record_timing_supportability_metrics(method, start_ts, serialize_finish_ts, request_send_ts, response_check_ts)
576
+ record_size_supportability_metrics(method, size, options[:item_count]) if size
577
+ end
551
578
  end
552
579
 
553
580
  def handle_serialization_error(method, e)
@@ -612,9 +639,13 @@ module NewRelic
612
639
  def send_request(opts)
613
640
  request = prep_request(opts)
614
641
  response = relay_request(request, opts)
615
- return response if response.is_a?(Net::HTTPSuccess) || response.is_a?(Net::HTTPAccepted)
616
642
 
617
- handle_error_response(response, opts[:endpoint])
643
+ if response.is_a?(Net::HTTPSuccess) || response.is_a?(Net::HTTPAccepted)
644
+ NewRelic::Agent.agent&.health_check&.update_status(NewRelic::Agent::HealthCheck::HEALTHY)
645
+ response
646
+ else
647
+ handle_error_response(response, opts[:endpoint])
648
+ end
618
649
  end
619
650
 
620
651
  def log_response(response)
@@ -674,9 +705,7 @@ module NewRelic
674
705
 
675
706
  def invoke_remote_send_request(method, payload, data, encoding)
676
707
  uri = remote_method_uri(method)
677
- full_uri = "#{@collector}#{uri}"
678
-
679
- @audit_logger.log_request(full_uri, payload, @marshaller)
708
+ @audit_logger.log_request("#{@collector}#{filtered_uri(uri)}", payload, @marshaller)
680
709
  request_send_ts = Process.clock_gettime(Process::CLOCK_MONOTONIC)
681
710
  response = send_request(:data => data,
682
711
  :uri => uri,
@@ -685,6 +714,10 @@ module NewRelic
685
714
  :endpoint => method)
686
715
  [response, request_send_ts, Process.clock_gettime(Process::CLOCK_MONOTONIC)]
687
716
  end
717
+
718
+ def filtered_uri(uri)
719
+ uri.gsub(license_key, ASTERISK * license_key.size)
720
+ end
688
721
  end
689
722
  end
690
723
  end
@@ -2,8 +2,6 @@
2
2
  # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
3
  # frozen_string_literal: true
4
4
 
5
- # require 'base64'
6
-
7
5
  module NewRelic
8
6
  module Agent
9
7
  class Obfuscator
@@ -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
6
+ module Agent
7
+ module OpenTelemetry
8
+ module Context
9
+ module Propagation
10
+ class TracePropagator
11
+ # The carrier is the object carrying the headers
12
+ # The context argument is a no-op, as the OpenTelemetry context is not used
13
+ # The setter argument is a no-op, added for consistency with the OpenTelemetry API
14
+ def inject(carrier, context: ::OpenTelemetry::Context.current, setter: nil)
15
+ # TODO: determine if we need to update this method to take Context into account
16
+ NewRelic::Agent::DistributedTracing.insert_distributed_trace_headers(carrier)
17
+ end
18
+
19
+ # The return value for this method should be an instance of the
20
+ # OpenTelemetry Context class. The return value of
21
+ # #accept_distributed_trace_headers is a transaction, so we cannot
22
+ # use it to extract the context.
23
+ def extract(carrier, context: ::OpenTelemetry::Context.current, getter: ::OpenTelemetry::Context::Propagation.text_map_getter)
24
+ carrier_format = determine_format(getter)
25
+ trace_context = NewRelic::Agent::DistributedTracing::TraceContext.parse(
26
+ carrier: carrier,
27
+ format: carrier_format,
28
+ trace_state_entry_key: Transaction::TraceContext::AccountHelpers.trace_state_entry_key
29
+ )
30
+ tp = trace_context.trace_parent
31
+ span_context = ::OpenTelemetry::Trace::SpanContext.new(
32
+ trace_id: tp['trace_id'],
33
+ span_id: tp['parent_id'],
34
+ trace_flags: tp['trace_flags'],
35
+ tracestate: trace_context.trace_state_payload,
36
+ remote: true
37
+ )
38
+ span = ::OpenTelemetry::Trace.non_recording_span(span_context)
39
+
40
+ ::OpenTelemetry::Trace.context_with_span(span, parent_context: context)
41
+ rescue StandardError => e
42
+ NewRelic::Agent.logger.error("Unable to extract context: #{e.message}")
43
+ context
44
+ end
45
+
46
+ private
47
+
48
+ # The getter is the way OpenTelemetry handles Rack vs. non-Rack
49
+ # formats. Rather than using their parser, get the class info we
50
+ # need to do things the New Relic way
51
+ def determine_format(getter)
52
+ case getter
53
+ when ::OpenTelemetry::Context::Propagation::RackEnvGetter
54
+ FORMAT_RACK
55
+ when defined?(::OpenTelemetry::Common) && ::OpenTelemetry::Common::Propagation::RackEnvGetter
56
+ FORMAT_RACK
57
+ else
58
+ FORMAT_NON_RACK
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,15 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ module NewRelic
6
+ module Agent
7
+ module OpenTelemetry
8
+ module Context
9
+ module Propagation
10
+ require_relative 'propagation/trace_propagator'
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -2,8 +2,12 @@
2
2
  # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
3
  # frozen_string_literal: true
4
4
 
5
- instrumentation_methods :chain, :prepend
6
-
7
- gemfile <<~RB
8
- gem '<%= @name.downcase %>'
9
- RB
5
+ module NewRelic
6
+ module Agent
7
+ module OpenTelemetry
8
+ module Context
9
+ require_relative 'context/propagation'
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,31 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ module NewRelic
6
+ module Agent
7
+ module OpenTelemetry
8
+ module Trace
9
+ class Span < ::OpenTelemetry::Trace::Span
10
+ attr_accessor :finishable
11
+
12
+ def finish(end_timestamp: nil)
13
+ finishable&.finish
14
+ end
15
+
16
+ def set_attribute(key, value)
17
+ NewRelic::Agent.add_custom_span_attributes(key => value)
18
+ end
19
+
20
+ def add_attributes(attributes)
21
+ NewRelic::Agent.add_custom_span_attributes(attributes)
22
+ end
23
+
24
+ def record_exception(exception, attributes: nil)
25
+ NewRelic::Agent.notice_error(exception, attributes: attributes)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,129 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ module NewRelic
6
+ module Agent
7
+ module OpenTelemetry
8
+ module Trace
9
+ class Tracer < ::OpenTelemetry::Trace::Tracer
10
+ def initialize(name = nil, version = nil)
11
+ @name = name || ''
12
+ @version = version || ''
13
+ end
14
+
15
+ def start_span(name, with_parent: nil, attributes: nil, links: nil, start_timestamp: nil, kind: nil)
16
+ parent_otel_context = ::OpenTelemetry::Trace.current_span(with_parent).context
17
+
18
+ finishable = if can_start_transaction?(parent_otel_context)
19
+ return if internal_span_kind_with_invalid_parent?(kind, parent_otel_context)
20
+
21
+ nr_item = NewRelic::Agent::Tracer.start_transaction_or_segment(name: name, category: :otel)
22
+ add_remote_context_to_txn(nr_item, parent_otel_context)
23
+ nr_item
24
+ else
25
+ NewRelic::Agent::Tracer.start_segment(name: name)
26
+ end
27
+
28
+ otel_span = get_otel_span_from_finishable(finishable)
29
+ otel_span.finishable = finishable
30
+ add_remote_context_to_otel_span(otel_span, parent_otel_context)
31
+ otel_span.add_attributes(attributes) if attributes
32
+ otel_span
33
+ end
34
+
35
+ def in_span(name, attributes: nil, links: nil, start_timestamp: nil, kind: nil)
36
+ span = start_span(name, attributes: attributes, links: links, start_timestamp: start_timestamp, kind: kind)
37
+ begin
38
+ yield
39
+ rescue => e
40
+ # TODO: Update for segment errors if finishable is a segment
41
+ NewRelic::Agent.notice_error(e)
42
+ raise
43
+ end
44
+ ensure
45
+ span&.finish
46
+ end
47
+
48
+ private
49
+
50
+ def get_otel_span_from_finishable(finishable)
51
+ case finishable
52
+ when NewRelic::Agent::Transaction
53
+ finishable.segments.first.instance_variable_get(:@otel_span)
54
+ when NewRelic::Agent::Transaction::Segment
55
+ finishable.instance_variable_get(:@otel_span)
56
+ else
57
+ NewRelic::Agent.logger.warn('Tracer#get_otel_span_from_finishable failed to get span from finishable - finishable is not a transaction or segment')
58
+ nil
59
+ end
60
+ end
61
+
62
+ def can_start_transaction?(parent_otel_context)
63
+ parent_otel_context.remote? || !parent_otel_context.valid?
64
+ end
65
+
66
+ def internal_span_kind_with_invalid_parent?(kind, parent_otel_context)
67
+ !parent_otel_context.valid? && kind == :internal
68
+ end
69
+
70
+ def transaction_and_remote_parent?(txn, parent_otel_context)
71
+ txn.is_a?(NewRelic::Agent::Transaction) && parent_otel_context.remote?
72
+ end
73
+
74
+ def add_remote_context_to_txn(txn, parent_otel_context)
75
+ return unless transaction_and_remote_parent?(txn, parent_otel_context)
76
+
77
+ txn.trace_id = parent_otel_context.trace_id
78
+ txn.parent_span_id = parent_otel_context.span_id
79
+
80
+ set_tracestate(txn.distributed_tracer, parent_otel_context)
81
+ end
82
+
83
+ def set_tracestate(distributed_tracer, otel_context)
84
+ case otel_context.tracestate
85
+ when ::OpenTelemetry::Trace::Tracestate
86
+ set_otel_trace_state(distributed_tracer, otel_context)
87
+ when NewRelic::Agent::TraceContextPayload
88
+ set_nr_trace_state(distributed_tracer, otel_context)
89
+ end
90
+ end
91
+
92
+ def set_nr_trace_state(distributed_tracer, otel_context)
93
+ distributed_tracer.instance_variable_set(:@trace_state_payload, otel_context.tracestate)
94
+ distributed_tracer.parent_transaction_id = distributed_tracer.trace_state_payload.transaction_id
95
+ distributed_tracer.determine_sampling_decision(otel_context.tracestate, otel_context.trace_flags)
96
+ end
97
+
98
+ def set_otel_trace_state(distributed_tracer, otel_context)
99
+ nr_entry = otel_context.tracestate.value(Transaction::TraceContext::AccountHelpers.trace_state_entry_key)
100
+ return unless nr_entry
101
+
102
+ nr_payload = NewRelic::Agent::TraceContextPayload.from_s(nr_entry)
103
+ distributed_tracer.instance_variable_set(:@trace_state_payload, nr_payload)
104
+ distributed_tracer.parent_transaction_id = distributed_tracer.trace_state_payload.transaction_id
105
+ trace_flags = parse_trace_flags(otel_context.trace_flags)
106
+ distributed_tracer.determine_sampling_decision(nr_payload, trace_flags)
107
+ end
108
+
109
+ def parse_trace_flags(trace_flags)
110
+ case trace_flags
111
+ when String
112
+ trace_flags
113
+ when Integer
114
+ trace_flags.to_s
115
+ when ::OpenTelemetry::Trace::TraceFlags
116
+ trace_flags.sampled? ? '01' : '00'
117
+ end
118
+ end
119
+
120
+ def add_remote_context_to_otel_span(otel_span, parent_otel_context)
121
+ return unless transaction_and_remote_parent?(otel_span.finishable, parent_otel_context)
122
+
123
+ otel_span.context.instance_variable_set(:@trace_id, otel_span.finishable.trace_id)
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,18 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ module NewRelic
6
+ module Agent
7
+ module OpenTelemetry
8
+ module Trace
9
+ class TracerProvider < ::OpenTelemetry::Trace::TracerProvider
10
+ # TODO: Add a registration mechanism for tracers like exists in the SDK
11
+ def tracer(name = nil, version = nil)
12
+ @tracer ||= Tracer.new(name, version)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,15 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ module NewRelic
6
+ module Agent
7
+ module OpenTelemetry
8
+ module Trace
9
+ require_relative 'trace/tracer_provider'
10
+ require_relative 'trace/tracer'
11
+ require_relative 'trace/span'
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,69 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ module NewRelic
6
+ module Agent
7
+ module OpenTelemetry
8
+ module TransactionPatch
9
+ attr_accessor :opentelemetry_context
10
+
11
+ def initialize(_category, _options)
12
+ @opentelemetry_context = {}
13
+ super
14
+ end
15
+
16
+ def set_current_segment(new_segment)
17
+ @current_segment_lock.synchronize do
18
+ unless opentelemetry_context.empty?
19
+ ::OpenTelemetry::Context.detach(opentelemetry_context[otel_current_span_key])
20
+ end
21
+
22
+ span = find_or_create_span(new_segment)
23
+ ctx = ::OpenTelemetry::Context.current.set_value(otel_current_span_key, span)
24
+ token = ::OpenTelemetry::Context.attach(ctx)
25
+
26
+ opentelemetry_context[otel_current_span_key] = token
27
+ end
28
+
29
+ super
30
+ end
31
+
32
+ def remove_current_segment_by_thread_id(id)
33
+ # make sure the context is fully detached when the transaction ends
34
+ @current_segment_lock.synchronize do
35
+ ::OpenTelemetry::Context.detach(opentelemetry_context[otel_current_span_key])
36
+ opentelemetry_context.delete(id)
37
+ end
38
+
39
+ super
40
+ end
41
+
42
+ private
43
+
44
+ def find_or_create_span(segment)
45
+ if segment.instance_variable_defined?(:@otel_span)
46
+ segment.instance_variable_get(:@otel_span)
47
+ else
48
+ span = Trace::Span.new(span_context: span_context_from_segment(segment))
49
+ segment.instance_variable_set(:@otel_span, span)
50
+ span
51
+ end
52
+ end
53
+
54
+ def span_context_from_segment(segment)
55
+ ::OpenTelemetry::Trace::SpanContext.new(
56
+ trace_id: segment.transaction.trace_id,
57
+ span_id: segment.guid,
58
+ remote: false
59
+ )
60
+ end
61
+
62
+ def otel_current_span_key
63
+ # CURRENT_SPAN_KEY is a private constant
64
+ ::OpenTelemetry::Trace.const_get(:CURRENT_SPAN_KEY)
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,32 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ module NewRelic
6
+ module Agent
7
+ class OpenTelemetryBridge
8
+ def initialize
9
+ # no-op without OpenTelemetry API & config
10
+ return unless defined?(OpenTelemetry) &&
11
+ NewRelic::Agent.config[:'opentelemetry_bridge.enabled']
12
+
13
+ OpenTelemetryBridge.install
14
+ end
15
+
16
+ private
17
+
18
+ def self.install
19
+ require 'opentelemetry' # requires the opentelemetry-api gem
20
+ require_relative 'opentelemetry/trace'
21
+ require_relative 'opentelemetry/transaction_patch'
22
+ require_relative 'opentelemetry/context'
23
+
24
+ # TODO: Add a warning if SDK gem is installed
25
+
26
+ ::OpenTelemetry.tracer_provider = OpenTelemetry::Trace::TracerProvider.new
27
+ Transaction.prepend(OpenTelemetry::TransactionPatch)
28
+ ::OpenTelemetry.propagation = OpenTelemetry::Context::Propagation::TracePropagator.new
29
+ end
30
+ end
31
+ end
32
+ end
@@ -9,7 +9,7 @@ module NewRelic
9
9
 
10
10
  ACTION_DISPATCH_PARAMETER_FILTER ||= 'action_dispatch.parameter_filter'.freeze
11
11
 
12
- if defined?(Rails) && Gem::Version.new(::Rails::VERSION::STRING) >= Gem::Version.new('5.0.0')
12
+ if defined?(Rails) && NewRelic::Helper.version_satisfied?(::Rails::VERSION::STRING, '>=', '5.0.0')
13
13
  Rails.application.config.to_prepare do
14
14
  RAILS_FILTER_CLASS ||= if defined?(ActiveSupport::ParameterFilter)
15
15
  ActiveSupport::ParameterFilter
@@ -2,7 +2,7 @@
2
2
  # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
3
  # frozen_string_literal: true
4
4
 
5
- require 'base64'
5
+ require 'new_relic/base64'
6
6
 
7
7
  module NewRelic
8
8
  module Agent
@@ -257,7 +257,7 @@ module NewRelic
257
257
  Marshal.load(data)
258
258
  rescue StandardError => e
259
259
  ::NewRelic::Agent.logger.error('Failure unmarshalling message from Resque child process', e)
260
- ::NewRelic::Agent.logger.debug(Base64.encode64(data))
260
+ ::NewRelic::Agent.logger.debug(NewRelic::Base64.encode64(data))
261
261
  nil
262
262
  end
263
263