newrelic_rpm 5.7.0.350 → 9.0.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 (476) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +15 -1
  3. data/.rubocop.yml +1919 -0
  4. data/.rubocop_todo.yml +100 -0
  5. data/.simplecov +15 -0
  6. data/.snyk +11 -0
  7. data/.yardopts +2 -0
  8. data/Brewfile +12 -0
  9. data/CHANGELOG.md +4056 -2339
  10. data/CONTRIBUTING.md +132 -19
  11. data/DOCKER.md +167 -0
  12. data/Dockerfile +10 -0
  13. data/Gemfile +5 -2
  14. data/Guardfile +22 -4
  15. data/LICENSE +202 -38
  16. data/README.md +87 -87
  17. data/Rakefile +27 -27
  18. data/THIRD_PARTY_NOTICES.md +28 -0
  19. data/Thorfile +5 -0
  20. data/bin/newrelic +3 -2
  21. data/bin/newrelic_cmd +1 -0
  22. data/bin/nrdebug +77 -54
  23. data/config.dot +5 -5
  24. data/docker-compose.yml +107 -0
  25. data/init.rb +5 -7
  26. data/install.rb +3 -3
  27. data/lefthook.yml +9 -0
  28. data/lib/new_relic/agent/adaptive_sampler.rb +14 -10
  29. data/lib/new_relic/agent/agent.rb +125 -969
  30. data/lib/new_relic/agent/agent_helpers/connect.rb +227 -0
  31. data/lib/new_relic/agent/agent_helpers/harvest.rb +153 -0
  32. data/lib/new_relic/agent/agent_helpers/shutdown.rb +72 -0
  33. data/lib/new_relic/agent/agent_helpers/special_startup.rb +74 -0
  34. data/lib/new_relic/agent/agent_helpers/start_worker_thread.rb +167 -0
  35. data/lib/new_relic/agent/agent_helpers/startup.rb +202 -0
  36. data/lib/new_relic/agent/agent_helpers/transmit.rb +76 -0
  37. data/lib/new_relic/agent/agent_logger.rb +26 -18
  38. data/lib/new_relic/agent/attribute_filter.rb +69 -52
  39. data/lib/new_relic/agent/attribute_processing.rb +8 -8
  40. data/lib/new_relic/agent/attributes.rb +153 -0
  41. data/lib/new_relic/agent/audit_logger.rb +19 -4
  42. data/lib/new_relic/agent/autostart.rb +34 -28
  43. data/lib/new_relic/agent/chained_call.rb +2 -2
  44. data/lib/new_relic/agent/commands/agent_command.rb +4 -4
  45. data/lib/new_relic/agent/commands/agent_command_router.rb +15 -33
  46. data/lib/new_relic/agent/commands/thread_profiler_session.rb +13 -11
  47. data/lib/new_relic/agent/configuration/default_source.rb +1480 -1053
  48. data/lib/new_relic/agent/configuration/dotted_hash.rb +7 -6
  49. data/lib/new_relic/agent/configuration/environment_source.rb +15 -11
  50. data/lib/new_relic/agent/configuration/event_harvest_config.rb +68 -0
  51. data/lib/new_relic/agent/configuration/high_security_source.rb +9 -9
  52. data/lib/new_relic/agent/configuration/manager.rb +96 -79
  53. data/lib/new_relic/agent/configuration/manual_source.rb +2 -2
  54. data/lib/new_relic/agent/configuration/mask_defaults.rb +4 -4
  55. data/lib/new_relic/agent/configuration/security_policy_source.rb +83 -86
  56. data/lib/new_relic/agent/configuration/server_source.rb +49 -12
  57. data/lib/new_relic/agent/configuration/yaml_source.rb +42 -13
  58. data/lib/new_relic/agent/configuration.rb +2 -2
  59. data/lib/new_relic/agent/connect/request_builder.rb +61 -0
  60. data/lib/new_relic/agent/connect/response_handler.rb +58 -0
  61. data/lib/new_relic/agent/custom_event_aggregator.rb +15 -15
  62. data/lib/new_relic/agent/database/explain_plan_helpers.rb +5 -6
  63. data/lib/new_relic/agent/database/obfuscation_helpers.rb +16 -15
  64. data/lib/new_relic/agent/database/obfuscator.rb +3 -3
  65. data/lib/new_relic/agent/database/postgres_explain_obfuscator.rb +4 -4
  66. data/lib/new_relic/agent/database.rb +44 -53
  67. data/lib/new_relic/agent/database_adapter.rb +35 -0
  68. data/lib/new_relic/agent/datastores/metric_helper.rb +18 -20
  69. data/lib/new_relic/agent/datastores/mongo/event_formatter.rb +9 -8
  70. data/lib/new_relic/agent/datastores/mongo/metric_translator.rb +7 -11
  71. data/lib/new_relic/agent/datastores/mongo.rb +7 -12
  72. data/lib/new_relic/agent/datastores/nosql_obfuscator.rb +41 -0
  73. data/lib/new_relic/agent/datastores/redis.rb +6 -12
  74. data/lib/new_relic/agent/datastores.rb +19 -23
  75. data/lib/new_relic/agent/deprecator.rb +2 -2
  76. data/lib/new_relic/agent/{cross_app_payload.rb → distributed_tracing/cross_app_payload.rb} +13 -12
  77. data/lib/new_relic/agent/{cross_app_tracing.rb → distributed_tracing/cross_app_tracing.rb} +87 -66
  78. data/lib/new_relic/agent/distributed_tracing/distributed_trace_attributes.rb +84 -0
  79. data/lib/new_relic/agent/distributed_tracing/distributed_trace_metrics.rb +75 -0
  80. data/lib/new_relic/agent/distributed_tracing/distributed_trace_payload.rb +163 -0
  81. data/lib/new_relic/agent/distributed_tracing/distributed_trace_transport_type.rb +38 -0
  82. data/lib/new_relic/agent/distributed_tracing/trace_context.rb +245 -0
  83. data/lib/new_relic/agent/distributed_tracing/trace_context_payload.rb +127 -0
  84. data/lib/new_relic/agent/distributed_tracing.rb +113 -32
  85. data/lib/new_relic/agent/encoding_normalizer.rb +5 -3
  86. data/lib/new_relic/agent/error_collector.rb +99 -63
  87. data/lib/new_relic/agent/error_event_aggregator.rb +10 -8
  88. data/lib/new_relic/agent/error_filter.rb +174 -0
  89. data/lib/new_relic/agent/error_trace_aggregator.rb +6 -4
  90. data/lib/new_relic/agent/event_aggregator.rb +43 -48
  91. data/lib/new_relic/agent/event_buffer.rb +8 -9
  92. data/lib/new_relic/agent/event_listener.rb +2 -3
  93. data/lib/new_relic/agent/event_loop.rb +27 -25
  94. data/lib/new_relic/agent/external.rb +20 -51
  95. data/lib/new_relic/agent/guid_generator.rb +30 -0
  96. data/lib/new_relic/agent/harvester.rb +5 -6
  97. data/lib/new_relic/agent/heap.rb +8 -10
  98. data/lib/new_relic/agent/hostname.rb +26 -5
  99. data/lib/new_relic/agent/http_clients/abstract.rb +81 -0
  100. data/lib/new_relic/agent/http_clients/curb_wrappers.rb +26 -26
  101. data/lib/new_relic/agent/http_clients/excon_wrappers.rb +31 -17
  102. data/lib/new_relic/agent/http_clients/http_rb_wrappers.rb +18 -23
  103. data/lib/new_relic/agent/http_clients/httpclient_wrappers.rb +12 -15
  104. data/lib/new_relic/agent/http_clients/net_http_wrappers.rb +24 -8
  105. data/lib/new_relic/agent/http_clients/typhoeus_wrappers.rb +9 -12
  106. data/lib/new_relic/agent/http_clients/uri_util.rb +12 -13
  107. data/lib/new_relic/agent/instrumentation/action_cable_subscriber.rb +22 -52
  108. data/lib/new_relic/agent/instrumentation/action_controller_other_subscriber.rb +39 -0
  109. data/lib/new_relic/agent/instrumentation/action_controller_subscriber.rb +59 -72
  110. data/lib/new_relic/agent/instrumentation/action_dispatch.rb +31 -0
  111. data/lib/new_relic/agent/instrumentation/action_dispatch_subscriber.rb +64 -0
  112. data/lib/new_relic/agent/instrumentation/action_mailbox.rb +30 -0
  113. data/lib/new_relic/agent/instrumentation/action_mailbox_subscriber.rb +33 -0
  114. data/lib/new_relic/agent/instrumentation/action_mailer.rb +30 -0
  115. data/lib/new_relic/agent/instrumentation/action_mailer_subscriber.rb +85 -0
  116. data/lib/new_relic/agent/instrumentation/action_view_subscriber.rb +86 -62
  117. data/lib/new_relic/agent/instrumentation/active_job.rb +38 -19
  118. data/lib/new_relic/agent/instrumentation/active_job_subscriber.rb +41 -0
  119. data/lib/new_relic/agent/instrumentation/active_merchant.rb +21 -7
  120. data/lib/new_relic/agent/instrumentation/active_record.rb +95 -46
  121. data/lib/new_relic/agent/instrumentation/active_record_helper.rb +82 -61
  122. data/lib/new_relic/agent/instrumentation/active_record_notifications.rb +155 -0
  123. data/lib/new_relic/agent/instrumentation/active_record_prepend.rb +36 -12
  124. data/lib/new_relic/agent/instrumentation/active_record_subscriber.rb +69 -64
  125. data/lib/new_relic/agent/instrumentation/active_storage.rb +8 -4
  126. data/lib/new_relic/agent/instrumentation/active_storage_subscriber.rb +11 -32
  127. data/lib/new_relic/agent/instrumentation/active_support.rb +27 -0
  128. data/lib/new_relic/agent/instrumentation/active_support_logger/chain.rb +23 -0
  129. data/lib/new_relic/agent/instrumentation/active_support_logger/instrumentation.rb +20 -0
  130. data/lib/new_relic/agent/instrumentation/active_support_logger/prepend.rb +12 -0
  131. data/lib/new_relic/agent/instrumentation/active_support_logger.rb +24 -0
  132. data/lib/new_relic/agent/instrumentation/active_support_subscriber.rb +41 -0
  133. data/lib/new_relic/agent/instrumentation/bunny/chain.rb +45 -0
  134. data/lib/new_relic/agent/instrumentation/bunny/instrumentation.rb +150 -0
  135. data/lib/new_relic/agent/instrumentation/bunny/prepend.rb +35 -0
  136. data/lib/new_relic/agent/instrumentation/bunny.rb +14 -134
  137. data/lib/new_relic/agent/instrumentation/concurrent_ruby/chain.rb +36 -0
  138. data/lib/new_relic/agent/instrumentation/concurrent_ruby/instrumentation.rb +21 -0
  139. data/lib/new_relic/agent/instrumentation/concurrent_ruby/prepend.rb +27 -0
  140. data/lib/new_relic/agent/instrumentation/concurrent_ruby.rb +31 -0
  141. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +77 -61
  142. data/lib/new_relic/agent/instrumentation/curb/chain.rb +91 -0
  143. data/lib/new_relic/agent/instrumentation/curb/instrumentation.rb +221 -0
  144. data/lib/new_relic/agent/instrumentation/curb/prepend.rb +61 -0
  145. data/lib/new_relic/agent/instrumentation/curb.rb +15 -187
  146. data/lib/new_relic/agent/instrumentation/custom_events.rb +12 -0
  147. data/lib/new_relic/agent/instrumentation/custom_events_subscriber.rb +37 -0
  148. data/lib/new_relic/agent/instrumentation/delayed_job/chain.rb +35 -0
  149. data/lib/new_relic/agent/instrumentation/delayed_job/instrumentation.rb +48 -0
  150. data/lib/new_relic/agent/instrumentation/delayed_job/prepend.rb +33 -0
  151. data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +30 -52
  152. data/lib/new_relic/agent/instrumentation/elasticsearch/chain.rb +29 -0
  153. data/lib/new_relic/agent/instrumentation/elasticsearch/instrumentation.rb +66 -0
  154. data/lib/new_relic/agent/instrumentation/elasticsearch/prepend.rb +13 -0
  155. data/lib/new_relic/agent/instrumentation/elasticsearch.rb +31 -0
  156. data/lib/new_relic/agent/instrumentation/excon/middleware.rb +8 -7
  157. data/lib/new_relic/agent/instrumentation/excon.rb +29 -31
  158. data/lib/new_relic/agent/instrumentation/fiber/chain.rb +20 -0
  159. data/lib/new_relic/agent/instrumentation/fiber/instrumentation.rb +24 -0
  160. data/lib/new_relic/agent/instrumentation/fiber/prepend.rb +18 -0
  161. data/lib/new_relic/agent/instrumentation/fiber.rb +25 -0
  162. data/lib/new_relic/agent/instrumentation/grape/chain.rb +24 -0
  163. data/lib/new_relic/agent/instrumentation/grape/instrumentation.rb +100 -0
  164. data/lib/new_relic/agent/instrumentation/grape/prepend.rb +17 -0
  165. data/lib/new_relic/agent/instrumentation/grape.rb +16 -121
  166. data/lib/new_relic/agent/instrumentation/grpc/client/chain.rb +97 -0
  167. data/lib/new_relic/agent/instrumentation/grpc/client/instrumentation.rb +89 -0
  168. data/lib/new_relic/agent/instrumentation/grpc/client/prepend.rb +111 -0
  169. data/lib/new_relic/agent/instrumentation/grpc/client/request_wrapper.rb +30 -0
  170. data/lib/new_relic/agent/instrumentation/grpc/helper.rb +32 -0
  171. data/lib/new_relic/agent/instrumentation/grpc/server/chain.rb +69 -0
  172. data/lib/new_relic/agent/instrumentation/grpc/server/instrumentation.rb +134 -0
  173. data/lib/new_relic/agent/instrumentation/grpc/server/rpc_desc_prepend.rb +35 -0
  174. data/lib/new_relic/agent/instrumentation/grpc/server/rpc_server_prepend.rb +26 -0
  175. data/lib/new_relic/agent/instrumentation/grpc_client.rb +23 -0
  176. data/lib/new_relic/agent/instrumentation/grpc_server.rb +25 -0
  177. data/lib/new_relic/agent/instrumentation/httpclient/chain.rb +24 -0
  178. data/lib/new_relic/agent/instrumentation/httpclient/instrumentation.rb +37 -0
  179. data/lib/new_relic/agent/instrumentation/httpclient/prepend.rb +15 -0
  180. data/lib/new_relic/agent/instrumentation/httpclient.rb +12 -32
  181. data/lib/new_relic/agent/instrumentation/httprb/chain.rb +22 -0
  182. data/lib/new_relic/agent/instrumentation/httprb/instrumentation.rb +30 -0
  183. data/lib/new_relic/agent/instrumentation/httprb/prepend.rb +15 -0
  184. data/lib/new_relic/agent/instrumentation/httprb.rb +29 -0
  185. data/lib/new_relic/agent/instrumentation/ignore_actions.rb +5 -6
  186. data/lib/new_relic/agent/instrumentation/logger/chain.rb +21 -0
  187. data/lib/new_relic/agent/instrumentation/logger/instrumentation.rb +66 -0
  188. data/lib/new_relic/agent/instrumentation/logger/prepend.rb +13 -0
  189. data/lib/new_relic/agent/instrumentation/logger.rb +26 -0
  190. data/lib/new_relic/agent/instrumentation/memcache/chain.rb +15 -0
  191. data/lib/new_relic/agent/instrumentation/memcache/dalli.rb +58 -125
  192. data/lib/new_relic/agent/instrumentation/memcache/helper.rb +59 -0
  193. data/lib/new_relic/agent/instrumentation/memcache/instrumentation.rb +90 -0
  194. data/lib/new_relic/agent/instrumentation/memcache/prepend.rb +101 -0
  195. data/lib/new_relic/agent/instrumentation/memcache.rb +57 -71
  196. data/lib/new_relic/agent/instrumentation/middleware_proxy.rb +15 -14
  197. data/lib/new_relic/agent/instrumentation/middleware_tracing.rb +21 -14
  198. data/lib/new_relic/agent/instrumentation/mongo.rb +7 -132
  199. data/lib/new_relic/agent/instrumentation/mongodb_command_subscriber.rb +49 -13
  200. data/lib/new_relic/agent/instrumentation/net_http/chain.rb +24 -0
  201. data/lib/new_relic/agent/instrumentation/net_http/instrumentation.rb +40 -0
  202. data/lib/new_relic/agent/instrumentation/net_http/prepend.rb +21 -0
  203. data/lib/new_relic/agent/instrumentation/net_http.rb +44 -0
  204. data/lib/new_relic/agent/instrumentation/notifications_subscriber.rb +142 -0
  205. data/lib/new_relic/agent/instrumentation/padrino/chain.rb +38 -0
  206. data/lib/new_relic/agent/instrumentation/padrino/instrumentation.rb +28 -0
  207. data/lib/new_relic/agent/instrumentation/padrino/prepend.rb +20 -0
  208. data/lib/new_relic/agent/instrumentation/padrino.rb +22 -58
  209. data/lib/new_relic/agent/instrumentation/passenger_instrumentation.rb +7 -7
  210. data/lib/new_relic/agent/instrumentation/queue_time.rb +9 -10
  211. data/lib/new_relic/agent/instrumentation/rack/chain.rb +66 -0
  212. data/lib/new_relic/agent/instrumentation/rack/helpers.rb +33 -0
  213. data/lib/new_relic/agent/instrumentation/rack/instrumentation.rb +75 -0
  214. data/lib/new_relic/agent/instrumentation/rack/prepend.rb +43 -0
  215. data/lib/new_relic/agent/instrumentation/rack.rb +33 -141
  216. data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +19 -55
  217. data/lib/new_relic/agent/instrumentation/rails_middleware.rb +5 -5
  218. data/lib/new_relic/agent/instrumentation/rails_notifications/action_cable.rb +36 -0
  219. data/lib/new_relic/agent/instrumentation/rails_notifications/action_controller.rb +45 -0
  220. data/lib/new_relic/agent/instrumentation/rails_notifications/action_view.rb +30 -0
  221. data/lib/new_relic/agent/instrumentation/rails_notifications/custom_events.rb +30 -0
  222. data/lib/new_relic/agent/instrumentation/rake/chain.rb +20 -0
  223. data/lib/new_relic/agent/instrumentation/rake/instrumentation.rb +142 -0
  224. data/lib/new_relic/agent/instrumentation/rake/prepend.rb +14 -0
  225. data/lib/new_relic/agent/instrumentation/rake.rb +18 -159
  226. data/lib/new_relic/agent/instrumentation/redis/chain.rb +45 -0
  227. data/lib/new_relic/agent/instrumentation/redis/constants.rb +17 -0
  228. data/lib/new_relic/agent/instrumentation/redis/instrumentation.rb +93 -0
  229. data/lib/new_relic/agent/instrumentation/redis/middleware.rb +16 -0
  230. data/lib/new_relic/agent/instrumentation/redis/prepend.rb +29 -0
  231. data/lib/new_relic/agent/instrumentation/redis.rb +20 -103
  232. data/lib/new_relic/agent/instrumentation/resque/chain.rb +21 -0
  233. data/lib/new_relic/agent/instrumentation/resque/helper.rb +19 -0
  234. data/lib/new_relic/agent/instrumentation/resque/instrumentation.rb +34 -0
  235. data/lib/new_relic/agent/instrumentation/resque/prepend.rb +15 -0
  236. data/lib/new_relic/agent/instrumentation/resque.rb +33 -41
  237. data/lib/new_relic/agent/instrumentation/sequel.rb +17 -20
  238. data/lib/new_relic/agent/instrumentation/sequel_helper.rb +3 -3
  239. data/lib/new_relic/agent/instrumentation/sidekiq/client.rb +20 -0
  240. data/lib/new_relic/agent/instrumentation/sidekiq/extensions/delayed_class.rb +30 -0
  241. data/lib/new_relic/agent/instrumentation/sidekiq/server.rb +37 -0
  242. data/lib/new_relic/agent/instrumentation/sidekiq.rb +29 -46
  243. data/lib/new_relic/agent/instrumentation/sinatra/chain.rb +55 -0
  244. data/lib/new_relic/agent/instrumentation/sinatra/ignorer.rb +31 -37
  245. data/lib/new_relic/agent/instrumentation/sinatra/instrumentation.rb +125 -0
  246. data/lib/new_relic/agent/instrumentation/sinatra/prepend.rb +33 -0
  247. data/lib/new_relic/agent/instrumentation/sinatra/transaction_namer.rb +3 -3
  248. data/lib/new_relic/agent/instrumentation/sinatra.rb +35 -165
  249. data/lib/new_relic/agent/instrumentation/thread/chain.rb +24 -0
  250. data/lib/new_relic/agent/instrumentation/thread/instrumentation.rb +28 -0
  251. data/lib/new_relic/agent/instrumentation/thread/prepend.rb +22 -0
  252. data/lib/new_relic/agent/instrumentation/thread.rb +20 -0
  253. data/lib/new_relic/agent/instrumentation/tilt/chain.rb +24 -0
  254. data/lib/new_relic/agent/instrumentation/tilt/instrumentation.rb +41 -0
  255. data/lib/new_relic/agent/instrumentation/tilt/prepend.rb +13 -0
  256. data/lib/new_relic/agent/instrumentation/tilt.rb +25 -0
  257. data/lib/new_relic/agent/instrumentation/typhoeus/chain.rb +22 -0
  258. data/lib/new_relic/agent/instrumentation/typhoeus/instrumentation.rb +80 -0
  259. data/lib/new_relic/agent/instrumentation/typhoeus/prepend.rb +14 -0
  260. data/lib/new_relic/agent/instrumentation/typhoeus.rb +14 -76
  261. data/lib/new_relic/agent/instrumentation.rb +2 -2
  262. data/lib/new_relic/agent/internal_agent_error.rb +3 -3
  263. data/lib/new_relic/agent/javascript_instrumentor.rb +51 -45
  264. data/lib/new_relic/agent/linking_metadata.rb +44 -0
  265. data/lib/new_relic/agent/local_log_decorator.rb +37 -0
  266. data/lib/new_relic/agent/log_event_aggregator.rb +235 -0
  267. data/lib/new_relic/agent/log_once.rb +2 -2
  268. data/lib/new_relic/agent/log_priority.rb +20 -0
  269. data/lib/new_relic/agent/logging.rb +142 -0
  270. data/lib/new_relic/agent/memory_logger.rb +3 -3
  271. data/lib/new_relic/agent/messaging.rb +81 -164
  272. data/lib/new_relic/agent/method_tracer.rb +152 -145
  273. data/lib/new_relic/agent/method_tracer_helpers.rb +90 -13
  274. data/lib/new_relic/agent/monitors/cross_app_monitor.rb +117 -0
  275. data/lib/new_relic/agent/monitors/distributed_tracing_monitor.rb +28 -0
  276. data/lib/new_relic/agent/{inbound_request_monitor.rb → monitors/inbound_request_monitor.rb} +5 -6
  277. data/lib/new_relic/agent/{synthetics_monitor.rb → monitors/synthetics_monitor.rb} +9 -15
  278. data/lib/new_relic/agent/monitors.rb +26 -0
  279. data/lib/new_relic/agent/new_relic_service/encoders.rb +7 -7
  280. data/lib/new_relic/agent/new_relic_service/json_marshaller.rb +6 -7
  281. data/lib/new_relic/agent/new_relic_service/marshaller.rb +8 -29
  282. data/lib/new_relic/agent/new_relic_service/security_policy_settings.rb +5 -5
  283. data/lib/new_relic/agent/new_relic_service.rb +282 -166
  284. data/lib/new_relic/agent/noticeable_error.rb +19 -0
  285. data/lib/new_relic/agent/null_logger.rb +8 -4
  286. data/lib/new_relic/agent/obfuscator.rb +9 -11
  287. data/lib/new_relic/agent/parameter_filtering.rb +35 -8
  288. data/lib/new_relic/agent/payload_metric_mapping.rb +10 -11
  289. data/lib/new_relic/agent/pipe_channel_manager.rb +28 -18
  290. data/lib/new_relic/agent/pipe_service.rb +9 -6
  291. data/lib/new_relic/agent/prepend_supportability.rb +3 -3
  292. data/lib/new_relic/agent/priority_sampled_buffer.rb +16 -14
  293. data/lib/new_relic/agent/range_extensions.rb +9 -29
  294. data/lib/new_relic/agent/rules_engine/replacement_rule.rb +12 -12
  295. data/lib/new_relic/agent/rules_engine/segment_terms_rule.rb +13 -14
  296. data/lib/new_relic/agent/rules_engine.rb +6 -5
  297. data/lib/new_relic/agent/sampler.rb +4 -5
  298. data/lib/new_relic/agent/sampler_collection.rb +4 -5
  299. data/lib/new_relic/agent/samplers/cpu_sampler.rb +4 -3
  300. data/lib/new_relic/agent/samplers/delayed_job_sampler.rb +14 -11
  301. data/lib/new_relic/agent/samplers/memory_sampler.rb +26 -15
  302. data/lib/new_relic/agent/samplers/object_sampler.rb +2 -2
  303. data/lib/new_relic/agent/samplers/vm_sampler.rb +22 -20
  304. data/lib/new_relic/agent/span_event_aggregator.rb +14 -16
  305. data/lib/new_relic/agent/span_event_primitive.rb +118 -58
  306. data/lib/new_relic/agent/sql_sampler.rb +25 -25
  307. data/lib/new_relic/agent/stats.rb +79 -42
  308. data/lib/new_relic/agent/stats_engine/gc_profiler.rb +11 -13
  309. data/lib/new_relic/agent/stats_engine/stats_hash.rb +13 -14
  310. data/lib/new_relic/agent/stats_engine.rb +11 -11
  311. data/lib/new_relic/agent/synthetics_event_aggregator.rb +8 -9
  312. data/lib/new_relic/agent/system_info.rb +100 -66
  313. data/lib/new_relic/agent/threading/agent_thread.rb +20 -16
  314. data/lib/new_relic/agent/threading/backtrace_node.rb +13 -14
  315. data/lib/new_relic/agent/threading/backtrace_service.rb +18 -18
  316. data/lib/new_relic/agent/threading/thread_profile.rb +31 -45
  317. data/lib/new_relic/agent/timestamp_sampled_buffer.rb +2 -2
  318. data/lib/new_relic/agent/tracer.rb +513 -0
  319. data/lib/new_relic/agent/transaction/abstract_segment.rb +131 -41
  320. data/lib/new_relic/agent/transaction/datastore_segment.rb +22 -18
  321. data/lib/new_relic/agent/transaction/distributed_tracer.rb +184 -0
  322. data/lib/new_relic/agent/transaction/distributed_tracing.rb +72 -163
  323. data/lib/new_relic/agent/transaction/external_request_segment.rb +66 -63
  324. data/lib/new_relic/agent/transaction/message_broker_segment.rb +34 -46
  325. data/lib/new_relic/agent/transaction/request_attributes.rb +36 -36
  326. data/lib/new_relic/agent/transaction/segment.rb +46 -10
  327. data/lib/new_relic/agent/transaction/slowest_sample_buffer.rb +2 -4
  328. data/lib/new_relic/agent/transaction/synthetics_sample_buffer.rb +2 -2
  329. data/lib/new_relic/agent/transaction/trace.rb +21 -24
  330. data/lib/new_relic/agent/transaction/trace_builder.rb +11 -12
  331. data/lib/new_relic/agent/transaction/trace_context.rb +168 -0
  332. data/lib/new_relic/agent/transaction/trace_node.rb +31 -28
  333. data/lib/new_relic/agent/transaction/tracing.rb +15 -111
  334. data/lib/new_relic/agent/transaction/transaction_sample_buffer.rb +6 -6
  335. data/lib/new_relic/agent/transaction.rb +252 -259
  336. data/lib/new_relic/agent/transaction_error_primitive.rb +34 -37
  337. data/lib/new_relic/agent/transaction_event_aggregator.rb +13 -13
  338. data/lib/new_relic/agent/transaction_event_primitive.rb +44 -56
  339. data/lib/new_relic/agent/transaction_event_recorder.rb +17 -16
  340. data/lib/new_relic/agent/transaction_metrics.rb +11 -10
  341. data/lib/new_relic/agent/transaction_sampler.rb +7 -12
  342. data/lib/new_relic/agent/transaction_time_aggregator.rb +41 -26
  343. data/lib/new_relic/agent/utilization/aws.rb +34 -4
  344. data/lib/new_relic/agent/utilization/azure.rb +4 -4
  345. data/lib/new_relic/agent/utilization/gcp.rb +8 -8
  346. data/lib/new_relic/agent/utilization/pcf.rb +6 -5
  347. data/lib/new_relic/agent/utilization/vendor.rb +44 -29
  348. data/lib/new_relic/agent/utilization_data.rb +43 -6
  349. data/lib/new_relic/agent/vm/jruby_vm.rb +2 -2
  350. data/lib/new_relic/agent/vm/monotonic_gc_profiler.rb +3 -3
  351. data/lib/new_relic/agent/vm/mri_vm.rb +46 -19
  352. data/lib/new_relic/agent/vm/snapshot.rb +6 -6
  353. data/lib/new_relic/agent/vm.rb +2 -2
  354. data/lib/new_relic/agent/worker_loop.rb +11 -13
  355. data/lib/new_relic/agent.rb +151 -79
  356. data/lib/new_relic/cli/command.rb +21 -23
  357. data/lib/new_relic/cli/commands/deployments.rb +94 -45
  358. data/lib/new_relic/cli/commands/install.rb +24 -26
  359. data/lib/new_relic/coerce.rb +42 -15
  360. data/lib/new_relic/collection_helper.rb +51 -49
  361. data/lib/new_relic/constants.rb +39 -0
  362. data/lib/new_relic/control/class_methods.rb +11 -5
  363. data/lib/new_relic/control/frameworks/external.rb +3 -3
  364. data/lib/new_relic/control/frameworks/rails.rb +24 -18
  365. data/lib/new_relic/control/frameworks/rails3.rb +4 -5
  366. data/lib/new_relic/control/frameworks/rails4.rb +2 -2
  367. data/lib/new_relic/control/frameworks/rails_notifications.rb +14 -0
  368. data/lib/new_relic/control/frameworks/ruby.rb +4 -4
  369. data/lib/new_relic/control/frameworks/sinatra.rb +8 -2
  370. data/lib/new_relic/control/frameworks.rb +2 -2
  371. data/lib/new_relic/control/instance_methods.rb +33 -42
  372. data/lib/new_relic/control/instrumentation.rb +40 -12
  373. data/lib/new_relic/control/private_instance_methods.rb +48 -0
  374. data/lib/new_relic/control/server_methods.rb +4 -5
  375. data/lib/new_relic/control.rb +2 -3
  376. data/lib/new_relic/delayed_job_injection.rb +2 -2
  377. data/lib/new_relic/dependency_detection.rb +129 -18
  378. data/lib/new_relic/environment_report.rb +41 -35
  379. data/lib/new_relic/helper.rb +49 -8
  380. data/lib/new_relic/language_support.rb +30 -6
  381. data/lib/new_relic/latest_changes.rb +9 -8
  382. data/lib/new_relic/local_environment.rb +23 -27
  383. data/lib/new_relic/metric_data.rb +32 -27
  384. data/lib/new_relic/metric_spec.rb +9 -7
  385. data/lib/new_relic/noticed_error.rb +46 -33
  386. data/lib/new_relic/rack/agent_hooks.rb +2 -2
  387. data/lib/new_relic/rack/agent_middleware.rb +7 -5
  388. data/lib/new_relic/rack/browser_monitoring.rb +134 -117
  389. data/lib/new_relic/rack.rb +2 -2
  390. data/lib/new_relic/recipes/capistrano3.rb +4 -62
  391. data/lib/new_relic/recipes/capistrano_legacy.rb +24 -27
  392. data/lib/new_relic/recipes/helpers/send_deployment.rb +70 -0
  393. data/lib/new_relic/recipes.rb +2 -2
  394. data/lib/new_relic/supportability_helper.rb +21 -7
  395. data/lib/new_relic/traced_thread.rb +39 -0
  396. data/lib/new_relic/version.rb +7 -18
  397. data/lib/newrelic_rpm.rb +20 -33
  398. data/lib/sequel/extensions/{newrelic_instrumentation.rb → new_relic_instrumentation.rb} +16 -19
  399. data/lib/sequel/plugins/{newrelic_instrumentation.rb → new_relic_instrumentation.rb} +9 -15
  400. data/lib/tasks/all.rb +4 -4
  401. data/lib/tasks/config.rake +22 -118
  402. data/lib/tasks/coverage_report.rake +28 -0
  403. data/lib/tasks/helpers/config.html.erb +21 -0
  404. data/lib/tasks/helpers/format.rb +123 -0
  405. data/lib/tasks/helpers/matches.rb +12 -0
  406. data/lib/tasks/helpers/prompt.rb +24 -0
  407. data/lib/tasks/helpers/removers.rb +33 -0
  408. data/lib/tasks/install.rake +4 -0
  409. data/lib/tasks/instrumentation_generator/README.md +63 -0
  410. data/lib/tasks/instrumentation_generator/TODO.md +33 -0
  411. data/lib/tasks/instrumentation_generator/instrumentation.thor +121 -0
  412. data/lib/tasks/instrumentation_generator/templates/Envfile.tt +9 -0
  413. data/lib/tasks/instrumentation_generator/templates/chain.tt +22 -0
  414. data/lib/tasks/instrumentation_generator/templates/chain_method.tt +8 -0
  415. data/lib/tasks/instrumentation_generator/templates/dependency_detection.tt +29 -0
  416. data/lib/tasks/instrumentation_generator/templates/instrumentation.tt +13 -0
  417. data/lib/tasks/instrumentation_generator/templates/instrumentation_method.tt +3 -0
  418. data/lib/tasks/instrumentation_generator/templates/newrelic.yml.tt +19 -0
  419. data/lib/tasks/instrumentation_generator/templates/prepend.tt +13 -0
  420. data/lib/tasks/instrumentation_generator/templates/prepend_method.tt +3 -0
  421. data/lib/tasks/instrumentation_generator/templates/test.tt +15 -0
  422. data/lib/tasks/multiverse.rake +4 -0
  423. data/lib/tasks/multiverse.rb +12 -5
  424. data/lib/tasks/newrelic.rb +2 -2
  425. data/lib/tasks/tests.rake +14 -14
  426. data/newrelic.yml +672 -3
  427. data/newrelic_rpm.gemspec +40 -31
  428. data/recipes/newrelic.rb +3 -3
  429. data/test/agent_helper.rb +419 -98
  430. metadata +238 -127
  431. data/.travis.yml +0 -228
  432. data/bin/mongrel_rpm +0 -33
  433. data/cert/cacert.pem +0 -1177
  434. data/lib/new_relic/agent/commands/xray_session.rb +0 -55
  435. data/lib/new_relic/agent/commands/xray_session_collection.rb +0 -161
  436. data/lib/new_relic/agent/cross_app_monitor.rb +0 -110
  437. data/lib/new_relic/agent/datastores/mongo/obfuscator.rb +0 -44
  438. data/lib/new_relic/agent/datastores/mongo/statement_formatter.rb +0 -53
  439. data/lib/new_relic/agent/distributed_trace_monitor.rb +0 -41
  440. data/lib/new_relic/agent/distributed_trace_payload.rb +0 -246
  441. data/lib/new_relic/agent/http_clients/abstract_request.rb +0 -31
  442. data/lib/new_relic/agent/instrumentation/active_record_4.rb +0 -42
  443. data/lib/new_relic/agent/instrumentation/active_record_5.rb +0 -41
  444. data/lib/new_relic/agent/instrumentation/acts_as_solr.rb +0 -74
  445. data/lib/new_relic/agent/instrumentation/authlogic.rb +0 -25
  446. data/lib/new_relic/agent/instrumentation/data_mapper.rb +0 -202
  447. data/lib/new_relic/agent/instrumentation/evented_subscriber.rb +0 -104
  448. data/lib/new_relic/agent/instrumentation/excon/connection.rb +0 -46
  449. data/lib/new_relic/agent/instrumentation/http.rb +0 -46
  450. data/lib/new_relic/agent/instrumentation/merb/controller.rb +0 -44
  451. data/lib/new_relic/agent/instrumentation/merb/errors.rb +0 -33
  452. data/lib/new_relic/agent/instrumentation/net.rb +0 -50
  453. data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +0 -125
  454. data/lib/new_relic/agent/instrumentation/rails/action_web_service.rb +0 -46
  455. data/lib/new_relic/agent/instrumentation/rails4/action_controller.rb +0 -32
  456. data/lib/new_relic/agent/instrumentation/rails4/action_view.rb +0 -27
  457. data/lib/new_relic/agent/instrumentation/rails5/action_cable.rb +0 -36
  458. data/lib/new_relic/agent/instrumentation/rails5/action_controller.rb +0 -33
  459. data/lib/new_relic/agent/instrumentation/rails5/action_view.rb +0 -27
  460. data/lib/new_relic/agent/instrumentation/rainbows_instrumentation.rb +0 -26
  461. data/lib/new_relic/agent/instrumentation/sunspot.rb +0 -33
  462. data/lib/new_relic/agent/supported_versions.rb +0 -275
  463. data/lib/new_relic/agent/transaction/attributes.rb +0 -154
  464. data/lib/new_relic/agent/transaction/xray_sample_buffer.rb +0 -64
  465. data/lib/new_relic/agent/transaction_state.rb +0 -186
  466. data/lib/new_relic/build.rb +0 -2
  467. data/lib/new_relic/control/frameworks/merb.rb +0 -29
  468. data/lib/new_relic/control/frameworks/rails5.rb +0 -14
  469. data/lib/new_relic/metrics.rb +0 -13
  470. data/lib/tasks/config.html.erb +0 -32
  471. data/lib/tasks/versions.html.erb +0 -28
  472. data/lib/tasks/versions.postface.html +0 -8
  473. data/lib/tasks/versions.preface.html +0 -9
  474. data/lib/tasks/versions.rake +0 -65
  475. data/lib/tasks/versions.txt.erb +0 -14
  476. /data/lib/tasks/{config.text.erb → helpers/config.text.erb} +0 -0
