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
@@ -0,0 +1,227 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ module NewRelic
6
+ module Agent
7
+ module AgentHelpers
8
+ # This module is an artifact of a refactoring of the connect
9
+ # method - all of its methods are used in that context, so it
10
+ # can be refactored at will. It should be fully tested
11
+ module Connect
12
+ # number of attempts we've made to contact the server
13
+ attr_accessor :connect_attempts
14
+
15
+ # Disconnect just sets the connect state to disconnected, preventing
16
+ # further retries.
17
+ def disconnect
18
+ @connect_state = :disconnected
19
+ true
20
+ end
21
+
22
+ def connected?
23
+ @connect_state == :connected
24
+ end
25
+
26
+ def disconnected?
27
+ @connect_state == :disconnected
28
+ end
29
+
30
+ # Don't connect if we're already connected, or if we tried to connect
31
+ # and were rejected with prejudice because of a license issue, unless
32
+ # we're forced to by force_reconnect.
33
+ def should_connect?(force = false)
34
+ force || (!connected? && !disconnected?)
35
+ end
36
+
37
+ # Per the spec at
38
+ # /agents/agent-specs/Collector-Response-Handling.md, retry
39
+ # connections after a specific backoff sequence to prevent
40
+ # hammering the server.
41
+ def connect_retry_period
42
+ NewRelic::CONNECT_RETRY_PERIODS[connect_attempts] || NewRelic::MAX_RETRY_PERIOD
43
+ end
44
+
45
+ def note_connect_failure
46
+ self.connect_attempts += 1
47
+ end
48
+
49
+ # When we have a problem connecting to the server, we need
50
+ # to tell the user what happened, since this is not an error
51
+ # we can handle gracefully.
52
+ def log_error(error)
53
+ ::NewRelic::Agent.logger.error("Error establishing connection with New Relic Service at #{control.server}:",
54
+ error)
55
+ end
56
+
57
+ # When the server sends us an error with the license key, we
58
+ # want to tell the user that something went wrong, and let
59
+ # them know where to go to get a valid license key
60
+ #
61
+ # After this runs, it disconnects the agent so that it will
62
+ # no longer try to connect to the server, saving the
63
+ # application and the server load
64
+ def handle_license_error(error)
65
+ ::NewRelic::Agent.logger.error( \
66
+ error.message, \
67
+ "Visit NewRelic.com to obtain a valid license key, or to upgrade your account."
68
+ )
69
+ disconnect
70
+ end
71
+
72
+ def handle_unrecoverable_agent_error(error)
73
+ ::NewRelic::Agent.logger.error(error.message)
74
+ disconnect
75
+ shutdown
76
+ end
77
+
78
+ # Checks whether we should send environment info, and if so,
79
+ # returns the snapshot from the local environment.
80
+ # Generating the EnvironmentReport has the potential to trigger
81
+ # require calls in Rails environments, so this method should only
82
+ # be called synchronously from on the main thread.
83
+ def environment_for_connect
84
+ @environment_report ||= Agent.config[:send_environment_info] ? Array(EnvironmentReport.new) : []
85
+ end
86
+
87
+ # Constructs and memoizes an event_harvest_config hash to be used in
88
+ # the payload sent during connect (and reconnect)
89
+ def event_harvest_config
90
+ @event_harvest_config ||= Configuration::EventHarvestConfig.from_config(Agent.config)
91
+ end
92
+
93
+ # Builds the payload to send to the connect service,
94
+ # connects, then configures the agent using the response from
95
+ # the connect service
96
+ def connect_to_server
97
+ request_builder = ::NewRelic::Agent::Connect::RequestBuilder.new( \
98
+ @service,
99
+ Agent.config,
100
+ event_harvest_config,
101
+ environment_for_connect
102
+ )
103
+ connect_response = @service.connect(request_builder.connect_payload)
104
+
105
+ response_handler = ::NewRelic::Agent::Connect::ResponseHandler.new(self, Agent.config)
106
+ response_handler.configure_agent(connect_response)
107
+
108
+ log_connection(connect_response) if connect_response
109
+ connect_response
110
+ end
111
+
112
+ # Logs when we connect to the server, for debugging purposes
113
+ # - makes sure we know if an agent has not connected
114
+ def log_connection(config_data)
115
+ ::NewRelic::Agent.logger.debug("Connected to NewRelic Service at #{@service.collector.name}")
116
+ ::NewRelic::Agent.logger.debug("Agent Run = #{@service.agent_id}.")
117
+ ::NewRelic::Agent.logger.debug("Connection data = #{config_data.inspect}")
118
+ if config_data['messages'] && config_data['messages'].any?
119
+ log_collector_messages(config_data['messages'])
120
+ end
121
+ end
122
+
123
+ def log_collector_messages(messages)
124
+ messages.each do |message|
125
+ ::NewRelic::Agent.logger.send(message['level'].downcase, message['message'])
126
+ end
127
+ end
128
+
129
+ # apdex_f is always 4 times the apdex_t
130
+ def apdex_f
131
+ (Agent.config[:apdex_t] * 4).to_f
132
+ end
133
+
134
+ class WaitOnConnectTimeout < StandardError
135
+ end
136
+
137
+ # Used for testing to let us know we've actually started to wait
138
+ def waited_on_connect?
139
+ @waited_on_connect
140
+ end
141
+
142
+ def signal_connected
143
+ @wait_on_connect_mutex.synchronize do
144
+ @wait_on_connect_condition.signal
145
+ end
146
+ end
147
+
148
+ def wait_on_connect(timeout)
149
+ return if connected?
150
+
151
+ @waited_on_connect = true
152
+ NewRelic::Agent.logger.debug("Waiting on connect to complete.")
153
+
154
+ @wait_on_connect_mutex.synchronize do
155
+ @wait_on_connect_condition.wait(@wait_on_connect_mutex, timeout)
156
+ end
157
+
158
+ unless connected?
159
+ raise WaitOnConnectTimeout, "Agent was unable to connect in #{timeout} seconds."
160
+ end
161
+ end
162
+
163
+ def connect_options(options)
164
+ {
165
+ keep_retrying: true,
166
+ force_reconnect: Agent.config[:force_reconnect]
167
+ }.merge(options)
168
+ end
169
+
170
+ # Establish a connection to New Relic servers.
171
+ #
172
+ # By default, if a connection has already been established, this method
173
+ # will be a no-op.
174
+ #
175
+ # @param [Hash] options
176
+ # @option options [Boolean] :keep_retrying (true)
177
+ # If true, this method will block until a connection is successfully
178
+ # established, continuing to retry upon failure. If false, this method
179
+ # will return after either successfully connecting, or after failing
180
+ # once.
181
+ #
182
+ # @option options [Boolean] :force_reconnect (false)
183
+ # If true, this method will force establishment of a new connection
184
+ # with New Relic, even if there is already an existing connection.
185
+ # This is useful primarily when re-establishing a new connection after
186
+ # forking off from a parent process.
187
+ #
188
+ def connect(options = {})
189
+ opts = connect_options(options)
190
+ return unless should_connect?(opts[:force_reconnect])
191
+
192
+ ::NewRelic::Agent.logger.debug("Connecting Process to New Relic: #$0")
193
+ connect_to_server
194
+ @connected_pid = $$
195
+ @connect_state = :connected
196
+ signal_connected
197
+ rescue NewRelic::Agent::ForceDisconnectException => e
198
+ handle_force_disconnect(e)
199
+ rescue NewRelic::Agent::LicenseException => e
200
+ handle_license_error(e)
201
+ rescue NewRelic::Agent::UnrecoverableAgentException => e
202
+ handle_unrecoverable_agent_error(e)
203
+ rescue StandardError, Timeout::Error, NewRelic::Agent::ServerConnectionException => e
204
+ retry if retry_from_error?(e, opts)
205
+ rescue Exception => e
206
+ ::NewRelic::Agent.logger.error("Exception of unexpected type during Agent#connect():", e)
207
+
208
+ raise
209
+ end
210
+
211
+ def retry_from_error?(e, opts)
212
+ # Allow a killed (aborting) thread to continue exiting during shutdown.
213
+ # See: https://github.com/newrelic/newrelic-ruby-agent/issues/340
214
+ raise if Thread.current.status == 'aborting'
215
+
216
+ log_error(e)
217
+ return false unless opts[:keep_retrying]
218
+
219
+ note_connect_failure
220
+ ::NewRelic::Agent.logger.info("Will re-attempt in #{connect_retry_period} seconds")
221
+ sleep(connect_retry_period)
222
+ true
223
+ end
224
+ end
225
+ end
226
+ end
227
+ end
@@ -0,0 +1,153 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ module NewRelic
6
+ module Agent
7
+ module AgentHelpers
8
+ module Harvest
9
+ # Harvests data from the given container, sends it to the named endpoint
10
+ # on the service, and automatically merges back in upon a recoverable
11
+ # failure.
12
+ #
13
+ # The given container should respond to:
14
+ #
15
+ # #harvest!
16
+ # returns a payload that contains enumerable collection of data items and
17
+ # optional metadata to be sent to the collector.
18
+ #
19
+ # #reset!
20
+ # drop any stored data and reset to a clean state.
21
+ #
22
+ # #merge!(payload)
23
+ # merge the given payload back into the internal buffer of the
24
+ # container, so that it may be harvested again later.
25
+ #
26
+ def harvest_and_send_from_container(container, endpoint)
27
+ payload = harvest_from_container(container, endpoint)
28
+ sample_count = harvest_size(container, payload)
29
+ if sample_count > 0
30
+ NewRelic::Agent.logger.debug("Sending #{sample_count} items to #{endpoint}")
31
+ send_data_to_endpoint(endpoint, payload, container)
32
+ end
33
+ end
34
+
35
+ def harvest_size(container, items)
36
+ if container.respond_to?(:has_metadata?) && container.has_metadata? && !items.empty?
37
+ items.last.size
38
+ else
39
+ items.size
40
+ end
41
+ end
42
+
43
+ def harvest_from_container(container, endpoint)
44
+ items = []
45
+ begin
46
+ items = container.harvest!
47
+ rescue => e
48
+ NewRelic::Agent.logger.error("Failed to harvest #{endpoint} data, resetting. Error: ", e)
49
+ container.reset!
50
+ end
51
+ items
52
+ end
53
+
54
+ def harvest_and_send_timeslice_data
55
+ TransactionTimeAggregator.harvest!
56
+ harvest_and_send_from_container(@stats_engine, :metric_data)
57
+ end
58
+
59
+ def harvest_and_send_slowest_sql
60
+ harvest_and_send_from_container(@sql_sampler, :sql_trace_data)
61
+ end
62
+
63
+ # This handles getting the transaction traces and then sending
64
+ # them across the wire. This includes gathering SQL
65
+ # explanations, stripping out stack traces, and normalizing
66
+ # SQL. note that we explain only the sql statements whose
67
+ # nodes' execution times exceed our threshold (to avoid
68
+ # unnecessary overhead of running explains on fast queries.)
69
+ def harvest_and_send_transaction_traces
70
+ harvest_and_send_from_container(@transaction_sampler, :transaction_sample_data)
71
+ end
72
+
73
+ def harvest_and_send_for_agent_commands
74
+ harvest_and_send_from_container(@agent_command_router, :profile_data)
75
+ end
76
+
77
+ def harvest_and_send_errors
78
+ harvest_and_send_from_container(@error_collector.error_trace_aggregator, :error_data)
79
+ end
80
+
81
+ def harvest_and_send_analytic_event_data
82
+ harvest_and_send_from_container(transaction_event_aggregator, :analytic_event_data)
83
+ harvest_and_send_from_container(synthetics_event_aggregator, :analytic_event_data)
84
+ end
85
+
86
+ def harvest_and_send_custom_event_data
87
+ harvest_and_send_from_container(@custom_event_aggregator, :custom_event_data)
88
+ end
89
+
90
+ def harvest_and_send_error_event_data
91
+ harvest_and_send_from_container(@error_collector.error_event_aggregator, :error_event_data)
92
+ end
93
+
94
+ def harvest_and_send_span_event_data
95
+ harvest_and_send_from_container(span_event_aggregator, :span_event_data)
96
+ end
97
+
98
+ def harvest_and_send_log_event_data
99
+ harvest_and_send_from_container(@log_event_aggregator, :log_event_data)
100
+ end
101
+
102
+ def harvest_and_send_data_types
103
+ harvest_and_send_errors
104
+ harvest_and_send_error_event_data
105
+ harvest_and_send_transaction_traces
106
+ harvest_and_send_slowest_sql
107
+ harvest_and_send_timeslice_data
108
+ harvest_and_send_span_event_data
109
+ harvest_and_send_log_event_data
110
+ end
111
+
112
+ def send_data_to_endpoint(endpoint, payload, container)
113
+ begin
114
+ @service.send(endpoint, payload)
115
+ rescue ForceRestartException, ForceDisconnectException
116
+ raise
117
+ rescue SerializationError => e
118
+ NewRelic::Agent.logger.warn("Failed to serialize data for #{endpoint}, discarding. Error: ", e)
119
+ rescue UnrecoverableServerException => e
120
+ NewRelic::Agent.logger.warn("#{endpoint} data was rejected by remote service, discarding. Error: ", e)
121
+ rescue ServerConnectionException => e
122
+ log_remote_unavailable(endpoint, e)
123
+ container.merge!(payload)
124
+ rescue => e
125
+ NewRelic::Agent.logger.info("Unable to send #{endpoint} data, will try again later. Error: ", e)
126
+ container.merge!(payload)
127
+ end
128
+ end
129
+
130
+ def check_for_and_handle_agent_commands
131
+ begin
132
+ @agent_command_router.check_for_and_handle_agent_commands
133
+ rescue ForceRestartException, ForceDisconnectException
134
+ raise
135
+ rescue UnrecoverableServerException => e
136
+ NewRelic::Agent.logger.warn("get_agent_commands message was rejected by remote service, discarding. " \
137
+ "Error: ", e)
138
+ rescue ServerConnectionException => e
139
+ log_remote_unavailable(:get_agent_commands, e)
140
+ rescue => e
141
+ NewRelic::Agent.logger.info("Error during check_for_and_handle_agent_commands, will retry later: ", e)
142
+ end
143
+ end
144
+
145
+ def log_remote_unavailable(endpoint, e)
146
+ NewRelic::Agent.logger.debug("Unable to send #{endpoint} data, will try again later. Error: ", e)
147
+ NewRelic::Agent.record_metric("Supportability/remote_unavailable", 0.0)
148
+ NewRelic::Agent.record_metric("Supportability/remote_unavailable/#{endpoint.to_s}", 0.0)
149
+ end
150
+ end
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,72 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ module NewRelic
6
+ module Agent
7
+ module AgentHelpers
8
+ module Shutdown
9
+ # Attempt a graceful shutdown of the agent, flushing any remaining
10
+ # data.
11
+ def shutdown
12
+ return unless started?
13
+
14
+ ::NewRelic::Agent.logger.info("Starting Agent shutdown")
15
+
16
+ stop_event_loop
17
+ trap_signals_for_litespeed
18
+ untraced_graceful_disconnect
19
+ revert_to_default_configuration
20
+
21
+ @started = nil
22
+ Control.reset
23
+ end
24
+
25
+ def untraced_graceful_disconnect
26
+ begin
27
+ NewRelic::Agent.disable_all_tracing do
28
+ graceful_disconnect
29
+ end
30
+ rescue => e
31
+ ::NewRelic::Agent.logger.error(e)
32
+ end
33
+ end
34
+
35
+ # This method contacts the server to send remaining data and
36
+ # let the server know that the agent is shutting down - this
37
+ # allows us to do things like accurately set the end of the
38
+ # lifetime of the process
39
+ #
40
+ # If this process comes from a parent process, it will not
41
+ # disconnect, so that the parent process can continue to send data
42
+ def graceful_disconnect
43
+ if connected?
44
+ begin
45
+ @service.request_timeout = 10
46
+
47
+ @events.notify(:before_shutdown)
48
+ transmit_data_types
49
+ shutdown_service
50
+
51
+ ::NewRelic::Agent.logger.debug("Graceful disconnect complete")
52
+ rescue Timeout::Error, StandardError => e
53
+ ::NewRelic::Agent.logger.debug("Error when disconnecting #{e.class.name}: #{e.message}")
54
+ end
55
+ else
56
+ ::NewRelic::Agent.logger.debug("Bypassing graceful disconnect - agent not connected")
57
+ end
58
+ end
59
+
60
+ def shutdown_service
61
+ if @connected_pid == $$ && !@service.kind_of?(NewRelic::Agent::NewRelicService)
62
+ ::NewRelic::Agent.logger.debug("Sending New Relic service agent run shutdown message")
63
+ @service.shutdown
64
+ else
65
+ ::NewRelic::Agent.logger.debug("This agent connected from parent process #{@connected_pid}--not sending " \
66
+ "shutdown")
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,74 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ module NewRelic
6
+ module Agent
7
+ module AgentHelpers
8
+ module SpecialStartup
9
+ # If we're using a dispatcher that forks before serving
10
+ # requests, we need to wait until the children are forked
11
+ # before connecting, otherwise the parent process sends useless data
12
+ def using_forking_dispatcher?
13
+ if [:puma, :passenger, :unicorn].include?(Agent.config[:dispatcher])
14
+ ::NewRelic::Agent.logger.info("Deferring startup of agent reporting thread because " \
15
+ "#{Agent.config[:dispatcher]} may fork.")
16
+ true
17
+ else
18
+ false
19
+ end
20
+ end
21
+
22
+ # Return true if we're using resque and it hasn't had a chance to (potentially)
23
+ # daemonize itself. This avoids hanging when there's a Thread started
24
+ # before Resque calls Process.daemon (Jira RUBY-857)
25
+ def defer_for_resque?
26
+ NewRelic::Agent.config[:dispatcher] == :resque &&
27
+ NewRelic::Agent::Instrumentation::Resque::Helper.resque_fork_per_job? &&
28
+ !PipeChannelManager.listener.started?
29
+ end
30
+
31
+ def in_resque_child_process?
32
+ defined?(@service) && @service.is_a?(PipeService)
33
+ end
34
+
35
+ def defer_for_delayed_job?
36
+ NewRelic::Agent.config[:dispatcher] == :delayed_job &&
37
+ !NewRelic::DelayedJobInjection.worker_name
38
+ end
39
+
40
+ # This matters when the following three criteria are met:
41
+ #
42
+ # 1. A Sinatra 'classic' application is being run
43
+ # 2. The app is being run by executing the main file directly, rather
44
+ # than via a config.ru file.
45
+ # 3. newrelic_rpm is required *after* sinatra
46
+ #
47
+ # In this case, the entire application runs from an at_exit handler in
48
+ # Sinatra, and if we were to install ours, it would be executed before
49
+ # the one in Sinatra, meaning that we'd shutdown the agent too early
50
+ # and never collect any data.
51
+ def sinatra_classic_app?
52
+ (
53
+ defined?(Sinatra::Application) &&
54
+ Sinatra::Application.respond_to?(:run) &&
55
+ Sinatra::Application.run?
56
+ )
57
+ end
58
+
59
+ def should_install_exit_handler?
60
+ return false unless Agent.config[:send_data_on_exit]
61
+
62
+ !sinatra_classic_app? || Agent.config[:force_install_exit_handler]
63
+ end
64
+
65
+ def install_exit_handler
66
+ return unless should_install_exit_handler?
67
+
68
+ NewRelic::Agent.logger.debug("Installing at_exit handler")
69
+ at_exit { shutdown }
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,167 @@
1
+ # This file is distributed under New Relic's license terms.
2
+ # See https://github.com/newrelic/newrelic-ruby-agent/blob/main/LICENSE for complete details.
3
+ # frozen_string_literal: true
4
+
5
+ module NewRelic
6
+ module Agent
7
+ module AgentHelpers
8
+ module StartWorkerThread
9
+ LOG_ONCE_KEYS_RESET_PERIOD = 60.0
10
+
11
+ TRANSACTION_EVENT_DATA = "transaction_event_data".freeze
12
+ CUSTOM_EVENT_DATA = "custom_event_data".freeze
13
+ ERROR_EVENT_DATA = "error_event_data".freeze
14
+ SPAN_EVENT_DATA = "span_event_data".freeze
15
+ LOG_EVENT_DATA = "log_event_data".freeze
16
+
17
+ # Try to launch the worker thread and connect to the server.
18
+ #
19
+ # See #connect for a description of connection_options.
20
+ def start_worker_thread(connection_options = {})
21
+ if disable = NewRelic::Agent.config[:disable_harvest_thread]
22
+ NewRelic::Agent.logger.info("Not starting Ruby Agent worker thread because :disable_harvest_thread is " \
23
+ "#{disable}")
24
+ return
25
+ end
26
+
27
+ ::NewRelic::Agent.logger.debug("Creating Ruby Agent worker thread.")
28
+ @worker_thread = Threading::AgentThread.create('Worker Loop') do
29
+ deferred_work!(connection_options)
30
+ end
31
+ end
32
+
33
+ def create_event_loop
34
+ EventLoop.new
35
+ end
36
+
37
+ # If the @worker_thread encounters an error during the attempt to connect to the collector
38
+ # then the connect attempts enter an exponential backoff retry loop. To avoid potential
39
+ # race conditions with shutting down while also attempting to reconnect, we join the
40
+ # @worker_thread with a timeout threshold. This allows potentially connecting and flushing
41
+ # pending data to the server, but without waiting indefinitely for a reconnect to succeed.
42
+ # The use-case where this typically arises is in cronjob scheduled rake tasks where there's
43
+ # also some network stability/latency issues happening.
44
+ def stop_event_loop
45
+ @event_loop.stop if @event_loop
46
+ # Wait the end of the event loop thread.
47
+ if @worker_thread
48
+ unless @worker_thread.join(3)
49
+ ::NewRelic::Agent.logger.debug("Event loop thread did not stop within 3 seconds")
50
+ end
51
+ end
52
+ end
53
+
54
+ # Certain event types may sometimes need to be on the same interval as metrics,
55
+ # so we will check config assigned in EventHarvestConfig to determine the interval
56
+ # on which to report them
57
+ def interval_for(event_type)
58
+ interval = Agent.config[:"event_report_period.#{event_type}"]
59
+ :"#{interval}_second_harvest"
60
+ end
61
+
62
+ def create_and_run_event_loop
63
+ data_harvest = :"#{Agent.config[:data_report_period]}_second_harvest"
64
+ event_harvest = :"#{Agent.config[:event_report_period]}_second_harvest"
65
+
66
+ @event_loop = create_event_loop
67
+ @event_loop.on(data_harvest) do
68
+ transmit_data
69
+ end
70
+
71
+ @event_loop.on(interval_for(TRANSACTION_EVENT_DATA)) do
72
+ transmit_analytic_event_data
73
+ end
74
+ @event_loop.on(interval_for(CUSTOM_EVENT_DATA)) do
75
+ transmit_custom_event_data
76
+ end
77
+ @event_loop.on(interval_for(ERROR_EVENT_DATA)) do
78
+ transmit_error_event_data
79
+ end
80
+ @event_loop.on(interval_for(SPAN_EVENT_DATA)) do
81
+ transmit_span_event_data
82
+ end
83
+ @event_loop.on(interval_for(LOG_EVENT_DATA)) do
84
+ transmit_log_event_data
85
+ end
86
+
87
+ @event_loop.on(:reset_log_once_keys) do
88
+ ::NewRelic::Agent.logger.clear_already_logged
89
+ end
90
+ @event_loop.fire_every(Agent.config[:data_report_period], data_harvest)
91
+ @event_loop.fire_every(Agent.config[:event_report_period], event_harvest)
92
+ @event_loop.fire_every(LOG_ONCE_KEYS_RESET_PERIOD, :reset_log_once_keys)
93
+
94
+ @event_loop.run
95
+ end
96
+
97
+ # Handles the case where the server tells us to restart -
98
+ # this clears the data, clears connection attempts, and
99
+ # waits a while to reconnect.
100
+ def handle_force_restart(error)
101
+ ::NewRelic::Agent.logger.debug(error.message)
102
+ drop_buffered_data
103
+ @service.force_restart if @service
104
+ @connect_state = :pending
105
+ sleep(30)
106
+ end
107
+
108
+ # when a disconnect is requested, stop the current thread, which
109
+ # is the worker thread that gathers data and talks to the
110
+ # server.
111
+ def handle_force_disconnect(error)
112
+ ::NewRelic::Agent.logger.warn("Agent received a ForceDisconnectException from the server, disconnecting. " \
113
+ "(#{error.message})")
114
+ disconnect
115
+ end
116
+
117
+ # Handles an unknown error in the worker thread by logging
118
+ # it and disconnecting the agent, since we are now in an
119
+ # unknown state.
120
+ def handle_other_error(error)
121
+ ::NewRelic::Agent.logger.error("Unhandled error in worker thread, disconnecting.")
122
+ # These errors are fatal (that is, they will prevent the agent from
123
+ # reporting entirely), so we really want backtraces when they happen
124
+ ::NewRelic::Agent.logger.log_exception(:error, error)
125
+ disconnect
126
+ end
127
+
128
+ # a wrapper method to handle all the errors that can happen
129
+ # in the connection and worker thread system. This
130
+ # guarantees a no-throw from the background thread.
131
+ def catch_errors
132
+ yield
133
+ rescue NewRelic::Agent::ForceRestartException => e
134
+ handle_force_restart(e)
135
+ retry
136
+ rescue NewRelic::Agent::ForceDisconnectException => e
137
+ handle_force_disconnect(e)
138
+ rescue => e
139
+ handle_other_error(e)
140
+ end
141
+
142
+ # This is the method that is run in a new thread in order to
143
+ # background the harvesting and sending of data during the
144
+ # normal operation of the agent.
145
+ #
146
+ # Takes connection options that determine how we should
147
+ # connect to the server, and loops endlessly - typically we
148
+ # never return from this method unless we're shutting down
149
+ # the agent
150
+ def deferred_work!(connection_options)
151
+ catch_errors do
152
+ NewRelic::Agent.disable_all_tracing do
153
+ connect(connection_options)
154
+ if connected?
155
+ create_and_run_event_loop
156
+ # never reaches here unless there is a problem or
157
+ # the agent is exiting
158
+ else
159
+ ::NewRelic::Agent.logger.debug("No connection. Worker thread ending.")
160
+ end
161
+ end
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end
167
+ end