class NewRelic::Agent::InfiniteTracing::Connection
Public Class Methods
# File lib/infinite_tracing/connection.rb, line 38 def instance @@instance ||= new end
# File lib/infinite_tracing/connection.rb, line 60 def metadata instance.metadata end
prepares the connection to wait for the agent to connect and have an agent_run_token ready for metadata on rpc calls.
# File lib/infinite_tracing/connection.rb, line 128 def initialize @active_clients = {} @rpc = nil @metadata = nil @connection_attempts = 0 @agent_connected = NewRelic::Agent.agent.connected? @agent_started = ConditionVariable.new @lock = Mutex.new end
RPC calls will pass the calling client instance in. We track this so we're able to signal the client to restart when connectivity to the server is disrupted.
# File lib/infinite_tracing/connection.rb, line 56 def record_span_batches client, enumerator, exponential_backoff instance.record_span_batch client, enumerator, exponential_backoff end
RPC calls will pass the calling client instance in. We track this so we're able to signal the client to restart when connectivity to the server is disrupted.
# File lib/infinite_tracing/connection.rb, line 49 def record_spans client, enumerator, exponential_backoff instance.record_spans client, enumerator, exponential_backoff end
# File lib/infinite_tracing/connection.rb, line 42 def reset @@instance = new end
Public Instance Methods
The metadata for the RPC calls is a blocking call waiting for the Agent
to connect and receive the server side configuration, which contains the license_key
as well as the agent_id
(agent_run_token).
# File lib/infinite_tracing/connection.rb, line 97 def metadata return @metadata if @metadata @lock.synchronize do @metadata = { "license_key" => license_key, "agent_run_token" => agent_id } @metadata.merge!(request_headers_map) end end
Initializes rpc so we can get a Channel
and Stub (connect to gRPC server) Initializes metadata so we use newest values in establishing channel Sets the agent_connected flag and signals the agent started so any waiting locks (rpc calls ahead of the agent connecting) can proceed.
# File lib/infinite_tracing/connection.rb, line 114 def notify_agent_started @lock.synchronize do @rpc = nil @metadata = nil @agent_connected = true @agent_started.signal end @active_clients.each_value(&:restart) end
RPC calls will pass the calling client instance in. We track this so we're able to signal the client to restart when connectivity to the server is disrupted.
# File lib/infinite_tracing/connection.rb, line 75 def record_span_batches client, enumerator, exponential_backoff @active_clients[client] = client with_reconnection_backoff(exponential_backoff) { rpc.record_span_batch enumerator, metadata: metadata } end
We attempt to connect and record spans with reconnection backoff in order to deal with unavailable errors coming from the stub being created and record_span call
# File lib/infinite_tracing/connection.rb, line 67 def record_spans client, enumerator, exponential_backoff @active_clients[client] = client with_reconnection_backoff(exponential_backoff) { rpc.record_span enumerator, metadata: metadata } end
Acquires the new channel stub for the RPC calls. We attempt to connect and record spans with reconnection backoff in order to deal with unavailable errors coming from the stub being created and record_span call
# File lib/infinite_tracing/connection.rb, line 83 def rpc wait_for_agent_connect @rpc ||= Channel.new.stub end
# File lib/infinite_tracing/connection.rb, line 88 def wait_for_agent_connect @lock.synchronize do @agent_started.wait(@lock) if !@agent_connected end end
Private Instance Methods
The agent run token, which is only available after a server source configuration has been added to the agent's config stack.
# File lib/infinite_tracing/connection.rb, line 140 def agent_id NewRelic::Agent.agent.service.agent_id.to_s end
# File lib/infinite_tracing/connection.rb, line 144 def license_key NewRelic::Agent.config[:license_key] end
broken out to help for testing
# File lib/infinite_tracing/connection.rb, line 178 def note_connect_failure @connection_attempts += 1 end
# File lib/infinite_tracing/connection.rb, line 148 def request_headers_map headers = NewRelic::Agent.agent.service.instance_variable_get(:@request_headers_map) || NewRelic::EMPTY_HASH # transform_keys only 2.5+, but infinite tracing is 2.5+ only also headers.transform_keys(&:downcase) end
# File lib/infinite_tracing/connection.rb, line 169 def retry_connection_period exponential_backoff=true if exponential_backoff NewRelic::CONNECT_RETRY_PERIODS[@connection_attempts] || NewRelic::MAX_RETRY_PERIOD else NewRelic::MIN_RETRY_PERIOD end end
Continues retrying the connection at backoff intervals until a successful connection is made
# File lib/infinite_tracing/connection.rb, line 155 def with_reconnection_backoff exponential_backoff=true, &block @connection_attempts = 0 begin yield rescue => exception retry_connection_period = retry_connection_period(exponential_backoff) ::NewRelic::Agent.logger.error "Error establishing connection with infinite tracing service:", exception ::NewRelic::Agent.logger.info "Will re-attempt infinte tracing connection in #{retry_connection_period} seconds" sleep retry_connection_period note_connect_failure retry end end