class Instana::Snapshot::DockerContainer

Describes a Docker container visible to the current process @since 1.197.0

Constants

ID

Public Class Methods

new(container, metadata_uri: ENV['ECS_CONTAINER_METADATA_URI']) click to toggle source
# File lib/instana/snapshot/docker_container.rb, line 12
def initialize(container, metadata_uri: ENV['ECS_CONTAINER_METADATA_URI'])
  @container = container
  @metadata_uri = URI(metadata_uri)
  @client = Backend::RequestClient.new(@metadata_uri.host, @metadata_uri.port, use_ssl: @metadata_uri.scheme == "https")
end

Public Instance Methods

data() click to toggle source
# File lib/instana/snapshot/docker_container.rb, line 22
def data
  metrics = lookup('/task/stats').fetch(@container['DockerId'], {})

  container_metrics(metrics)
    .merge(container_metadata)
end
entity_id() click to toggle source
# File lib/instana/snapshot/docker_container.rb, line 18
def entity_id
  "#{@container['Labels']['com.amazonaws.ecs.task-arn']}::#{@container['Name']}"
end
snapshot() click to toggle source
# File lib/instana/snapshot/docker_container.rb, line 29
def snapshot
  {
    name: ID,
    entityId: entity_id,
    data: data
  }
end

Private Instance Methods

blkio_stats(metrics) click to toggle source
# File lib/instana/snapshot/docker_container.rb, line 78
def blkio_stats(metrics)
  delta = ->(old, new) { new - old }
  bytes = {
    'block_bytes' => metrics['blkio_stats']['io_service_bytes_recursive'].map { |r| [r['op'], r['value']] }.to_h
  }

  {
    blk_read: delta('block_bytes', 'Read', compute: delta, obj: bytes),
    blk_write: delta('block_bytes', 'Write', compute: delta, obj: bytes)
  }
end
container_metadata() click to toggle source
# File lib/instana/snapshot/docker_container.rb, line 39
def container_metadata
  {
    Id: @container['DockerId'],
    Created: @container['CreatedAt'],
    Started: @container['StartedAt'],
    Image: @container['Image'],
    Labels: @container['Labels'],
    Ports: @container['Ports'],
    NetworkMode: @container['Networks'].first['NetworkMode']
  }
end
container_metrics(metrics) click to toggle source
# File lib/instana/snapshot/docker_container.rb, line 51
def container_metrics(metrics)
  return {} if metrics.empty?

  {
    memory: memory_stats(metrics),
    blkio: blkio_stats(metrics),
    cpu: cpu_stats(metrics),
    network: network_stats(metrics)
  }.reject { |_, v| v.nil? }
end
cpu_stats(metrics) click to toggle source
# File lib/instana/snapshot/docker_container.rb, line 90
def cpu_stats(metrics)
  delta = ->(old, new) { new - old }
  identity = ->(_old, new) { new }

  cpu_system_delta = delta('cpu_stats', 'system_cpu_usage', compute: delta, obj: metrics).to_f
  online_cpus = delta('cpu_stats', 'online_cpus', compute: identity, obj: metrics) || 1

  {
    total_usage: (delta('cpu_stats', 'cpu_usage', 'total_usage', compute: delta, obj: metrics) / cpu_system_delta) * online_cpus,
    user_usage: (delta('cpu_stats', 'cpu_usage', 'usage_in_usermode', compute: delta, obj: metrics) / cpu_system_delta) * online_cpus,
    system_usage: (delta('cpu_stats', 'cpu_usage', 'usage_in_kernelmode', compute: delta, obj: metrics) / cpu_system_delta) * online_cpus,
    throttling_count: delta('cpu_stats', 'throttling_data', 'periods', compute: delta, obj: metrics),
    throttling_time: delta('cpu_stats', 'throttling_data', 'throttled_time', compute: delta, obj: metrics)
  }
end
lookup(resource) click to toggle source
# File lib/instana/snapshot/docker_container.rb, line 141
def lookup(resource)
  path = @metadata_uri.path + resource
  response = @client.send_request('GET', path)

  raise "Unable to get `#{path}`. Got `#{response.code}`." unless response.ok?

  response.json
end
memory_stats(metrics) click to toggle source
# File lib/instana/snapshot/docker_container.rb, line 62
def memory_stats(metrics)
  identity = ->(_old, new) { new }

  {
    active_anon: delta('memory_stats', 'stats', 'active_anon', compute: identity, obj: metrics),
    active_file: delta('memory_stats', 'stats', 'active_file', compute: identity, obj: metrics),
    inactive_anon: delta('memory_stats', 'stats', 'inactive_anon', compute: identity, obj: metrics),
    inactive_file: delta('memory_stats', 'stats', 'inactive_file', compute: identity, obj: metrics),
    total_cache: delta('memory_stats', 'stats', 'total_cache', compute: identity, obj: metrics),
    total_rss: delta('memory_stats', 'stats', 'total_rss', compute: identity, obj: metrics),
    usage: delta('memory_stats', 'usage', compute: identity, obj: metrics),
    max_usage: delta('memory_stats', 'max_usage', compute: identity, obj: metrics),
    limit: delta('memory_stats', 'limit', compute: identity, obj: metrics)
  }
end
network_stats(metrics) click to toggle source
# File lib/instana/snapshot/docker_container.rb, line 106
def network_stats(metrics)
  delta = ->(old, new) { new - old }
  return nil unless metrics['networks']

  interfaces = metrics['networks'].keys
  payload = {
    rx: {
      bytes: 0,
      dropped: 0,
      errors: 0,
      packet: 0
    },
    tx: {
      bytes: 0,
      dropped: 0,
      errors: 0,
      packet: 0
    }
  }

  interfaces.each do |interface|
    payload[:rx][:bytes] += delta('networks', interface, 'rx_bytes', compute: delta, obj: metrics)
    payload[:rx][:dropped] += delta('networks', interface, 'rx_dropped', compute: delta, obj: metrics)
    payload[:rx][:errors] += delta('networks', interface, 'rx_errors', compute: delta, obj: metrics)
    payload[:rx][:packet] += delta('networks', interface, 'rx_packets', compute: delta, obj: metrics)

    payload[:tx][:bytes] += delta('networks', interface, 'tx_bytes', compute: delta, obj: metrics)
    payload[:tx][:dropped] += delta('networks', interface, 'tx_packets', compute: delta, obj: metrics)
    payload[:tx][:errors] += delta('networks', interface, 'tx_errors', compute: delta, obj: metrics)
    payload[:tx][:packet] += delta('networks', interface, 'tx_dropped', compute: delta, obj: metrics)
  end

  payload
end