newrelic_rpm 8.13.1 → 8.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -1
  3. data/.rubocop.yml +130 -1
  4. data/.rubocop_todo.yml +3 -0
  5. data/CHANGELOG.md +3284 -3148
  6. data/CONTRIBUTING.md +1 -2
  7. data/README.md +2 -1
  8. data/init.rb +1 -1
  9. data/lib/new_relic/agent/agent.rb +14 -466
  10. data/lib/new_relic/agent/agent_helpers/connect.rb +227 -0
  11. data/lib/new_relic/agent/agent_helpers/harvest.rb +153 -0
  12. data/lib/new_relic/agent/agent_helpers/shutdown.rb +72 -0
  13. data/lib/new_relic/agent/agent_helpers/special_startup.rb +75 -0
  14. data/lib/new_relic/agent/agent_helpers/start_worker_thread.rb +167 -0
  15. data/lib/new_relic/agent/agent_helpers/startup.rb +202 -0
  16. data/lib/new_relic/agent/agent_helpers/transmit.rb +76 -0
  17. data/lib/new_relic/agent/configuration/default_source.rb +47 -9
  18. data/lib/new_relic/agent/datastores.rb +2 -2
  19. data/lib/new_relic/agent/event_loop.rb +1 -1
  20. data/lib/new_relic/agent/guid_generator.rb +11 -2
  21. data/lib/new_relic/agent/heap.rb +1 -1
  22. data/lib/new_relic/agent/instrumentation/active_job.rb +7 -7
  23. data/lib/new_relic/agent/instrumentation/active_merchant.rb +2 -2
  24. data/lib/new_relic/agent/instrumentation/active_record.rb +9 -9
  25. data/lib/new_relic/agent/instrumentation/active_record_notifications.rb +24 -24
  26. data/lib/new_relic/agent/instrumentation/active_storage.rb +2 -2
  27. data/lib/new_relic/agent/instrumentation/active_support.rb +12 -0
  28. data/lib/new_relic/agent/instrumentation/active_support_logger.rb +3 -3
  29. data/lib/new_relic/agent/instrumentation/acts_as_solr.rb +2 -2
  30. data/lib/new_relic/agent/instrumentation/authlogic.rb +2 -2
  31. data/lib/new_relic/agent/instrumentation/bunny/instrumentation.rb +3 -3
  32. data/lib/new_relic/agent/instrumentation/bunny.rb +4 -4
  33. data/lib/new_relic/agent/instrumentation/concurrent_ruby/chain.rb +36 -0
  34. data/lib/new_relic/agent/instrumentation/concurrent_ruby/instrumentation.rb +21 -0
  35. data/lib/new_relic/agent/instrumentation/concurrent_ruby/prepend.rb +27 -0
  36. data/lib/new_relic/agent/instrumentation/concurrent_ruby.rb +31 -0
  37. data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +1 -1
  38. data/lib/new_relic/agent/instrumentation/curb/instrumentation.rb +1 -1
  39. data/lib/new_relic/agent/instrumentation/curb.rb +6 -6
  40. data/lib/new_relic/agent/instrumentation/custom_events_subscriber.rb +37 -0
  41. data/lib/new_relic/agent/instrumentation/data_mapper.rb +50 -50
  42. data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +5 -5
  43. data/lib/new_relic/agent/instrumentation/elasticsearch.rb +5 -5
  44. data/lib/new_relic/agent/instrumentation/excon/middleware.rb +1 -1
  45. data/lib/new_relic/agent/instrumentation/excon.rb +9 -9
  46. data/lib/new_relic/agent/instrumentation/grape.rb +8 -8
  47. data/lib/new_relic/agent/instrumentation/grpc/client/instrumentation.rb +1 -1
  48. data/lib/new_relic/agent/instrumentation/grpc_client.rb +3 -3
  49. data/lib/new_relic/agent/instrumentation/grpc_server.rb +4 -4
  50. data/lib/new_relic/agent/instrumentation/httpclient/instrumentation.rb +1 -1
  51. data/lib/new_relic/agent/instrumentation/httpclient.rb +2 -2
  52. data/lib/new_relic/agent/instrumentation/httprb/instrumentation.rb +1 -1
  53. data/lib/new_relic/agent/instrumentation/httprb.rb +3 -3
  54. data/lib/new_relic/agent/instrumentation/logger.rb +3 -3
  55. data/lib/new_relic/agent/instrumentation/memcache/instrumentation.rb +3 -3
  56. data/lib/new_relic/agent/instrumentation/memcache.rb +16 -16
  57. data/lib/new_relic/agent/instrumentation/mongo.rb +1 -1
  58. data/lib/new_relic/agent/instrumentation/net_http.rb +6 -6
  59. data/lib/new_relic/agent/instrumentation/padrino.rb +3 -3
  60. data/lib/new_relic/agent/instrumentation/passenger_instrumentation.rb +5 -5
  61. data/lib/new_relic/agent/instrumentation/rack.rb +14 -14
  62. data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +5 -5
  63. data/lib/new_relic/agent/instrumentation/rails_middleware.rb +3 -3
  64. data/lib/new_relic/agent/instrumentation/rails_notifications/action_cable.rb +6 -6
  65. data/lib/new_relic/agent/instrumentation/rails_notifications/action_controller.rb +2 -2
  66. data/lib/new_relic/agent/instrumentation/rails_notifications/action_view.rb +5 -3
  67. data/lib/new_relic/agent/instrumentation/rails_notifications/custom_events.rb +30 -0
  68. data/lib/new_relic/agent/instrumentation/rainbows_instrumentation.rb +4 -4
  69. data/lib/new_relic/agent/instrumentation/rake.rb +7 -7
  70. data/lib/new_relic/agent/instrumentation/redis/instrumentation.rb +29 -8
  71. data/lib/new_relic/agent/instrumentation/redis.rb +4 -4
  72. data/lib/new_relic/agent/instrumentation/resque.rb +9 -9
  73. data/lib/new_relic/agent/instrumentation/sequel.rb +2 -2
  74. data/lib/new_relic/agent/instrumentation/sidekiq.rb +3 -3
  75. data/lib/new_relic/agent/instrumentation/sinatra.rb +7 -7
  76. data/lib/new_relic/agent/instrumentation/sunspot.rb +4 -4
  77. data/lib/new_relic/agent/instrumentation/thread/instrumentation.rb +5 -1
  78. data/lib/new_relic/agent/instrumentation/thread.rb +3 -3
  79. data/lib/new_relic/agent/instrumentation/tilt.rb +3 -3
  80. data/lib/new_relic/agent/instrumentation/typhoeus/instrumentation.rb +2 -2
  81. data/lib/new_relic/agent/instrumentation/typhoeus.rb +1 -1
  82. data/lib/new_relic/agent/javascript_instrumentor.rb +2 -2
  83. data/lib/new_relic/agent/method_tracer_helpers.rb +6 -11
  84. data/lib/new_relic/agent/range_extensions.rb +2 -2
  85. data/lib/new_relic/agent/tracer.rb +8 -4
  86. data/lib/new_relic/agent/transaction/abstract_segment.rb +2 -2
  87. data/lib/new_relic/agent/transaction/segment.rb +6 -0
  88. data/lib/new_relic/agent/transaction/transaction_sample_buffer.rb +1 -1
  89. data/lib/new_relic/agent/transaction.rb +3 -3
  90. data/lib/new_relic/agent.rb +7 -0
  91. data/lib/new_relic/control/instance_methods.rb +6 -2
  92. data/lib/new_relic/helper.rb +1 -1
  93. data/lib/new_relic/recipes/helpers/send_deployment.rb +2 -1
  94. data/lib/new_relic/traced_thread.rb +5 -1
  95. data/lib/new_relic/version.rb +2 -2
  96. data/lib/newrelic_rpm.rb +13 -2
  97. data/lib/sequel/extensions/newrelic_instrumentation.rb +1 -1
  98. data/lib/sequel/plugins/newrelic_instrumentation.rb +1 -1
  99. data/newrelic.yml +23 -5
  100. data/test/agent_helper.rb +7 -7
  101. metadata +16 -6
  102. data/lib/new_relic/agent/agent/shutdown.rb +0 -35
  103. data/lib/new_relic/agent/agent/special_startup.rb +0 -72
  104. data/lib/new_relic/agent/agent/start_worker_thread.rb +0 -163
  105. data/lib/new_relic/agent/agent/startup.rb +0 -197