@@ -1,6 +1,6 @@
1
- # encoding: utf-8
2
1
  # This file is distributed under New Relic's license terms.
3
- # See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
4
 
5
5
  require 'zlib'
6
6
  require 'timeout'
@@ -15,44 +15,57 @@ module NewRelic
15
15
  class NewRelicService
16
16
  # Specifies the version of the agent's communication protocol with
17
17
  # the NewRelic hosted site.
18
-
19
- PROTOCOL_VERSION = 16
20
-
21
- # 1f147a42: v10 (tag 3.5.3.17)
22
- # cf0d1ff1: v9 (tag 3.5.0)
23
- # 14105: v8 (tag 2.10.3)
24
- # (no v7)
25
- # 10379: v6 (not tagged)
26
- # 4078: v5 (tag 2.5.4)
27
- # 2292: v4 (tag 2.3.6)
28
- # 1754: v3 (tag 2.3.0)
29
- # 534: v2 (shows up in 2.1.0, our first tag)
18
+ PROTOCOL_VERSION = 17
30
19
 
31
20
  # These include Errno connection errors, and all indicate that the
32
21
  # underlying TCP connection may be in a bad state.
33
22
  CONNECTION_ERRORS = [Timeout::Error, EOFError, SystemCallError, SocketError].freeze
