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
@@ -4,6 +4,7 @@
4
4
 
5
5
  require 'new_relic/agent/event_aggregator'
6
6
  require 'new_relic/agent/log_priority'
7
+ require 'new_relic/agent/log_event_attributes'
7
8
 
8
9
  module NewRelic
9
10
  module Agent
@@ -19,10 +20,12 @@ module NewRelic
19
20
  DROPPED_METRIC = 'Logging/Forwarding/Dropped'.freeze
20
21
  SEEN_METRIC = 'Supportability/Logging/Forwarding/Seen'.freeze
21
22
  SENT_METRIC = 'Supportability/Logging/Forwarding/Sent'.freeze
22
- OVERALL_SUPPORTABILITY_FORMAT = 'Supportability/Logging/Ruby/Logger/%s'.freeze
23
+ LOGGER_SUPPORTABILITY_FORMAT = 'Supportability/Logging/Ruby/Logger/%s'.freeze
24
+ LOGSTASHER_SUPPORTABILITY_FORMAT = 'Supportability/Logging/Ruby/LogStasher/%s'.freeze
23
25
  METRICS_SUPPORTABILITY_FORMAT = 'Supportability/Logging/Metrics/Ruby/%s'.freeze
24
26
  FORWARDING_SUPPORTABILITY_FORMAT = 'Supportability/Logging/Forwarding/Ruby/%s'.freeze
25
27
  DECORATING_SUPPORTABILITY_FORMAT = 'Supportability/Logging/LocalDecorating/Ruby/%s'.freeze
28
+ LABELS_SUPPORTABILITY_FORMAT = 'Supportability/Logging/Labels/Ruby/%s'.freeze
26
29
  MAX_BYTES = 32768 # 32 * 1024 bytes (32 kibibytes)
27
30
 
28
31
  named :LogEventAggregator
@@ -36,6 +39,11 @@ module NewRelic
36
39
  METRICS_ENABLED_KEY = :'application_logging.metrics.enabled'
37
40
  FORWARDING_ENABLED_KEY = :'application_logging.forwarding.enabled'
38
41
  DECORATING_ENABLED_KEY = :'application_logging.local_decorating.enabled'
42
+ LABELS_ENABLED_KEY = :'application_logging.forwarding.labels.enabled'
43
+ LOG_LEVEL_KEY = :'application_logging.forwarding.log_level'
44
+ CUSTOM_ATTRIBUTES_KEY = :'application_logging.forwarding.custom_attributes'
45
+
46
+ attr_reader :attributes
39
47
 
40
48
  def initialize(events)
41
49
  super(events)
@@ -44,6 +52,8 @@ module NewRelic
44
52
  @seen_by_severity = Hash.new(0)
45
53
  @high_security = NewRelic::Agent.config[:high_security]
46
54
  @instrumentation_logger_enabled = NewRelic::Agent::Instrumentation::Logger.enabled?
55
+ @attributes = NewRelic::Agent::LogEventAttributes.new
56
+
47
57
  register_for_done_configuring(events)
48
58
  end
49
59
 
@@ -52,37 +62,71 @@ module NewRelic
52
62
  end
53
63
 
54
64
  def record(formatted_message, severity)
55
- return unless enabled?
65
+ return unless logger_enabled?
56
66
 
57
67
  severity = 'UNKNOWN' if severity.nil? || severity.empty?
68
+ increment_event_counters(severity)
69
+
70
+ return if formatted_message.nil? || formatted_message.empty?
71
+ return unless monitoring_conditions_met?(severity)
72
+
73
+ txn = NewRelic::Agent::Transaction.tl_current
74
+ priority = LogPriority.priority_for(txn)
75
+
76
+ return txn.add_log_event(create_event(priority, formatted_message, severity)) if txn
58
77
 
59
- if NewRelic::Agent.config[METRICS_ENABLED_KEY]
60
- @counter_lock.synchronize do
61
- @seen += 1
62
- @seen_by_severity[severity] += 1
78
+ @lock.synchronize do
79
+ @buffer.append(priority: priority) do
80
+ create_event(priority, formatted_message, severity)
63
81
  end
64
82
  end
83
+ rescue
84
+ nil
85
+ end
65
86
 
