class Instana::Backend::HostAgentReportingObserver

Process which is responsible for reporting metrics and tracing to the local agent @since 1.197.0

Constants

ENTITY_DATA_URL
RESPONSE_DATA_URL
TRACES_DATA_URL
TRACE_METRICS_URL

Attributes

report_timer[R]

Public Class Methods

new(client, discovery, logger: ::Instana.logger, timer_class: Concurrent::TimerTask, processor: ::Instana.processor) click to toggle source

@param [RequestClient] client used to make requests to the backend @param [Concurrent::Atom] discovery object used to store discovery response in

# File lib/instana/backend/host_agent_reporting_observer.rb, line 18
def initialize(client, discovery, logger: ::Instana.logger, timer_class: Concurrent::TimerTask, processor: ::Instana.processor)
  @client = client
  @discovery = discovery
  @logger = logger
  @report_timer = timer_class.new(execution_interval: 1, run_now: true) { report_to_backend }
  @nonce = Time.now
  @processor = processor
end

Public Instance Methods

update(time, _old_version, new_version) click to toggle source
# File lib/instana/backend/host_agent_reporting_observer.rb, line 27
def update(time, _old_version, new_version)
  return unless time > @nonce

  @nonce = time
  new_version.nil? ? @report_timer.shutdown : @report_timer.execute
end

Private Instance Methods

handle_agent_tasks(response, discovery) click to toggle source
# File lib/instana/backend/host_agent_reporting_observer.rb, line 90
def handle_agent_tasks(response, discovery)
  payload = response.json
  payload = [payload] if payload.is_a?(Hash)
  payload
    .select { |t| t['action'] == 'ruby.source' }
    .each do |action|
      payload = ::Instana::Util.get_rb_source(action['args']['file'])
      path = format(RESPONSE_DATA_URL, discovery['pid'], action['messageId'])
      @client.send_request('POST', path, payload)
    end
rescue StandardError => e
  @logger.debug("Error processing agent task #{e.inspect}")
end
metrics_payload(discovery) click to toggle source
# File lib/instana/backend/host_agent_reporting_observer.rb, line 104
def metrics_payload(discovery)
  payload = {
    pid: discovery['pid'],
    name: Util.get_app_name
  }

  if ::Instana.config[:metrics][:memory][:enabled]
    proc_table = Sys::ProcTable.ps(pid: Process.pid)
    process = ProcessInfo.new(proc_table)
    payload[:exec_args] = process.arguments
    payload[:memory] = {rss_size: process.memory_used}
  end

  if ::Instana.config[:metrics][:gc][:enabled]
    payload[:gc] = GCSnapshot.instance.report
  end

  if ::Instana.config[:metrics][:thread][:enabled]
    payload[:thread] = {count: ::Thread.list.count}
  end

  payload
end
report_metrics() click to toggle source
# File lib/instana/backend/host_agent_reporting_observer.rb, line 74
def report_metrics
  discovery = @discovery.value
  return unless discovery

  path = format(ENTITY_DATA_URL, discovery['pid'])
  payload = metrics_payload(discovery).merge(Util.take_snapshot)
  response = @client.send_request('POST', path, payload)

  if response.ok?
    handle_agent_tasks(response, discovery) unless response.body.empty?
  else
    @logger.debug("Sent `#{payload}` to `#{path}` and got `#{response.code}`.")
    @discovery.swap { nil }
  end
end
report_to_backend() click to toggle source
# File lib/instana/backend/host_agent_reporting_observer.rb, line 36
def report_to_backend
  report_metrics if ::Instana.config[:metrics][:enabled]
  report_traces if ::Instana.config[:tracing][:enabled]
  report_trace_stats if ::Instana.config[:tracing][:enabled]
rescue StandardError => e
  @logger.error(%(#{e}\n#{e.backtrace.join("\n")}))
end
report_trace_stats() click to toggle source
# File lib/instana/backend/host_agent_reporting_observer.rb, line 44
def report_trace_stats
  discovery = @discovery.value
  return unless discovery

  payload = {
    tracer: 'ruby',
    pid: discovery['pid'],
    metrics: @processor.span_metrics
  }

  @client.send_request('POST', TRACE_METRICS_URL, payload)
end
report_traces() click to toggle source
# File lib/instana/backend/host_agent_reporting_observer.rb, line 57
def report_traces
  discovery = @discovery.value
  return unless discovery

  path = format(TRACES_DATA_URL, discovery['pid'])

  @processor.send do |spans|
    response = @client.send_request('POST', path, spans)

    unless response.ok?
      @logger.debug("Sent `#{spans.count}` spans to `#{path}` and got `#{response.code}`.")
      @discovery.swap { nil }
      break
    end
  end
end