34
23
 
24
+ # The maximum number of times to attempt an HTTP request
25
+ MAX_ATTEMPTS = 2
26
+
27
+ # Don't perform compression on the payload unless its uncompressed size is
28
+ # greater than or equal to this number of bytes. In testing with
29
+ # Ruby 2.2 - 3.1, we determined an absolute minimum value for ASCII to be
30
+ # 535 bytes to obtain at least a 10% savings in size. It is recommended
31
+ # that this value be kept above that 535 number. It is also important to
32
+ # consider the CPU cost involved with performing compression and to find
33
+ # a balance between CPU cycles spent and bandwidth saved. A good
34
+ # reasonable default here is 2048 bytes, which is a tried and true Apache
35
+ # Tomcat default (as of v8.5.78)
36
+ MIN_BYTE_SIZE_TO_COMPRESS = 2048
37
+
35
38
  attr_accessor :request_timeout
36
39
  attr_reader :collector, :marshaller, :agent_id
37
40
 
38
- def initialize(license_key=nil, collector=control.server)
41
+ def initialize(license_key = nil, collector = control.server)
39
42
  @license_key = license_key
40
43
  @collector = collector
44
+ @configured_collector = collector
41
45
  @request_timeout = Agent.config[:timeout]
42
46
  @ssl_cert_store = nil