66
- return if formatted_message.nil? || formatted_message.empty?
67
- return unless NewRelic::Agent.config[:'application_logging.forwarding.enabled']
68
- return if @high_security
87
+ def record_logstasher_event(log)
88
+ return unless logstasher_enabled?
89
+
90
+ # LogStasher logs do not inherently include a message key, so most logs are recorded.
91
+ # But when the key exists, we should not record the log if the message value is nil or empty.
92
+ return if log.key?('message') && (log['message'].nil? || log['message'].empty?)
93
+
94
+ severity = determine_severity(log)
95
+ increment_event_counters(severity)
96
+
97
+ return unless monitoring_conditions_met?(severity)
69
98
 
70
99
  txn = NewRelic::Agent::Transaction.tl_current
71
100
  priority = LogPriority.priority_for(txn)
72
101
 
73
- if txn
74
- return txn.add_log_event(create_event(priority, formatted_message, severity))
75
- else
76
- return @lock.synchronize do
77
- @buffer.append(priority: priority) do
78
- create_event(priority, formatted_message, severity)
79
- end
102
+ return txn.add_log_event(create_logstasher_event(priority, severity, log)) if txn
103
+
104
+ @lock.synchronize do
105
+ @buffer.append(priority: priority) do
106
+ create_logstasher_event(priority, severity, log)
80
107
  end
81
108
  end
82
109
  rescue
83
110
  nil
84
111
  end
85
112
 
113
+ def monitoring_conditions_met?(severity)
114
+ !severity_too_low?(severity) && NewRelic::Agent.config[FORWARDING_ENABLED_KEY] && !@high_security
115
+ end
116
+
117
+ def determine_severity(log)
118
+ log['level'] ? log['level'].to_s.upcase : 'UNKNOWN'
119
+ end
120
+
121
+ def increment_event_counters(severity)
122
+ return unless NewRelic::Agent.config[METRICS_ENABLED_KEY]
123
+
124
+ @counter_lock.synchronize do
125
+ @seen += 1
126
+ @seen_by_severity[severity] += 1
127
+ end
128
+ end
129
+
86
130
  def record_batch(txn, logs)
87
131
  # Ensure we have the same shared priority
88
132
  priority = LogPriority.priority_for(txn)
@@ -97,15 +141,17 @@ module NewRelic
97
141
  end
98
142
  end
99
143
 
100
- def create_event(priority, formatted_message, severity)
101
- formatted_message = truncate_message(formatted_message)
102
-
103
- event = LinkingMetadata.append_trace_linking_metadata({
144
+ def add_event_metadata(formatted_message, severity)
145
+ metadata = {
104
146
  LEVEL_KEY => severity,
105
- MESSAGE_KEY => formatted_message,
106
147
  TIMESTAMP_KEY => Process.clock_gettime(Process::CLOCK_REALTIME) * 1000
107
- })
148
+ }
149
+ metadata[MESSAGE_KEY] = formatted_message unless formatted_message.nil?
150
+
151
+ LinkingMetadata.append_trace_linking_metadata(metadata)
152
+ end
108
153
 
