Module: NewRelic::Agent::AgentHelpers::Connect
- Included in:
- NewRelic::Agent::Agent
- Defined in:
- lib/new_relic/agent/agent_helpers/connect.rb
Overview
This module is an artifact of a refactoring of the connect method - all of its methods are used in that context, so it can be refactored at will. It should be fully tested
Defined Under Namespace
Classes: WaitOnConnectTimeout
Instance Attribute Summary collapse
-
#connect_attempts ⇒ Object
number of attempts we’ve made to contact the server.
Instance Method Summary collapse
-
#connect(options = {}) ⇒ Object
Establish a connection to New Relic servers.
- #connect_options(options) ⇒ Object
-
#connect_retry_period ⇒ Object
Per the spec at /agents/agent-specs/Collector-Response-Handling.md, retry connections after a specific backoff sequence to prevent hammering the server.
-
#connect_to_server ⇒ Object
Builds the payload to send to the connect service, connects, then configures the agent using the response from the connect service.
- #connected? ⇒ Boolean
-
#disconnect ⇒ Object
Disconnect just sets the connect state to disconnected, preventing further retries.
- #disconnected? ⇒ Boolean
-
#environment_for_connect ⇒ Object
Checks whether we should send environment info, and if so, returns the snapshot from the local environment.
-
#event_harvest_config ⇒ Object
Constructs and memoizes an event_harvest_config hash to be used in the payload sent during connect (and reconnect).
-
#handle_license_error(error) ⇒ Object
When the server sends us an error with the license key, we want to tell the user that something went wrong, and let them know where to go to get a valid license key.
- #handle_unrecoverable_agent_error(error) ⇒ Object
- #log_collector_messages(messages) ⇒ Object
-
#log_connection(config_data) ⇒ Object
Logs when we connect to the server, for debugging purposes - makes sure we know if an agent has not connected.
-
#log_error(error) ⇒ Object
When we have a problem connecting to the server, we need to tell the user what happened, since this is not an error we can handle gracefully.
- #note_connect_failure ⇒ Object
- #retry_from_error?(e, opts) ⇒ Boolean
- #serverless? ⇒ Boolean
-
#should_connect?(force = false) ⇒ Boolean
Don’t connect if we’re already connected, if we’re in serverless mode, or if we tried to connect and were rejected with prejudice because of a license issue, unless we’re forced to by force_reconnect.
- #signal_connected ⇒ Object
- #wait_on_connect(timeout) ⇒ Object
-
#waited_on_connect? ⇒ Boolean
Used for testing to let us know we’ve actually started to wait.
Instance Attribute Details
#connect_attempts ⇒ Object
number of attempts we’ve made to contact the server
13 14 15 |
# File 'lib/new_relic/agent/agent_helpers/connect.rb', line 13 def connect_attempts @connect_attempts end |
Instance Method Details
#connect(options = {}) ⇒ Object
Establish a connection to New Relic servers.
By default, if a connection has already been established, this method will be a no-op.
185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/new_relic/agent/agent_helpers/connect.rb', line 185 def connect( = {}) opts = () return unless should_connect?(opts[:force_reconnect]) ::NewRelic::Agent.logger.debug("Connecting Process to New Relic: #$0") connect_to_server @connected_pid = $$ @connect_state = :connected signal_connected rescue NewRelic::Agent::ForceDisconnectException => e handle_force_disconnect(e) rescue NewRelic::Agent::LicenseException => e handle_license_error(e) rescue NewRelic::Agent::UnrecoverableAgentException => e handle_unrecoverable_agent_error(e) rescue StandardError, Timeout::Error, NewRelic::Agent::ServerConnectionException => e retry if retry_from_error?(e, opts) rescue Exception => e ::NewRelic::Agent.logger.error('Exception of unexpected type during Agent#connect():', e) raise end |
#connect_options(options) ⇒ Object
160 161 162 163 164 165 |
# File 'lib/new_relic/agent/agent_helpers/connect.rb', line 160 def () { keep_retrying: true, force_reconnect: Agent.config[:force_reconnect] }.merge() end |
#connect_retry_period ⇒ Object
Per the spec at /agents/agent-specs/Collector-Response-Handling.md, retry connections after a specific backoff sequence to prevent hammering the server.
45 46 47 |
# File 'lib/new_relic/agent/agent_helpers/connect.rb', line 45 def connect_retry_period NewRelic::CONNECT_RETRY_PERIODS[connect_attempts] || NewRelic::MAX_RETRY_PERIOD end |
#connect_to_server ⇒ Object
Builds the payload to send to the connect service, connects, then configures the agent using the response from the connect service
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/new_relic/agent/agent_helpers/connect.rb', line 98 def connect_to_server request_builder = ::NewRelic::Agent::Connect::RequestBuilder.new( @service, Agent.config, event_harvest_config, environment_for_connect ) connect_response = @service.connect(request_builder.connect_payload) response_handler = ::NewRelic::Agent::Connect::ResponseHandler.new(self, Agent.config) response_handler.configure_agent(connect_response) log_connection(connect_response) if connect_response connect_response end |
#connected? ⇒ Boolean
22 23 24 |
# File 'lib/new_relic/agent/agent_helpers/connect.rb', line 22 def connected? @connect_state == :connected end |
#disconnect ⇒ Object
Disconnect just sets the connect state to disconnected, preventing further retries.
17 18 19 20 |
# File 'lib/new_relic/agent/agent_helpers/connect.rb', line 17 def disconnect @connect_state = :disconnected true end |
#disconnected? ⇒ Boolean
26 27 28 |
# File 'lib/new_relic/agent/agent_helpers/connect.rb', line 26 def disconnected? @connect_state == :disconnected end |
#environment_for_connect ⇒ Object
Checks whether we should send environment info, and if so, returns the snapshot from the local environment. Generating the EnvironmentReport has the potential to trigger require calls in Rails environments, so this method should only be called synchronously from on the main thread.
85 86 87 |
# File 'lib/new_relic/agent/agent_helpers/connect.rb', line 85 def environment_for_connect @environment_report ||= Agent.config[:send_environment_info] ? Array(EnvironmentReport.new) : [] end |
#event_harvest_config ⇒ Object
Constructs and memoizes an event_harvest_config hash to be used in the payload sent during connect (and reconnect)
91 92 93 |
# File 'lib/new_relic/agent/agent_helpers/connect.rb', line 91 def event_harvest_config @event_harvest_config ||= Configuration::EventHarvestConfig.from_config(Agent.config) end |
#handle_license_error(error) ⇒ Object
When the server sends us an error with the license key, we want to tell the user that something went wrong, and let them know where to go to get a valid license key
After this runs, it disconnects the agent so that it will no longer try to connect to the server, saving the application and the server load
68 69 70 71 72 |
# File 'lib/new_relic/agent/agent_helpers/connect.rb', line 68 def handle_license_error(error) ::NewRelic::Agent.logger.error(error., 'Visit newrelic.com to obtain a valid license key, or to upgrade your account.') disconnect end |
#handle_unrecoverable_agent_error(error) ⇒ Object
74 75 76 77 78 |
# File 'lib/new_relic/agent/agent_helpers/connect.rb', line 74 def handle_unrecoverable_agent_error(error) ::NewRelic::Agent.logger.error(error.) disconnect shutdown end |
#log_collector_messages(messages) ⇒ Object
125 126 127 128 129 |
# File 'lib/new_relic/agent/agent_helpers/connect.rb', line 125 def () .each do || ::NewRelic::Agent.logger.send(['level'].downcase, ['message']) end end |
#log_connection(config_data) ⇒ Object
Logs when we connect to the server, for debugging purposes
-
makes sure we know if an agent has not connected
116 117 118 119 120 121 122 123 |
# File 'lib/new_relic/agent/agent_helpers/connect.rb', line 116 def log_connection(config_data) ::NewRelic::Agent.logger.debug("Connected to NewRelic Service at #{@service.collector.name}") ::NewRelic::Agent.logger.debug("Agent Run = #{@service.agent_id}.") ::NewRelic::Agent.logger.debug("Connection data = #{config_data.inspect}") if config_data['messages']&.any? (config_data['messages']) end end |
#log_error(error) ⇒ Object
When we have a problem connecting to the server, we need to tell the user what happened, since this is not an error we can handle gracefully.
56 57 58 59 |
# File 'lib/new_relic/agent/agent_helpers/connect.rb', line 56 def log_error(error) ::NewRelic::Agent.logger.error("Error establishing connection with New Relic Service at #{control.server}:", error) end |
#note_connect_failure ⇒ Object
49 50 51 |
# File 'lib/new_relic/agent/agent_helpers/connect.rb', line 49 def note_connect_failure self.connect_attempts += 1 end |
#retry_from_error?(e, opts) ⇒ Boolean
208 209 210 211 212 213 214 215 216 217 218 219 220 |
# File 'lib/new_relic/agent/agent_helpers/connect.rb', line 208 def retry_from_error?(e, opts) # Allow a killed (aborting) thread to continue exiting during shutdown. # See: https://github.com/newrelic/newrelic-ruby-agent/issues/340 raise if Thread.current.status == 'aborting' log_error(e) return false unless opts[:keep_retrying] note_connect_failure ::NewRelic::Agent.logger.info("Will re-attempt in #{connect_retry_period} seconds") sleep(connect_retry_period) true end |
#serverless? ⇒ Boolean
30 31 32 |
# File 'lib/new_relic/agent/agent_helpers/connect.rb', line 30 def serverless? Agent.config[:'serverless_mode.enabled'] end |
#should_connect?(force = false) ⇒ Boolean
Don’t connect if we’re already connected, if we’re in serverless mode, or if we tried to connect and were rejected with prejudice because of a license issue, unless we’re forced to by force_reconnect.
37 38 39 |
# File 'lib/new_relic/agent/agent_helpers/connect.rb', line 37 def should_connect?(force = false) force || (!connected? && !disconnected?) end |
#signal_connected ⇒ Object
139 140 141 142 143 |
# File 'lib/new_relic/agent/agent_helpers/connect.rb', line 139 def signal_connected @wait_on_connect_mutex.synchronize do @wait_on_connect_condition.signal end end |
#wait_on_connect(timeout) ⇒ Object
145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/new_relic/agent/agent_helpers/connect.rb', line 145 def wait_on_connect(timeout) return if connected? @waited_on_connect = true NewRelic::Agent.logger.debug('Waiting on connect to complete.') @wait_on_connect_mutex.synchronize do @wait_on_connect_condition.wait(@wait_on_connect_mutex, timeout) end unless connected? raise WaitOnConnectTimeout, "Agent was unable to connect in #{timeout} seconds." end end |
#waited_on_connect? ⇒ Boolean
Used for testing to let us know we’ve actually started to wait
135 136 137 |
# File 'lib/new_relic/agent/agent_helpers/connect.rb', line 135 def waited_on_connect? @waited_on_connect end |