43
47
  @in_session = nil
44
48
  @agent_id = nil
45
49
  @shared_tcp_connection = nil
50
+ @request_headers_map = nil
46
51
  reset_remote_method_uris
47
52
 
53
+ prep_audit_logger
54
+ prep_marshaller
55
+ end
56
+
57
+ def prep_audit_logger
48
58
  @audit_logger = ::NewRelic::Agent::AuditLogger.new
49
59
  Agent.config.register_callback(:'audit_log.enabled') do |enabled|
50
60
  @audit_logger.enabled = enabled
51
61
  end
62
+ end
52
63
 
64
+ def prep_marshaller
53
65
  Agent.config.register_callback(:marshaller) do |marshaller|
54
66
  if marshaller != 'json'
55
- ::NewRelic::Agent.logger.warn("Non-JSON marshaller '#{marshaller}' requested but not supported, using JSON marshaller instead. pruby marshalling has been removed as of version 3.14.0.")
67
+ ::NewRelic::Agent.logger.warn("Non-JSON marshaller '#{marshaller}' requested but not supported, using " \
68
+ "JSON marshaller instead. pruby marshalling has been removed as of version 3.14.0.")
56
69
  end
57
70
 
58
71
  @marshaller = JsonMarshaller.new
@@ -64,11 +77,11 @@ module NewRelic
64
77
  # clear out our cached values whenever the run ID changes.