data/CONTRIBUTING.md CHANGED
@@ -183,8 +183,7 @@ For more information about CLAs, please check out Alex Russell’s excellent pos
183
183
  We host a public Slack with a dedicated channel for contributors and maintainers
184
184
  of open source projects hosted by New Relic. If you are contributing to this
185
185
  project, you're welcome to request access to the #oss-contributors channel in
186
- the newrelicusers.slack.com workspace. To request access, see
187
- https://newrelicusers-signup.herokuapp.com/.
186
+ the newrelicusers.slack.com workspace. To request access, please use this [link](https://join.slack.com/t/newrelicusers/shared_invite/zt-1ayj69rzm-~go~Eo1whIQGYnu3qi15ng).
188
187
 
189
188
  ## Explorer's Hub
190
189
 
data/README.md CHANGED
@@ -1,4 +1,5 @@
1
- [![Blue banner - Community Plus: This code is currently maintained by New Relic engineering teams and delivered here in GitHub. See the README for troubleshooting and defect reporting instructions.](https://github.com/newrelic/opensource-website/raw/main/src/images/categories/Community_Plus.png)](https://opensource.newrelic.com/oss-category/#community-plus)
1
+ [![Open Source, New Relic Community Plus: This code is currently maintained by New Relic engineering teams and delivered here in GitHub. See the README for troubleshooting and defect reporting instructions.](https://github.com/newrelic/open-source-office/raw/master/examples/categories/images/Community_Plus.png)](https://opensource.newrelic.com/oss-category/#community-plus)
2
+
2
3
 
3
4
  # New Relic Ruby Agent
4
5
 
data/init.rb CHANGED
@@ -26,5 +26,5 @@ begin
26
26
 
27
27
  NewRelic::Control.instance.init_plugin(:config => current_config)
28
28
  rescue => e
29
- ::NewRelic::Agent.logger.error("Error initializing New Relic plugin. Agent is disabled.", e)
29
+ NewRelic::Agent.logger.error("Error initializing New Relic plugin. Agent is disabled.", e)
30
30
  end
@@ -37,10 +37,13 @@ require 'new_relic/agent/adaptive_sampler'
37
37
  require 'new_relic/agent/connect/request_builder'
38
38
  require 'new_relic/agent/connect/response_handler'
39
39
 
40
- require 'new_relic/agent/agent/start_worker_thread'
41
- require 'new_relic/agent/agent/startup'
42
- require 'new_relic/agent/agent/special_startup'
43
- require 'new_relic/agent/agent/shutdown'
40
+ require 'new_relic/agent/agent_helpers/connect'
41
+ require 'new_relic/agent/agent_helpers/harvest'
42
+ require 'new_relic/agent/agent_helpers/start_worker_thread'
43
+ require 'new_relic/agent/agent_helpers/startup'
44
+ require 'new_relic/agent/agent_helpers/special_startup'
45
+ require 'new_relic/agent/agent_helpers/shutdown'
46
+ require 'new_relic/agent/agent_helpers/transmit'
44
47
 
45
48
  module NewRelic
46
49
  module Agent
@@ -53,10 +56,13 @@ module NewRelic
53
56
  ::NewRelic::Agent.config
54
57
  end
55
58
 
56
- include NewRelic::Agent::StartWorkerThread
57
- include NewRelic::Agent::SpecialStartup
58
- include NewRelic::Agent::Startup
59
- include NewRelic::Agent::Shutdown
59
+ include NewRelic::Agent::AgentHelpers::Connect
60
+ include NewRelic::Agent::AgentHelpers::Harvest
61
+ include NewRelic::Agent::AgentHelpers::StartWorkerThread
62
+ include NewRelic::Agent::AgentHelpers::SpecialStartup
63
+ include NewRelic::Agent::AgentHelpers::Startup
64
+ include NewRelic::Agent::AgentHelpers::Shutdown
65
+ include NewRelic::Agent::AgentHelpers::Transmit
60
66
 
61
67
  def initialize
62
68
  init_basics
@@ -321,162 +327,6 @@ module NewRelic
321
327
  NewRelic::Control.instance
322
328
  end
323
329
 
324
- # This module is an artifact of a refactoring of the connect
325
- # method - all of its methods are used in that context, so it
326
- # can be refactored at will. It should be fully tested
327
- module Connect
328
- # number of attempts we've made to contact the server
329
- attr_accessor :connect_attempts
330
-
331
- # Disconnect just sets the connect state to disconnected, preventing
332
- # further retries.
333
- def disconnect
334
- @connect_state = :disconnected
335
- true
336
- end
337
-
338
- def connected?
339
- @connect_state == :connected
340
- end
341
-
342
- def disconnected?
343
- @connect_state == :disconnected
344
- end
345
-
346
- # Don't connect if we're already connected, or if we tried to connect
347
- # and were rejected with prejudice because of a license issue, unless
348
- # we're forced to by force_reconnect.
349
- def should_connect?(force = false)
350
- force || (!connected? && !disconnected?)
351
- end
352
-
353
- # Per the spec at
354
- # /agents/agent-specs/Collector-Response-Handling.md, retry
355
- # connections after a specific backoff sequence to prevent
356
- # hammering the server.
357
- def connect_retry_period
358
- NewRelic::CONNECT_RETRY_PERIODS[connect_attempts] || NewRelic::MAX_RETRY_PERIOD
359
- end
360
-
361
- def note_connect_failure
362
- self.connect_attempts += 1
363
- end
364
-
365
- # When we have a problem connecting to the server, we need
366
- # to tell the user what happened, since this is not an error
367
- # we can handle gracefully.
368
- def log_error(error)
369
- ::NewRelic::Agent.logger.error("Error establishing connection with New Relic Service at #{control.server}:", error)
370
- end
371
-
372
- # When the server sends us an error with the license key, we
373
- # want to tell the user that something went wrong, and let
374
- # them know where to go to get a valid license key
375
- #
376
- # After this runs, it disconnects the agent so that it will
377
- # no longer try to connect to the server, saving the
378
- # application and the server load
379
- def handle_license_error(error)
380
- ::NewRelic::Agent.logger.error( \
381
- error.message, \
382
- "Visit NewRelic.com to obtain a valid license key, or to upgrade your account."
383
- )
384
- disconnect
385
- end
386
-
387
- def handle_unrecoverable_agent_error(error)
388
- ::NewRelic::Agent.logger.error(error.message)
389
- disconnect
390
- shutdown
391
- end
392
-
393
- # Checks whether we should send environment info, and if so,
394
- # returns the snapshot from the local environment.
395
- # Generating the EnvironmentReport has the potential to trigger
396
- # require calls in Rails environments, so this method should only
397
- # be called synchronously from on the main thread.
398
- def environment_for_connect
399
- @environment_report ||= Agent.config[:send_environment_info] ? Array(EnvironmentReport.new) : []
400
- end
401
-
402
- # Constructs and memoizes an event_harvest_config hash to be used in
403
- # the payload sent during connect (and reconnect)
404
- def event_harvest_config
405
- @event_harvest_config ||= Configuration::EventHarvestConfig.from_config(Agent.config)
406
- end
407
-
408
- # Builds the payload to send to the connect service,
409
- # connects, then configures the agent using the response from
410
- # the connect service
411
- def connect_to_server
412
- request_builder = ::NewRelic::Agent::Connect::RequestBuilder.new( \
413
- @service,
414
- Agent.config,
415
- event_harvest_config,
416
- environment_for_connect
417
- )
418
- connect_response = @service.connect(request_builder.connect_payload)
419
-
420
- response_handler = ::NewRelic::Agent::Connect::ResponseHandler.new(self, Agent.config)
421
- response_handler.configure_agent(connect_response)
422
-
423
- log_connection(connect_response) if connect_response
424
- connect_response
425
- end
426
-
427
- # Logs when we connect to the server, for debugging purposes
428
- # - makes sure we know if an agent has not connected
429
- def log_connection(config_data)
430
- ::NewRelic::Agent.logger.debug("Connected to NewRelic Service at #{@service.collector.name}")
431
- ::NewRelic::Agent.logger.debug("Agent Run = #{@service.agent_id}.")
432
- ::NewRelic::Agent.logger.debug("Connection data = #{config_data.inspect}")
433
- if config_data['messages'] && config_data['messages'].any?
434
- log_collector_messages(config_data['messages'])
435
- end
436
- end
437
-
438
- def log_collector_messages(messages)
439
- messages.each do |message|
440
- ::NewRelic::Agent.logger.send(message['level'].downcase, message['message'])
441
- end
442
- end
443
-
444
- # apdex_f is always 4 times the apdex_t
445
- def apdex_f
446
- (4 * Agent.config[:apdex_t]).to_f
447
- end
448
-
449
- class WaitOnConnectTimeout < StandardError
450
- end
451
-
452
- # Used for testing to let us know we've actually started to wait
453
- def waited_on_connect?
454
- @waited_on_connect
455
- end
456
-
457
- def signal_connected
458
- @wait_on_connect_mutex.synchronize do
459
- @wait_on_connect_condition.signal
460
- end
461
- end
462
-
463
- def wait_on_connect(timeout)
464
- return if connected?
465
-
466
- @waited_on_connect = true
467
- NewRelic::Agent.logger.debug("Waiting on connect to complete.")
468
-
469
- @wait_on_connect_mutex.synchronize do
470
- @wait_on_connect_condition.wait(@wait_on_connect_mutex, timeout)
471
- end
472
-
473
- unless connected?
474
- raise WaitOnConnectTimeout, "Agent was unable to connect in #{timeout} seconds."
475
- end
476
- end
477
- end
478
- include Connect
479
-
480
330
  def container_for_endpoint(endpoint)
481
331
  case endpoint
482
332
  when :metric_data then @stats_engine
@@ -506,313 +356,11 @@ module NewRelic
506
356
 
507
357
  public :merge_data_for_endpoint
508
358
 
509
- # Establish a connection to New Relic servers.
510
- #
511
- # By default, if a connection has already been established, this method
512
- # will be a no-op.
513
- #
514
- # @param [Hash] options
515
- # @option options [Boolean] :keep_retrying (true)
516
- # If true, this method will block until a connection is successfully
517
- # established, continuing to retry upon failure. If false, this method
518
- # will return after either successfully connecting, or after failing
519
- # once.
520
- #
521
- # @option options [Boolean] :force_reconnect (false)
522
- # If true, this method will force establishment of a new connection
523
- # with New Relic, even if there is already an existing connection.
524
- # This is useful primarily when re-establishing a new connection after
525
- # forking off from a parent process.
526
- #
527
- def connect(options = {})
528
- opts = connect_options(options)
529
- return unless should_connect?(opts[:force_reconnect])
530
-
531
- ::NewRelic::Agent.logger.debug("Connecting Process to New Relic: #$0")
532
- connect_to_server
533
- @connected_pid = $$
534
- @connect_state = :connected
535
- signal_connected
536
- rescue NewRelic::Agent::ForceDisconnectException => e
537
- handle_force_disconnect(e)
538
- rescue NewRelic::Agent::LicenseException => e
539
- handle_license_error(e)
540
- rescue NewRelic::Agent::UnrecoverableAgentException => e
541
- handle_unrecoverable_agent_error(e)
542
- rescue StandardError, Timeout::Error, NewRelic::Agent::ServerConnectionException => e
543
- retry if retry_from_error?(e, opts)
544
- rescue Exception => e
545
- ::NewRelic::Agent.logger.error("Exception of unexpected type during Agent#connect():", e)
546
-
547
- raise
548
- end
549
-
550
- def connect_options(options)
551
- {
552
- keep_retrying: Agent.config[:keep_retrying],
553
- force_reconnect: Agent.config[:force_reconnect]
554
- }.merge(options)
555
- end
556
-
557
- def retry_from_error?(e, opts)
558
- # Allow a killed (aborting) thread to continue exiting during shutdown.
559
- # See: https://github.com/newrelic/newrelic-ruby-agent/issues/340
560
- raise if Thread.current.status == 'aborting'
561
-
562
- log_error(e)
563
- return false unless opts[:keep_retrying]
564
-
565
- note_connect_failure
566
- ::NewRelic::Agent.logger.info("Will re-attempt in #{connect_retry_period} seconds")
567
- sleep(connect_retry_period)
568
- true
569
- end
570
-
571
359
  # Delegates to the control class to determine the root
572
360
  # directory of this project
573
361
  def determine_home_directory
574
362
  control.root
575
363
  end
576
-
577
- # Harvests data from the given container, sends it to the named endpoint
578
- # on the service, and automatically merges back in upon a recoverable
579
- # failure.
580
- #
581
- # The given container should respond to:
582
- #
583
- # #harvest!
584
- # returns a payload that contains enumerable collection of data items and
585
- # optional metadata to be sent to the collector.
586
- #
587
- # #reset!
588
- # drop any stored data and reset to a clean state.
589
- #
590
- # #merge!(payload)
591
- # merge the given payload back into the internal buffer of the
592
- # container, so that it may be harvested again later.
593
- #
594
- def harvest_and_send_from_container(container, endpoint)
595
- payload = harvest_from_container(container, endpoint)
596
- sample_count = harvest_size(container, payload)
597
- if sample_count > 0
598
- NewRelic::Agent.logger.debug("Sending #{sample_count} items to #{endpoint}")
599
- send_data_to_endpoint(endpoint, payload, container)
600
- end
601
- end
602
-
603
- def harvest_size(container, items)
604
- if container.respond_to?(:has_metadata?) && container.has_metadata? && !items.empty?
605
- items.last.size
606
- else
607
- items.size
608
- end
609
- end
610
-
611
- def harvest_from_container(container, endpoint)
612
- items = []
613
- begin
614
- items = container.harvest!
615
- rescue => e
616
- NewRelic::Agent.logger.error("Failed to harvest #{endpoint} data, resetting. Error: ", e)
617
- container.reset!
618
- end
619
- items
620
- end
621
-
622
- def send_data_to_endpoint(endpoint, payload, container)
623
- begin
624
- @service.send(endpoint, payload)
625
- rescue ForceRestartException, ForceDisconnectException
626
- raise
627
- rescue SerializationError => e
628
- NewRelic::Agent.logger.warn("Failed to serialize data for #{endpoint}, discarding. Error: ", e)
629
- rescue UnrecoverableServerException => e
630
- NewRelic::Agent.logger.warn("#{endpoint} data was rejected by remote service, discarding. Error: ", e)
631
- rescue ServerConnectionException => e
632
- log_remote_unavailable(endpoint, e)
633
- container.merge!(payload)
634
- rescue => e
635
- NewRelic::Agent.logger.info("Unable to send #{endpoint} data, will try again later. Error: ", e)
636
- container.merge!(payload)
637
- end
638
- end
639
-
640
- def harvest_and_send_timeslice_data
641
- TransactionTimeAggregator.harvest!
642
- harvest_and_send_from_container(@stats_engine, :metric_data)
643
- end
644
-
645
- def harvest_and_send_slowest_sql
646
- harvest_and_send_from_container(@sql_sampler, :sql_trace_data)
647
- end
648
-
649
- # This handles getting the transaction traces and then sending
650
- # them across the wire. This includes gathering SQL
651
- # explanations, stripping out stack traces, and normalizing
652
- # SQL. note that we explain only the sql statements whose
653
- # nodes' execution times exceed our threshold (to avoid
654
- # unnecessary overhead of running explains on fast queries.)
655
- def harvest_and_send_transaction_traces
656
- harvest_and_send_from_container(@transaction_sampler, :transaction_sample_data)
657
- end
658
-
659
- def harvest_and_send_for_agent_commands
660
- harvest_and_send_from_container(@agent_command_router, :profile_data)
661
- end
662
-
663
- def harvest_and_send_errors
664
- harvest_and_send_from_container(@error_collector.error_trace_aggregator, :error_data)
665
- end
666
-
667
- def harvest_and_send_analytic_event_data
668
- harvest_and_send_from_container(transaction_event_aggregator, :analytic_event_data)
669
- harvest_and_send_from_container(synthetics_event_aggregator, :analytic_event_data)
670
- end
671
-
672
- def harvest_and_send_custom_event_data
673
- harvest_and_send_from_container(@custom_event_aggregator, :custom_event_data)
674
- end
675
-
676
- def harvest_and_send_error_event_data
677
- harvest_and_send_from_container(@error_collector.error_event_aggregator, :error_event_data)
678
- end
679
-
680
- def harvest_and_send_span_event_data
681
- harvest_and_send_from_container(span_event_aggregator, :span_event_data)
682
- end
683
-
684
- def harvest_and_send_log_event_data
685
- harvest_and_send_from_container(@log_event_aggregator, :log_event_data)
686
- end
687
-
688
- def check_for_and_handle_agent_commands
689
- begin
690
- @agent_command_router.check_for_and_handle_agent_commands
691
- rescue ForceRestartException, ForceDisconnectException
692
- raise
693
- rescue UnrecoverableServerException => e
694
- NewRelic::Agent.logger.warn("get_agent_commands message was rejected by remote service, discarding. Error: ", e)
695
- rescue ServerConnectionException => e
696
- log_remote_unavailable(:get_agent_commands, e)
697
- rescue => e
698
- NewRelic::Agent.logger.info("Error during check_for_and_handle_agent_commands, will retry later: ", e)
699
- end
700
- end
701
-
702
- def log_remote_unavailable(endpoint, e)
703
- NewRelic::Agent.logger.debug("Unable to send #{endpoint} data, will try again later. Error: ", e)
704
- NewRelic::Agent.record_metric("Supportability/remote_unavailable", 0.0)
705
- NewRelic::Agent.record_metric("Supportability/remote_unavailable/#{endpoint.to_s}", 0.0)
706
- end
707
-
708
- TRANSACTION_EVENT = "TransactionEvent".freeze
709
- def transmit_analytic_event_data
710
- transmit_single_data_type(:harvest_and_send_analytic_event_data, TRANSACTION_EVENT)
711
- end
712
-
713
- CUSTOM_EVENT = "CustomEvent".freeze
714
- def transmit_custom_event_data
715
- transmit_single_data_type(:harvest_and_send_custom_event_data, CUSTOM_EVENT)
716
- end
717
-
718
- ERROR_EVENT = "ErrorEvent".freeze
719
- def transmit_error_event_data
720
- transmit_single_data_type(:harvest_and_send_error_event_data, ERROR_EVENT)
721
- end
722
-
723
- SPAN_EVENT = "SpanEvent".freeze
724
- def transmit_span_event_data
725
- transmit_single_data_type(:harvest_and_send_span_event_data, SPAN_EVENT)
726
- end
727
-
728
- LOG_EVENT = "LogEvent".freeze
729
- def transmit_log_event_data
730
- transmit_single_data_type(:harvest_and_send_log_event_data, LOG_EVENT)
731
- end
732
-
733
- def transmit_single_data_type(harvest_method, supportability_name)
734
- now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
735
-
736
- msg = "Sending #{supportability_name} data to New Relic Service"
737
- ::NewRelic::Agent.logger.debug(msg)
738
-
739
- @service.session do # use http keep-alive
740
- self.send(harvest_method)
741
- end
742
- ensure
743
- duration = Process.clock_gettime(Process::CLOCK_MONOTONIC) - now
744
- NewRelic::Agent.record_metric("Supportability/#{supportability_name}Harvest", duration)
745
- end
746
-
747
- def transmit_data
748
- now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
749
- ::NewRelic::Agent.logger.debug("Sending data to New Relic Service")
750
-
751
- @events.notify(:before_harvest)
752
- @service.session do # use http keep-alive
753
- harvest_and_send_data_types
754
-
755
- check_for_and_handle_agent_commands
756
- harvest_and_send_for_agent_commands
757
- end
758
- ensure
759
- NewRelic::Agent::Database.close_connections
760
- duration = Process.clock_gettime(Process::CLOCK_MONOTONIC) - now
761
- NewRelic::Agent.record_metric('Supportability/Harvest', duration)
762
- end
763
-
764
- # This method contacts the server to send remaining data and
765
- # let the server know that the agent is shutting down - this
766
- # allows us to do things like accurately set the end of the
767
- # lifetime of the process
768
- #
769
- # If this process comes from a parent process, it will not
770
- # disconnect, so that the parent process can continue to send data
771
- def graceful_disconnect
772
- if connected?
773
- begin
774
- @service.request_timeout = 10
775
-
776
- @events.notify(:before_shutdown)
777
- transmit_data_types
778
- shutdown_service
779
-
780
- ::NewRelic::Agent.logger.debug("Graceful disconnect complete")
781
- rescue Timeout::Error, StandardError => e
782
- ::NewRelic::Agent.logger.debug("Error when disconnecting #{e.class.name}: #{e.message}")
783
- end
784
- else
785
- ::NewRelic::Agent.logger.debug("Bypassing graceful disconnect - agent not connected")
786
- end
787
- end
788
- end
789
-
790
- def shutdown_service
791
- if @connected_pid == $$ && !@service.kind_of?(NewRelic::Agent::NewRelicService)
792
- ::NewRelic::Agent.logger.debug("Sending New Relic service agent run shutdown message")
793
- @service.shutdown
794
- else
795
- ::NewRelic::Agent.logger.debug("This agent connected from parent process #{@connected_pid}--not sending shutdown")
796
- end
797
- end
798
-
799
- def transmit_data_types
800
- transmit_data
801
- transmit_analytic_event_data
802
- transmit_custom_event_data
803
- transmit_error_event_data
804
- transmit_span_event_data
805
- transmit_log_event_data
806
- end
807
-
808
- def harvest_and_send_data_types
809
- harvest_and_send_errors
810
- harvest_and_send_error_event_data
811
- harvest_and_send_transaction_traces
812
- harvest_and_send_slowest_sql
813
- harvest_and_send_timeslice_data
814
- harvest_and_send_span_event_data
815
- harvest_and_send_log_event_data
816
364
  end
817
365
 
818
366
  extend ClassMethods