154
+ def create_prioritized_event(priority, event)
109
155
  [
110
156
  {
111
157
  PrioritySampledBuffer::PRIORITY_KEY => priority
@@ -114,6 +160,39 @@ module NewRelic
114
160
  ]
115
161
  end
116
162
 
163
+ def create_event(priority, formatted_message, severity)
164
+ formatted_message = truncate_message(formatted_message)
165
+ event = add_event_metadata(formatted_message, severity)
166
+
167
+ create_prioritized_event(priority, event)
168
+ end
169
+
170
+ def create_logstasher_event(priority, severity, log)
171
+ formatted_message = log['message'] ? truncate_message(log['message']) : nil
172
+ event = add_event_metadata(formatted_message, severity)
173
+ add_logstasher_event_attributes(event, log)
174
+
175
+ create_prioritized_event(priority, event)
176
+ end
177
+
178
+ def add_logstasher_event_attributes(event, log)
179
+ log_copy = log.dup
180
+ # Delete previously reported attributes
181
+ log_copy.delete('message')
182
+ log_copy.delete('level')
183
+ log_copy.delete('@timestamp')
184
+
185
+ event['attributes'] = log_copy
186
+ end
187
+
188
+ def add_custom_attributes(custom_attributes)
189
+ attributes.add_custom_attributes(custom_attributes)
190
+ end
191
+
192
+ def labels
193
+ @labels ||= create_labels
194
+ end
195
+
117
196
  # Because our transmission format (MELT) is different than historical
118
197
  # agent payloads, extract the munging here to keep the service focused
119
198
  # on the general harvest + transmit instead of the format.
@@ -129,6 +208,9 @@ module NewRelic
129
208
  # To save on unnecessary data transmission, trim the entity.type
130
209
  # sent by classic logs-in-context
131
210
  common_attributes.delete(ENTITY_TYPE_KEY)
211
+ aggregator = NewRelic::Agent.agent.log_event_aggregator
212
+ common_attributes.merge!(aggregator.attributes.custom_attributes)
213
+ common_attributes.merge!(aggregator.labels)
132
214
 
133
215
  _, items = data
134
216
  payload = [{
@@ -149,13 +231,18 @@ module NewRelic
149
231
  @seen = 0
150
232
  @seen_by_severity.clear
151
233
  end
234
+
152
235
  super
153
236
  end
154
237
 
155
- def enabled?
238
+ def logger_enabled?
156
239
  @enabled && @instrumentation_logger_enabled
157
240
  end
158
241
 
242
+ def logstasher_enabled?
243
+ @enabled && NewRelic::Agent::Instrumentation::LogStasher.enabled?
244
+ end
245
+
159
246
  private
160
247
 
161
248
  # We record once-per-connect metrics for enabled/disabled state at the
@@ -163,11 +250,14 @@ module NewRelic
163
250
  def register_for_done_configuring(events)
164
251
  events.subscribe(:server_source_configuration_added) do
165
252
  @high_security = NewRelic::Agent.config[:high_security]
166
-
167
- record_configuration_metric(OVERALL_SUPPORTABILITY_FORMAT, OVERALL_ENABLED_KEY)
253
+ record_configuration_metric(LOGGER_SUPPORTABILITY_FORMAT, OVERALL_ENABLED_KEY)
254
+ record_configuration_metric(LOGSTASHER_SUPPORTABILITY_FORMAT, OVERALL_ENABLED_KEY)
168
255
  record_configuration_metric(METRICS_SUPPORTABILITY_FORMAT, METRICS_ENABLED_KEY)
169
256
  record_configuration_metric(FORWARDING_SUPPORTABILITY_FORMAT, FORWARDING_ENABLED_KEY)
170
257
  record_configuration_metric(DECORATING_SUPPORTABILITY_FORMAT, DECORATING_ENABLED_KEY)
258
+ record_configuration_metric(LABELS_SUPPORTABILITY_FORMAT, LABELS_ENABLED_KEY)
259
+
260
+ add_custom_attributes(NewRelic::Agent.config[CUSTOM_ATTRIBUTES_KEY])
171
261
  end
172
262
  end
173
263
 
@@ -191,7 +281,7 @@ module NewRelic
191
281
  # these until harvest before recording them
192
282
  def record_customer_metrics
193
283
  return unless enabled?
194
- return unless NewRelic::Agent.config[:'application_logging.metrics.enabled']
284
+ return unless NewRelic::Agent.config[METRICS_ENABLED_KEY]
195
285
 
196
286
  @counter_lock.synchronize do
197
287
  return unless @seen > 0
@@ -230,6 +320,39 @@ module NewRelic
230
320
 
231
321
  message.byteslice(0...MAX_BYTES)
232
322
  end
323
+
324
+ def configured_log_level_constant
325
+ format_log_level_constant(NewRelic::Agent.config[LOG_LEVEL_KEY])
326
+ end
327
+
328
+ def format_log_level_constant(log_level)
329
+ log_level.upcase.to_sym
330
+ end
331
+
332
+ def severity_too_low?(severity)
333
+ severity_constant = format_log_level_constant(severity)
334
+ # always record custom log levels
335
+ return false unless Logger::Severity.constants.include?(severity_constant)
336
+
337
+ Logger::Severity.const_get(severity_constant) < Logger::Severity.const_get(configured_log_level_constant)
338
+ end
339
+
340
+ def create_labels
341
+ return NewRelic::EMPTY_HASH unless NewRelic::Agent.config[LABELS_ENABLED_KEY]
342
+
343
+ downcased_exclusions = NewRelic::Agent.config[:'application_logging.forwarding.labels.exclude'].map(&:downcase)
344
+ log_labels = {}
345
+
346
+ NewRelic::Agent.config.parsed_labels.each do |parsed_label|
347
+ next if downcased_exclusions.include?(parsed_label['label_type'].downcase)
348
+
349
+ # labels are referred to as tags in the UI, so prefix the
350
+ # label-related attributes with 'tags.*'
351
+ log_labels["tags.#{parsed_label['label_type']}"] = parsed_label['label_value']
352
+ end
353
+
354
+ log_labels
355
+ end
233
356
  end
234
357
  end
235
358
  end
@@ -0,0 +1,115 @@
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 LogEventAttributes
8
+ MAX_ATTRIBUTE_COUNT = 240 # limit is 255, assume we send 15
9
+ ATTRIBUTE_KEY_CHARACTER_LIMIT = 255
10
+ ATTRIBUTE_VALUE_CHARACTER_LIMIT = 4094
11
+
12
+ def add_custom_attributes(attributes)
13
+ return if defined?(@custom_attribute_limit_reached) && @custom_attribute_limit_reached
14
+
15
+ attributes.each do |key, value|
16
+ next if absent?(key) || absent?(value)
17
+
18
+ add_custom_attribute(key, value)
19
+ end
20
+ end
21
+
22
+ def custom_attributes
23
+ @custom_attributes ||= {}
24
+ end
25
+
26
+ private
27
+
28
+ class TruncationError < StandardError
29
+ attr_reader :attribute, :limit
30
+
31
+ def initialize(attribute, limit, msg = "Can't truncate")
32
+ @attribute = attribute
33
+ @limit = limit
34
+ super(msg)
35
+ end
36
+ end
37
+
38
+ class InvalidTypeError < StandardError
39
+ attr_reader :attribute
40
+
41
+ def initialize(attribute, msg = 'Invalid attribute type')
42
+ @attribute = attribute
43
+ super(msg)
44
+ end
45
+ end
46
+
47
+ def absent?(value)
48
+ value.nil? || (value.respond_to?(:empty?) && value.empty?)
49
+ end
50
+
51
+ def add_custom_attribute(key, value)
52
+ if custom_attributes.size >= MAX_ATTRIBUTE_COUNT
53
+ NewRelic::Agent.logger.warn(
54
+ 'Too many custom log attributes defined. ' \
55
+ "Only taking the first #{MAX_ATTRIBUTE_COUNT}."
56
+ )
57
+ @custom_attribute_limit_reached = true
58
+ return
59
+ end
60
+
61
+ @custom_attributes.merge!(truncate_attributes(key_to_string(key), value))
62
+ end
63
+
64
+ def key_to_string(key)
65
+ key.is_a?(String) ? key : key.to_s
66
+ end
67
+
68
+ def truncate_attribute(attribute, limit)
69
+ case attribute
70
+ when Integer
71
+ if attribute.digits.length > limit
72
+ raise TruncationError.new(attribute, limit)
73
+ end
74
+ when Float
75
+ if attribute.to_s.length > limit
76
+ raise TruncationError.new(attribute, limit)
77
+ end
78
+ when String, Symbol
79
+ if attribute.length > limit
80
+ attribute = attribute.slice(0..(limit - 1))
81
+ end
82
+ when TrueClass, FalseClass
83
+ attribute
84
+ else
85
+ raise InvalidTypeError.new(attribute)
86
+ end
87
+
88
+ attribute
89
+ end
90
+
91
+ def truncate_attributes(key, value)
92
+ key = truncate_attribute(key, ATTRIBUTE_KEY_CHARACTER_LIMIT)
93
+ value = truncate_attribute(value, ATTRIBUTE_VALUE_CHARACTER_LIMIT)
94
+
95
+ {key => value}
96
+ rescue TruncationError => e
97
+ NewRelic::Agent.logger.warn(
98
+ "Dropping custom log attribute #{key} => #{value} \n" \
99
+ "Length exceeds character limit of #{e.limit}. " \
100
+ "Can't truncate: #{e.attribute}"
101
+ )
102
+
103
+ {}
104
+ rescue InvalidTypeError => e
105
+ NewRelic::Agent.logger.warn(
106
+ "Dropping custom log attribute #{key} => #{value} \n" \
107
+ "Invalid type of #{e.attribute.class} given. " \
108
+ "Can't send #{e.attribute}."
109
+ )
110
+
111
+ {}
112
+ end
113
+ end
114
+ end
115
+ end
@@ -62,6 +62,10 @@ module NewRelic
62
62
  message << CLOSING_BRACE << NEWLINE
63
63
  end
64
64
 
65
+ def clear_tags!
66
+ # No-op; just avoiding issues with act-fluent-logger-rails
67
+ end
68
+
65
69
  private
66
70
 
67
71
  def add_app_name(message)
@@ -138,10 +142,6 @@ module NewRelic
138
142
  end
139
143
  message.to_json
140
144
  end
141
-
142
- def clear_tags!
143
- # No-op; just avoiding issues with act-fluent-logger-rails
144
- end
145
145
  end
146
146
 
147
147
  # This logger decorates logs with trace and entity metadata, and emits log
@@ -165,7 +165,7 @@ module NewRelic
165
165
  # Positional and Keyword arguments are separated beginning with Ruby 2.7
166
166
  # Signature of ::Logger constructor changes in Ruby 2.4 to have both positional and keyword args
167
167
  # We pivot on Ruby 2.7 for widest supportability with least amount of hassle.
168
- if RUBY_VERSION < '2.7.0'
168
+ if NewRelic::Helper.version_satisfied?(RUBY_VERSION, '<', '2.7.0')
169
169
  def initialize(*args)
170
170
  super(*args)
171
171
  self.formatter = DecoratingFormatter.new
@@ -49,6 +49,7 @@ module NewRelic
49
49
  #
50
50
  # @return [NewRelic::Agent::Transaction::MessageBrokerSegment]
51
51
  #
52
+ # @!scope class
52
53
  # @api public
53
54
  #
54
55
  def start_message_broker_segment(action: nil,
@@ -107,6 +108,7 @@ module NewRelic
107
108
  # @return return value of given block, which will be the same as the
108
109
  # return value of an un-instrumented subscribed callback
109
110
  #
111
+ # @!scope class
110
112
  # @api public
111
113
  #
112
114
  def wrap_message_broker_consume_transaction(library:,
@@ -117,7 +119,8 @@ module NewRelic
117
119
  queue_name: nil,
118
120
  exchange_type: nil,
119
121
  reply_to: nil,
120
- correlation_id: nil)
122
+ correlation_id: nil,
123
+ action: nil)
121
124
 
122
125
  state = Tracer.state
123
126
  return yield if state.current_transaction
@@ -125,12 +128,12 @@ module NewRelic
125
128
  txn = nil
126
129
 
127
130
  begin
128
- txn_name = transaction_name(library, destination_type, destination_name)
131
+ txn_name = transaction_name(library, destination_type, destination_name, action)
129
132
 
130
133
  txn = Tracer.start_transaction(name: txn_name, category: :message)
131
-
132
134
  if headers
133
- txn.distributed_tracer.consume_message_headers(headers, state, RABBITMQ_TRANSPORT_TYPE)
135
+ NewRelic::Agent::DistributedTracing::accept_distributed_trace_headers(headers, library) # to handle the new w3c headers
136
+ txn.distributed_tracer.consume_message_headers(headers, state, library) # to do the expected old things
134
137
  CrossAppTracing.reject_messaging_cat_headers(headers).each do |k, v|
135
138
  txn.add_agent_attribute(:"message.headers.#{k}", v, AttributeFilter::DST_NONE) unless v.nil?
136
139
  end
@@ -179,6 +182,7 @@ module NewRelic
179
182
  #
180
183
  # @return [NewRelic::Agent::Transaction::MessageBrokerSegment]
181
184
  #
185
+ # @!scope class
182
186
  # @api public
183
187
  #
184
188
  def start_amqp_publish_segment(library:,
@@ -239,6 +243,7 @@ module NewRelic
239
243
  #
240
244
  # @return [NewRelic::Agent::Transaction::MessageBrokerSegment]
241
245
  #
246
+ # @!scope class
242
247
  # @api public
243
248
  #
244
249
  def start_amqp_consume_segment(library:,
@@ -300,6 +305,7 @@ module NewRelic
300
305
  # @return return value of given block, which will be the same as the
301
306
  # return value of an un-instrumented subscribed callback
302
307
  #
308
+ # @!scope class
303
309
  # @api public
304
310
  #
305
311
  def wrap_amqp_consume_transaction(library: nil,
@@ -327,11 +333,16 @@ module NewRelic
327
333
  NewRelic::Agent.config[:'message_tracer.segment_parameters.enabled']
328
334
  end
329
335
 
330
- def transaction_name(library, destination_type, destination_name)
336
+ def transaction_name(library, destination_type, destination_name, action = nil)
331
337
  transaction_name = Transaction::MESSAGE_PREFIX + library
332
- transaction_name << Transaction::MessageBrokerSegment::SLASH
338
+ transaction_name << NewRelic::SLASH
333
339
  transaction_name << Transaction::MessageBrokerSegment::TYPES[destination_type]
334
- transaction_name << Transaction::MessageBrokerSegment::SLASH
340
+ transaction_name << NewRelic::SLASH
341
+
342
+ if action == :consume
343
+ transaction_name << 'Consume'
344
+ transaction_name << NewRelic::SLASH
345
+ end
335
346
 
336
347
  case destination_type
337
348
  when :queue
@@ -65,6 +65,7 @@ module NewRelic
65
65
  # categories, but generally this *should never ever be done*. Most of the time you can aggregate
66
66
  # on the server.
67
67
  #
68
+ # @!scope class
68
69
  # @api public
69
70
  #
70
71
  def trace_execution_scoped(metric_names, options = NewRelic::EMPTY_HASH) # THREAD_LOCAL_ACCESS
@@ -81,6 +82,7 @@ module NewRelic
81
82
  #
82
83
  # * <tt>metric_names</tt> is a single name or an array of names of metrics
83
84
  #
85
+ # @!scope class
84
86
  # @api public
85
87
  #
86
88
  def trace_execution_unscoped(metric_names, options = NewRelic::EMPTY_HASH) # THREAD_LOCAL_ACCESS
@@ -134,7 +136,7 @@ module NewRelic
134
136
  # Foo._nr_default_metric_name_code('bar') #=> "Custom/#{Foo.name}/bar"
135
137
  def _nr_default_metric_name(method_name)
136
138
  class_name = _nr_derived_class_name
137
- -> (*) { "Custom/#{class_name}/#{method_name}" }
139
+ ->(*) { "Custom/#{class_name}/#{method_name}" }
138
140
  end
139
141
 
140
142
  # Checks to see if the method we are attempting to trace
@@ -241,6 +243,7 @@ module NewRelic
241
243
  # # Instrument foo in transaction traces only
242
244
  # add_method_tracer :foo, 'Custom/foo', :metric => false
243
245
  #
246
+ # @!scope class
244
247
  # @api public
245
248
  #
246
249
  def add_method_tracer(method_name, metric_name = nil, options = {})
@@ -46,13 +46,15 @@ module NewRelic
46
46
  cache_key = "#{object.object_id}#{method_name}".freeze
47
47
  return @code_information[cache_key] if @code_information.key?(cache_key)
48
48
 
49
- namespace, location, is_class_method = namespace_and_location(object, method_name.to_sym)
49
+ info = namespace_and_location(object, method_name.to_sym)
50
+ return ::NewRelic::EMPTY_HASH if info.empty?
50
51
 
52
+ namespace, location, is_class_method = info
51
53
  @code_information[cache_key] = {filepath: location.first,
52
54
  lineno: location.last,
53
55
  function: "#{'self.' if is_class_method}#{method_name}",
54
56
  namespace: namespace}.freeze
55
- rescue => e
57
+ rescue StandardError => e
56
58
  ::NewRelic::Agent.logger.warn("Unable to determine source code info for '#{object}', " \
57
59
  "method '#{method_name}' - #{e.class}: #{e.message}")
58
60
  ::NewRelic::Agent.increment_metric(SOURCE_CODE_INFORMATION_FAILURE_METRIC, 1)
@@ -66,10 +68,10 @@ module NewRelic
66
68
  end
67
69
 
68
70
  # The string representation of a singleton class looks like
69
- # '#<Class:MyModule::MyClass>'. Return the 'MyModule::MyClass' part of
70
- # that string
71
+ # '#<Class:MyModule::MyClass>', or '#<Class:MyModule::MyClass(id: integer, attribute: string)>'
72
+ # Return the 'MyModule::MyClass' part of that string
71
73
  def klass_name(object)
72
- name = Regexp.last_match(1) if object.to_s =~ /^#<Class:(.*)>$/
74
+ name = Regexp.last_match(1) if object.to_s =~ /^#<Class:([\w:]+).*>$/
73
75
  return name if name
74
76
 
75
77
  raise "Unable to glean a class name from string '#{object}'"
@@ -101,6 +103,9 @@ module NewRelic
101
103
  klass = object.singleton_class? ? klassify_singleton(object) : object
102
104
  name = klass.name || '(Anonymous)'
103
105
  is_class_method = false
106
+
107
+ return controller_info(klass, name, is_class_method) if controller_without_method?(klass, method_name)
108
+
104
109
  method = if (klass.instance_methods + klass.private_instance_methods).include?(method_name)
105
110
  klass.instance_method(method_name)
106
111
  else
@@ -109,6 +114,22 @@ module NewRelic
109
114
  end
110
115
  [name, method.source_location, is_class_method]
111
116
  end
117
+
118
+ # Rails controllers can be a special case because by default, controllers in Rails
119
+ # automatically render views with names that correspond to valid routes. This means
120
+ # that a controller method may not have a corresponding method in the controller class.
121
+ def controller_without_method?(klass, method_name)
122
+ defined?(Rails) &&
123
+ defined?(ApplicationController) &&
124
+ klass < ApplicationController &&
125
+ !klass.method_defined?(method_name)
126
+ end
127
+
128
+ def controller_info(klass, name, is_class_method)
129
+ path = Rails.root.join("app/controllers/#{klass.name.underscore}.rb")
130
+
131
+ File.exist?(path) ? [name, [path.to_s, 1], is_class_method] : []
132
+ end
112
133
  end
113
134
  end
114
135
  end
@@ -32,7 +32,7 @@ module NewRelic
32
32
 
33
33
  def deserialize_header(encoded_header, key)
34
34
  decoded_header = obfuscator.deobfuscate(encoded_header)
35
- ::JSON.load(decoded_header)
35
+ ::JSON.parse(decoded_header)
36
36
  rescue => err
37
37
  # If we have a failure of any type here, just return nil and carry on
38
38
  NewRelic::Agent.logger.debug("Failure deserializing encoded header '#{key}' in #{self.class}, #{err.class}, #{err.message}")
@@ -5,7 +5,8 @@
5
5
  module NewRelic
6
6
  module Agent
7
7
  class SyntheticsMonitor < InboundRequestMonitor
8
- SYNTHETICS_HEADER_KEY = 'HTTP_X_NEWRELIC_SYNTHETICS'.freeze
8
+ SYNTHETICS_HEADER_KEY = 'HTTP_X_NEWRELIC_SYNTHETICS'
9
+ SYNTHETICS_INFO_HEADER_KEY = 'HTTP_X_NEWRELIC_SYNTHETICS_INFO'
9
10
 
10
11
  SUPPORTED_VERSION = 1
11
12
  EXPECTED_PAYLOAD_LENGTH = 5
@@ -16,6 +17,7 @@ module NewRelic
16
17
 
17
18
  def on_before_call(request) # THREAD_LOCAL_ACCESS
18
19
  encoded_header = request[SYNTHETICS_HEADER_KEY]
20
+ info_header = request[SYNTHETICS_INFO_HEADER_KEY]
19
21
  return unless encoded_header
20
22
 
21
23
  incoming_payload = deserialize_header(encoded_header, SYNTHETICS_HEADER_KEY)
@@ -27,7 +29,16 @@ module NewRelic
27
29
 
28
30
  txn = Tracer.current_transaction
29
31
  txn.raw_synthetics_header = encoded_header
32
+ txn.raw_synthetics_info_header = info_header
30
33
  txn.synthetics_payload = incoming_payload
34
+ txn.synthetics_info_payload = load_json(info_header, SYNTHETICS_INFO_HEADER_KEY)
35
+ end
36
+
37
+ def load_json(header, key)
38
+ ::JSON.parse(header)
39
+ rescue => err
40
+ NewRelic::Agent.logger.debug("Failure loading json header '#{key}' in #{self.class}, #{err.class}, #{err.message}")
41
+ nil
31
42
  end
32
43
 
33
44
  class << self
@@ -2,10 +2,10 @@
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
5
  require 'json'
7
6
  require 'stringio'
8
7
  require 'zlib'
8
+ require 'new_relic/base64'
9
9
 
10
10
  module NewRelic
11
11
  module Agent
@@ -45,7 +45,7 @@ module NewRelic
45
45
  data = NewRelic::Agent::EncodingNormalizer.normalize_object(data)
46
46
  end
47
47
  json = ::JSON.dump(data)
48
- Base64.encode64(Compressed::Deflate.encode(json))
48
+ NewRelic::Base64.encode64(Compressed::Deflate.encode(json))
49
49
  end
50
50
  end
51
51
  end