class NewRelic::Agent::InfiniteTracing::Connection

Public Class Methods

instance() click to toggle source
# File lib/infinite_tracing/connection.rb, line 38
def instance
  @@instance ||= new
end
metadata() click to toggle source
# File lib/infinite_tracing/connection.rb, line 60
def metadata
  instance.metadata
end
new() click to toggle source

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
record_span_batches(client, enumerator, exponential_backoff) click to toggle source

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
record_spans(client, enumerator, exponential_backoff) click to toggle source

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
reset() click to toggle source
# File lib/infinite_tracing/connection.rb, line 42
def reset
  @@instance = new
end

Public Instance Methods

metadata() click to toggle source

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
notify_agent_started() click to toggle source

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
record_span_batches(client, enumerator, exponential_backoff) click to toggle source

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
record_spans(client, enumerator, exponential_backoff) click to toggle source

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
rpc() click to toggle source

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
wait_for_agent_connect() click to toggle source
# 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

agent_id() click to toggle source

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
license_key() click to toggle source
# File lib/infinite_tracing/connection.rb, line 144
def license_key
  NewRelic::Agent.config[:license_key]
end
note_connect_failure() click to toggle source

broken out to help for testing

# File lib/infinite_tracing/connection.rb, line 178
def note_connect_failure
  @connection_attempts += 1
end
request_headers_map() click to toggle source
# 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
retry_connection_period(exponential_backoff=true) click to toggle source
# 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
with_reconnection_backoff(exponential_backoff=true) { || ... } click to toggle source

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