65
78
  #
66
79
  reset_remote_method_uris
67
-
68
80
  @agent_id = id
69
81
  end
70
82
 
71
- def connect(settings={})
83
+ def connect(settings = {})
84
+ @request_headers_map = nil
72
85
  security_policies = nil
73
86
  if response = preconnect
74
87
  if host = response['redirect_host']
@@ -80,6 +93,7 @@ module NewRelic
80
93
  end
81
94
  end
82
95
  response = invoke_remote(:connect, [settings])
96
+ @request_headers_map = response['request_headers_map']
83
97
  self.agent_id = response['agent_run_id']
84
98
  response.merge!(security_policies) if security_policies
85
99
  response
@@ -89,14 +103,16 @@ module NewRelic
89
103
  token = Agent.config[:security_policies_token]
90
104
 
91
105
  if token && !token.empty?
92
- response = invoke_remote(:preconnect, [{'security_policies_token' => token}])
106
+ response = invoke_remote(:preconnect, [{'security_policies_token' => token, 'high_security' => false}])
93
107
 
94
108
  validator = SecurityPolicySettings::Validator.new(response)
95
109
  validator.validate_matching_agent_config!
96
110
 
97
111
  response
112
+ elsif Agent.config[:high_security]
113
+ invoke_remote(:preconnect, [{'high_security' => true}])
98
114
  else
99
- invoke_remote(:preconnect, [])
115
+ invoke_remote(:preconnect, [{'high_security' => false}])
100
116
  end
101
117
  end
102
118
 
@@ -123,14 +139,13 @@ module NewRelic
123
139
 
124
140
  def metric_data(stats_hash)
125
141
  timeslice_start = stats_hash.started_at
126
- timeslice_end = stats_hash.harvested_at || Time.now
142
+ timeslice_end = stats_hash.harvested_at || Process.clock_gettime(Process::CLOCK_REALTIME)
127
143
  metric_data_array = build_metric_data_array(stats_hash)
128
- result = invoke_remote(
144
+ invoke_remote(
129
145
  :metric_data,
130
- [@agent_id, timeslice_start.to_f, timeslice_end.to_f, metric_data_array],
146
+ [@agent_id, timeslice_start, timeslice_end, metric_data_array],
131
147
  :item_count => metric_data_array.size
132
148
  )
133
- result
134
149
  end
135
150
 
136
151
  def error_data(unsent_errors)
@@ -160,10 +175,6 @@ module NewRelic
160
175
  invoke_remote(:agent_command_results, [@agent_id, results])
161
176
  end
162
177
 
163
- def get_xray_metadata(xray_ids)
164
- invoke_remote(:get_xray_metadata, [@agent_id, *xray_ids])
165
- end
166
-
167
178
  def analytic_event_data(data)
168
179
  _, items = data
169
180
  invoke_remote(:analytic_event_data, [@agent_id, *data],
@@ -176,31 +187,35 @@ module NewRelic
176
187
  :item_count => items.size)
177
188
  end
178
189
 
190
+ def log_event_data(data)
191
+ payload, size = LogEventAggregator.payload_to_melt_format(data)
192
+ invoke_remote(:log_event_data, payload, :item_count => size)
193
+ end
194
+
179
195
  def error_event_data(data)
180
196
  metadata, items = data
181
- invoke_remote(:error_event_data, [@agent_id, *data], :item_count => items.size)
197
+ response = invoke_remote(:error_event_data, [@agent_id, *data], :item_count => items.size)
182
198
  NewRelic::Agent.record_metric("Supportability/Events/TransactionError/Sent", :count => items.size)
183
199
  NewRelic::Agent.record_metric("Supportability/Events/TransactionError/Seen", :count => metadata[:events_seen])
200
+ response
184
201
  end
185
202
 
186
203
  def span_event_data(data)
187
204
  metadata, items = data
188
- invoke_remote(:span_event_data, [@agent_id, *data], :item_count => items.size)
205
+ response = invoke_remote(:span_event_data, [@agent_id, *data], :item_count => items.size)
189
206
  NewRelic::Agent.record_metric("Supportability/Events/SpanEvents/Sent", :count => items.size)
190
207
  NewRelic::Agent.record_metric("Supportability/Events/SpanEvents/Seen", :count => metadata[:events_seen])
208
+ response
191
209
  end
192
210
 
193
- # We do not compress if content is smaller than 64kb. There are
194
- # problems with bugs in Ruby in some versions that expose us
195
- # to a risk of segfaults if we compress aggressively.
196
211
  def compress_request_if_needed(data, endpoint)
197
212
  encoding = 'identity'
198
- if data.size > 64 * 1024
213
+ if data.size >= MIN_BYTE_SIZE_TO_COMPRESS
199
214
  encoding = Agent.config[:compressed_content_encoding]
200
- data = if encoding == 'gzip'
201
- Encoders::Compressed::Gzip.encode(data)
202
- else
215
+ data = if encoding == 'deflate'
203
216
  Encoders::Compressed::Deflate.encode(data)
217
+ else
218
+ Encoders::Compressed::Gzip.encode(data)
204
219
  end
205
220
  end
206
221
  check_post_size(data, endpoint)
@@ -211,10 +226,10 @@ module NewRelic
211
226
  # represents 1 tcp connection which may transmit multiple HTTP requests
212
227
  # via keep-alive.
213
228
  def session(&block)
214
- raise ArgumentError, "#{self.class}#shared_connection must be passed a block" unless block_given?
229
+ raise ArgumentError, "#{self.class}#shared_connection must be passed a block" unless block
215
230
 
216
231
  begin
217
- t0 = Time.now
232
+ t0 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
218
233
  @in_session = true
219
234
  if NewRelic::Agent.config[:aggressive_keepalive]
220
235
  session_with_keepalive(&block)
@@ -222,7 +237,7 @@ module NewRelic
222
237
  session_without_keepalive(&block)
223
238
  end
224
239
  rescue *CONNECTION_ERRORS => e
225
- elapsed = Time.now - t0
240
+ elapsed = Process.clock_gettime(Process::CLOCK_MONOTONIC) - t0
226
241
  raise NewRelic::Agent::ServerConnectionException, "Recoverable error connecting to #{@collector} after #{elapsed} seconds: #{e}"
227
242
  ensure
228
243
  @in_session = false
@@ -231,22 +246,20 @@ module NewRelic
231
246
 
232
247
  def session_with_keepalive(&block)
233
248
  establish_shared_connection
234
- block.call
249
+ yield
235
250
  end
236
251
 
237
252
  def session_without_keepalive(&block)
238
253
  begin
239
254
  establish_shared_connection
240
- block.call
255
+ yield
241
256
  ensure
242
257
  close_shared_connection
243
258
  end
244
259
  end
245
260
 
246
261
  def establish_shared_connection
247
- unless @shared_tcp_connection
248
- @shared_tcp_connection = create_and_start_http_connection
249
- end
262
+ @shared_tcp_connection ||= create_and_start_http_connection
250
263
  @shared_tcp_connection
251
264
  end
252
265
 
@@ -288,14 +301,22 @@ module NewRelic
288
301
  # Jruby 1.6.8 requires a gem for full ssl support and will throw
289
302
  # an error when use_ssl=(true) is called and jruby-openssl isn't
290
303
  # installed
291
- conn.use_ssl = true
304
+ conn.use_ssl = true
292
305
  conn.verify_mode = OpenSSL::SSL::VERIFY_PEER
293
- conn.cert_store = ssl_cert_store
306
+ set_cert_store(conn)
294
307
  rescue StandardError, LoadError
295
308
  msg = "SSL is not available in the environment; please install SSL support."
296
309
  raise UnrecoverableAgentException.new(msg)
297
310
  end
298
311
 
312
+ def set_cert_store(conn)
313
+ if NewRelic::Agent.config[:ca_bundle_path]
314
+ conn.cert_store = ssl_cert_store
315
+ else
316
+ ::NewRelic::Agent.logger.debug("Using default security certificates")
317
+ end
318
+ end
319
+
299
320
  def start_connection(conn)
300
321
  NewRelic::Agent.logger.debug("Opening TCP connection to #{conn.address}:#{conn.port}")
301
322
  Timeout.timeout(@request_timeout) { conn.start }
@@ -312,20 +333,7 @@ module NewRelic
312
333
  end
313
334
 
314
335
  def create_http_connection
315
- if Agent.config[:proxy_host]
316
- ::NewRelic::Agent.logger.debug("Using proxy server #{Agent.config[:proxy_host]}:#{Agent.config[:proxy_port]}")
317
-
318
- proxy = Net::HTTP::Proxy(
319
- Agent.config[:proxy_host],
320
- Agent.config[:proxy_port],
321
- Agent.config[:proxy_user],
322
- Agent.config[:proxy_pass]
323
- )
324
- conn = proxy.new(@collector.name, @collector.port)
325
- else
326
- conn = Net::HTTP.new(@collector.name, @collector.port)
327
- end
328
-
336
+ conn = prep_connection
329
337
  setup_connection_for_ssl(conn)
330
338
  setup_connection_timeouts(conn)
331
339
 
@@ -333,20 +341,38 @@ module NewRelic
333
341
  conn
334
342
  end
335
343
 
344
+ def prep_connection
345
+ return Net::HTTP.new(@collector.name, @collector.port) unless Agent.config[:proxy_host]
346
+
347
+ ::NewRelic::Agent.logger.debug("Using proxy server #{Agent.config[:proxy_host]}:#{Agent.config[:proxy_port]}")
348
+ prep_proxy_connection
349
+ end
350
+
351
+ def prep_proxy_connection
352
+ proxy = Net::HTTP::Proxy(
353
+ Agent.config[:proxy_host],
354
+ Agent.config[:proxy_port],
355
+ Agent.config[:proxy_user],
356
+ Agent.config[:proxy_pass]
357
+ )
358
+ proxy.new(@collector.name, @collector.port)
359
+ end
360
+
336
361
  def create_and_start_http_connection
337
362
  conn = create_http_connection
338
363
  start_connection(conn)
339
364
  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.")
367
+ raise
340
368
  end
341
369
 
342
370
  # The path to the certificate file used to verify the SSL
343
371
  # connection if verify_peer is enabled
344
372
  def cert_file_path
345
373
  if path_override = NewRelic::Agent.config[:ca_bundle_path]
346
- NewRelic::Agent.logger.warn("Couldn't find CA bundle from configured ca_bundle_path: #{path_override}") unless File.exist? path_override
374
+ NewRelic::Agent.logger.warn("Couldn't find CA bundle from configured ca_bundle_path: #{path_override}") unless File.exist?(path_override)
347
375
  path_override
348
- else
349
- File.expand_path(File.join(control.newrelic_root, 'cert', 'cacert.pem'))
350
376
  end
351
377
  end
352
378
 
@@ -365,6 +391,116 @@ module NewRelic
365
391
  NewRelic::Control.instance
366
392
  end
367
393
 
394
+ def prep_headers(opts)
395
+ headers = {
396
+ 'Content-Encoding' => opts[:encoding],
397
+ 'Host' => opts[:collector].name
398
+ }
399
+ headers.merge!(@request_headers_map) if @request_headers_map
400
+ headers
401
+ end
402
+
403
+ def prep_request(opts)
404
+ headers = prep_headers(opts)
405
+ if Agent.config[:put_for_data_send]
406
+ request = Net::HTTP::Put.new(opts[:uri], headers)
407
+ else
408
+ request = Net::HTTP::Post.new(opts[:uri], headers)
409
+ end
410
+ @audit_logger.log_request_headers(opts[:uri], headers)
411
+ request['user-agent'] = user_agent
412
+ request.content_type = "application/octet-stream"
413
+ request.body = opts[:data]
414
+ request
415
+ end
416
+
417
+ def relay_request(request, opts)
418
+ response = nil
419
+ attempts = 0
420
+
421
+ begin
422
+ attempts += 1
423
+ response = attempt_request(request, opts)
424
+ rescue *CONNECTION_ERRORS => e
425
+ close_shared_connection
426
+ if attempts < MAX_ATTEMPTS
427
+ ::NewRelic::Agent.logger.debug("Retrying request to #{opts[:collector]}#{opts[:uri]} after #{e}")
428
+ retry
429
+ else
430
+ raise ServerConnectionException, "Recoverable error talking to #{@collector} after #{attempts} attempts: #{e}"
431
+ end
432
+ end
433
+
434
+ log_response(response)
435
+ response
436
+ end
437
+
438
+ def attempt_request(request, opts)
439
+ response = nil
440
+ 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
446
+ end
447
+
448
+ def handle_error_response(response, endpoint)
449
+ case response
450
+ when Net::HTTPRequestTimeOut,
451
+ Net::HTTPTooManyRequests,
452
+ Net::HTTPInternalServerError,
453
+ Net::HTTPServiceUnavailable
454
+ handle_server_connection_exception(response, endpoint)
455
+ when Net::HTTPBadRequest,
456
+ Net::HTTPForbidden,
457
+ Net::HTTPNotFound,
458
+ Net::HTTPMethodNotAllowed,
459
+ Net::HTTPProxyAuthenticationRequired,
460
+ Net::HTTPLengthRequired,
461
+ Net::HTTPRequestEntityTooLarge,
462
+ Net::HTTPRequestURITooLong,
463
+ Net::HTTPUnsupportedMediaType,
464
+ Net::HTTPExpectationFailed,
465
+ Net::HTTPUnsupportedMediaType,
466
+ Net::HTTPRequestHeaderFieldsTooLarge
467
+ handle_unrecoverable_server_exception(response, endpoint)
468
+ when Net::HTTPConflict,
469
+ Net::HTTPUnauthorized
470
+ handle_unauthorized_error_response(response, endpoint)
471
+ raise ForceRestartException, "#{response.code}: #{response.message}"
472
+ when Net::HTTPGone
473
+ handle_gone_response(response, endpoint)
474
+ else
475
+ record_endpoint_attempts_supportability_metrics(endpoint)
476
+ record_error_response_supportability_metrics(response.code)
477
+ raise UnrecoverableServerException, "#{response.code}: #{response.message}"
478
+ end
479
+ response
480
+ end
481
+
482
+ def handle_server_connection_exception(response, endpoint)
483
+ record_endpoint_attempts_supportability_metrics(endpoint)
484
+ raise ServerConnectionException, "#{response.code}: #{response.message}"
485
+ end
486
+
487
+ def handle_unrecoverable_server_exception(response, endpoint)
488
+ record_endpoint_attempts_supportability_metrics(endpoint)
489
+ record_error_response_supportability_metrics(response.code)
490
+ raise UnrecoverableServerException, "#{response.code}: #{response.message}"
491
+ end
492
+
493
+ def handle_unauthorized_error_response(response, endpoint)
494
+ record_endpoint_attempts_supportability_metrics(endpoint)
495
+ record_error_response_supportability_metrics(response.code)
496
+ end
497
+
498
+ def handle_gone_response(response, endpoint)
499
+ record_endpoint_attempts_supportability_metrics(endpoint)
500
+ record_error_response_supportability_metrics(response.code)
501
+ raise ForceDisconnectException, "#{response.code}: #{response.message}"
502
+ end
503
+
368
504
  def remote_method_uri(method)
369
505
  @remote_method_uris[method]
370
506
  end
@@ -378,16 +514,17 @@ module NewRelic
378
514
  def generate_remote_method_uri(method)
379
515
  params = {
380
516
  'protocol_version' => PROTOCOL_VERSION,
381
- 'license_key' => license_key,
382
- 'run_id' => @agent_id,
383
- 'method' => method,
384
- 'marshal_format' => 'json', # Other formats are explicitly
385
- # ruled out; see the initializer
517
+ 'license_key' => license_key,
518
+ 'run_id' => @agent_id,
519
+ 'method' => method,
520
+ 'marshal_format' => 'json' # Other formats are explicitly
521
+ # ruled out; see the initializer
386
522
  }
387
523
 
388
- uri = "/agent_listener/invoke_raw_method?"
389
- uri << params.map do |k,v|
524
+ uri = String.new('/agent_listener/invoke_raw_method?')
525
+ uri << params.map do |k, v|
390
526
  next unless v
527
+
391
528
  "#{k}=#{v}"
392
529
  end.compact.join('&')
393
530
  uri
@@ -402,52 +539,35 @@ module NewRelic
402
539
  # enough to be worth compressing, and handles any errors the
403
540
  # server may return
404
541
  def invoke_remote(method, payload = [], options = {})
405
- start_ts = Time.now
406
-
407
- data, size, serialize_finish_ts = nil
408
- begin
409
- data = @marshaller.dump(payload, options)
410
- rescue StandardError, SystemStackError => e
411
- handle_serialization_error(method, e)
412
- end
413
- serialize_finish_ts = Time.now
414
-
415
- data, encoding = compress_request_if_needed(data, method)
416
- size = data.size
417
-
418
- uri = remote_method_uri(method)
419
- full_uri = "#{@collector}#{uri}"
420
-
421
- @audit_logger.log_request(full_uri, payload, @marshaller)
422
- response = send_request(:data => data,
423
- :uri => uri,
424
- :encoding => encoding,
425
- :collector => @collector)
542
+ start_ts = Process.clock_gettime(Process::CLOCK_MONOTONIC)
543
+ request_send_ts, response_check_ts = nil
544
+ data, encoding, size, serialize_finish_ts = marshal_payload(method, payload, options)
545
+ prep_collector(method)
546
+ response, request_send_ts, response_check_ts = invoke_remote_send_request(method, payload, data, encoding)
426
547
  @marshaller.load(decompress_response(response))
427
548
  ensure
428
- record_timing_supportability_metrics(method, start_ts, serialize_finish_ts)
429
- if size
430
- record_size_supportability_metrics(method, size, options[:item_count])
431
- end
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
432
551
  end
433
552
 
434
553
  def handle_serialization_error(method, e)
435
554
  NewRelic::Agent.increment_metric("Supportability/serialization_failure")
436
555
  NewRelic::Agent.increment_metric("Supportability/serialization_failure/#{method}")
437
- msg = "Failed to serialize #{method} data using #{@marshaller.class.to_s}: #{e.inspect}"
556
+ msg = "Failed to serialize #{method} data using #{@marshaller.class}: #{e.inspect}"
438
557
  error = SerializationError.new(msg)
439
558
  error.set_backtrace(e.backtrace)
440
559
  raise error
441
560
  end
442
561
 
443
- def record_timing_supportability_metrics(method, start_ts, serialize_finish_ts)
562
+ def record_timing_supportability_metrics(method, start_ts, serialize_finish_ts, request_send_ts, response_check_ts)
444
563
  serialize_time = serialize_finish_ts && (serialize_finish_ts - start_ts)
445
- duration = (Time.now - start_ts).to_f
446
- NewRelic::Agent.record_metric("Supportability/invoke_remote", duration)
447
- NewRelic::Agent.record_metric("Supportability/invoke_remote/#{method.to_s}", duration)
564
+ request_duration = response_check_ts && (response_check_ts - request_send_ts)
565
+ if request_duration
566
+ NewRelic::Agent.record_metric("Supportability/Agent/Collector/#{method}/Duration", request_duration)
567
+ end
448
568
  if serialize_time
449
569
  NewRelic::Agent.record_metric("Supportability/invoke_remote_serialize", serialize_time)
450
- NewRelic::Agent.record_metric("Supportability/invoke_remote_serialize/#{method.to_s}", serialize_time)
570
+ NewRelic::Agent.record_metric("Supportability/invoke_remote_serialize/#{method}", serialize_time)
451
571
  end
452
572
  end
453
573
 
@@ -461,8 +581,8 @@ module NewRelic
461
581
  # of items as arguments.
462
582
  def record_size_supportability_metrics(method, size_bytes, item_count)
463
583
  metrics = [
464
- "Supportability/invoke_remote_size",
465
- "Supportability/invoke_remote_size/#{method.to_s}"
584
+ "Supportability/Ruby/Collector/Output/Bytes",
585
+ "Supportability/Ruby/Collector/#{method}/Output/Bytes"
466
586
  ]
467
587
  # we may not have an item count, in which case, just record 0 for the exclusive time
468
588
  item_count ||= 0
@@ -473,8 +593,9 @@ module NewRelic
473
593
  # than the limit configured in the control object
474
594
  def check_post_size(post_string, endpoint)
475
595
  return if post_string.size < Agent.config[:max_payload_size_in_bytes]
476
- ::NewRelic::Agent.logger.debug "Tried to send too much data: #{post_string.size} bytes"
477
- NewRelic::Agent.increment_metric("Supportability/Agent/Collector/#{endpoint}/MaxPayloadSizeLimit")
596
+
597
+ ::NewRelic::Agent.logger.debug("Tried to send too much data: #{post_string.size} bytes")
598
+ NewRelic::Agent.increment_metric("Supportability/Ruby/Collector/#{endpoint}/MaxPayloadSizeLimit")
478
599
  raise UnrecoverableServerException.new('413 Request Entity Too Large')
479
600
  end
480
601
 
@@ -489,69 +610,33 @@ module NewRelic
489
610
  # contact
490
611
  # - :data => the data to send as the body of the request
491
612
  def send_request(opts)
492
- if Agent.config[:put_for_data_send]
493
- request = Net::HTTP::Put.new(opts[:uri], 'CONTENT-ENCODING' => opts[:encoding], 'HOST' => opts[:collector].name)
494
- else
495
- request = Net::HTTP::Post.new(opts[:uri], 'CONTENT-ENCODING' => opts[:encoding], 'HOST' => opts[:collector].name)
496
- end
497
- request['user-agent'] = user_agent
498
- request.content_type = "application/octet-stream"
499
- request.body = opts[:data]
500
-
501
- response = nil
502
- attempts = 0
503
- max_attempts = 2
613
+ request = prep_request(opts)
614
+ response = relay_request(request, opts)
615
+ return response if response.is_a?(Net::HTTPSuccess) || response.is_a?(Net::HTTPAccepted)
504
616
 
505
- begin
506
- attempts += 1
507
- conn = http_connection
508
- ::NewRelic::Agent.logger.debug "Sending request to #{opts[:collector]}#{opts[:uri]} with #{request.method}"
509
- Timeout.timeout(@request_timeout) do
510
- response = conn.request(request)
511
- end
512
- rescue *CONNECTION_ERRORS => e
513
- close_shared_connection
514
- if attempts < max_attempts
515
- ::NewRelic::Agent.logger.debug("Retrying request to #{opts[:collector]}#{opts[:uri]} after #{e}")
516
- retry
517
- else
518
- raise ServerConnectionException, "Recoverable error talking to #{@collector} after #{attempts} attempts: #{e}"
519
- end
520
- end
617
+ handle_error_response(response, opts[:endpoint])
618
+ end
521
619
 
522
- log_response(response)
620
+ def log_response(response)
621
+ ::NewRelic::Agent.logger.debug("Received response, status: #{response.code}, encoding: '#{response['content-encoding']}'")
622
+ end
523
623
 
524
- case response
525
- when Net::HTTPSuccess
526
- true # do nothing
527
- when Net::HTTPUnauthorized
528
- raise LicenseException, 'Invalid license key, please visit support.newrelic.com'
529
- when Net::HTTPServiceUnavailable
530
- raise ServerConnectionException, "Service unavailable (#{response.code}): #{response.message}"
531
- when Net::HTTPGatewayTimeOut
532
- raise ServerConnectionException, "Gateway timeout (#{response.code}): #{response.message}"
533
- when Net::HTTPRequestEntityTooLarge
534
- raise UnrecoverableServerException, '413 Request Entity Too Large'
535
- when Net::HTTPUnsupportedMediaType
536
- raise UnrecoverableServerException, '415 Unsupported Media Type'
537
- else
538
- raise ServerConnectionException, "Unexpected response from server (#{response.code}): #{response.message}"
539
- end
540
- response
624
+ # Per protocol 17, this metric should be recorded for all error response codes
625
+ # that cause data to be discarded.
626
+ def record_error_response_supportability_metrics(response_code)
627
+ ::NewRelic::Agent.increment_metric("Supportability/Agent/Collector/HTTPError/#{response_code}")
541
628
  end
542
629
 
543
- def log_response(response)
544
- ::NewRelic::Agent.logger.debug "Received response, status: #{response.code}, encoding: '#{response['content-encoding']}'"
630
+ def record_endpoint_attempts_supportability_metrics(endpoint)
631
+ ::NewRelic::Agent.increment_metric("Supportability/Agent/Collector/#{endpoint}/Attempts")
545
632
  end
546
633
 
547
634
  # Decompresses the response from the server, if it is gzip
548
635
  # encoded, otherwise returns it verbatim
549
636
  def decompress_response(response)
550
- if response['content-encoding'] == 'gzip'
551
- Zlib::GzipReader.new(StringIO.new(response.body)).read
552
- else
553
- response.body
554
- end
637
+ return response.body unless response['content-encoding'] == 'gzip'
638
+
639
+ Zlib::GzipReader.new(StringIO.new(response.body)).read
555
640
  end
556
641
 
557
642
  # Sets the user agent for connections to the server, to
@@ -559,16 +644,47 @@ module NewRelic
559
644
  # the ruby version and also zlib version if available since
560
645
  # that may cause corrupt compression if there is a problem.
561
646
  def user_agent
562
- ruby_description = ''
563
- # note the trailing space!
564
- ruby_description << "(ruby #{::RUBY_VERSION} #{::RUBY_PLATFORM}) " if defined?(::RUBY_VERSION) && defined?(::RUBY_PLATFORM)
565
- zlib_version = ''
566
- zlib_version << "zlib/#{Zlib.zlib_version}" if defined?(::Zlib) && Zlib.respond_to?(:zlib_version)
647
+ if defined?(::RUBY_VERSION) && defined?(::RUBY_PLATFORM)
648
+ ruby_description = "(ruby #{::RUBY_VERSION} #{::RUBY_PLATFORM}) " # NOTE: the trailing space!
649
+ end
650
+ zlib_version = "zlib/#{Zlib.zlib_version}" if defined?(::Zlib) && Zlib.respond_to?(:zlib_version)
567
651
  "NewRelic-RubyAgent/#{NewRelic::VERSION::STRING} #{ruby_description}#{zlib_version}"
568
652
  end
569
653
 
570
- # Used to wrap errors reported to agent by the collector
571
- class CollectorError < StandardError; end
654
+ def marshal_payload(method, payload, options)
655
+ begin
656
+ data = @marshaller.dump(payload, options)
657
+ rescue StandardError, SystemStackError => e
658
+ handle_serialization_error(method, e)
659
+ end
660
+ serialize_finish_ts = Process.clock_gettime(Process::CLOCK_MONOTONIC)
661
+
662
+ size = data.size # only the uncompressed size is reported
663
+ data, encoding = compress_request_if_needed(data, method)
664
+
665
+ [data, encoding, size, serialize_finish_ts]
666
+ end
667
+
668
+ def prep_collector(method)
669
+ # Preconnect needs to always use the configured collector host, not the redirect host
670
+ # We reset it here so we are always using the configured collector during our creation of the new connection
671
+ # and we also don't want to keep the previous redirect host around anymore
672
+ @collector = @configured_collector if method == :preconnect
673
+ end
674
+
675
+ def invoke_remote_send_request(method, payload, data, encoding)
676
+ uri = remote_method_uri(method)
677
+ full_uri = "#{@collector}#{uri}"
678
+
679
+ @audit_logger.log_request(full_uri, payload, @marshaller)
680
+ request_send_ts = Process.clock_gettime(Process::CLOCK_MONOTONIC)
681
+ response = send_request(:data => data,
682
+ :uri => uri,
683
+ :encoding => encoding,
684
+ :collector => @collector,
685
+ :endpoint => method)
686
+ [response, request_send_ts, Process.clock_gettime(Process::CLOCK_MONOTONIC)]
687
+ end
572
688
  end
573
689
  end
574
690
  end