class Tracebin::SystemHealthSample

Constants

DATA_TYPE

Public Class Methods

new(options = {}) click to toggle source
# File lib/tracebin/system_health_sample.rb, line 7
def initialize(options = {})
  @process = options[:process] || :web
  @sampled_at = timestamp_string
  @metrics = sample_metrics
end

Public Instance Methods

payload() click to toggle source
# File lib/tracebin/system_health_sample.rb, line 13
def payload
  {
    type: DATA_TYPE,

    data: {
      sampled_at: @sampled_at,

      metrics: @metrics
    }
  }
end

Private Instance Methods

darwin?() click to toggle source
# File lib/tracebin/system_health_sample.rb, line 41
def darwin?
  !!(ruby_os_identifier =~ /darwin/i)
end
disk_info(disks = ["disk0"]) click to toggle source
# File lib/tracebin/system_health_sample.rb, line 68
def disk_info(disks = ["disk0"])
  if darwin?
    read_iostat(disks)
  elsif linux?
    parse_proc
  end
end
get_darwin_cpu_usage() click to toggle source
# File lib/tracebin/system_health_sample.rb, line 191
def get_darwin_cpu_usage
  iostat = `iostat 2>/dev/null`.split(/\n+/).map do |line|
    line.strip.split(/\s+/)
  end
  cpu_idx = iostat[0].index('cpu') * 3
  user, sys, idle = iostat[2].map(&:to_f)[cpu_idx..cpu_idx + 2]

  (user + sys) / (user + sys + idle)
end
get_linux_cpu_usage() click to toggle source
# File lib/tracebin/system_health_sample.rb, line 201
def get_linux_cpu_usage
  proc_data = File.readlines('/proc/stat').grep(/^cpu /).first.split(" ")

  usage = proc_data[1].to_i + proc_data[2].to_i + proc_data[3].to_i
  total = usage + proc_data[4].to_i

  usage.to_f / total.to_f
end
get_linux_memory_stats() click to toggle source
# File lib/tracebin/system_health_sample.rb, line 131
def get_linux_memory_stats
  total, used, free, _, cache, available = `free | grep Mem`.scan(/\d+/).map { |mem_stat| mem_stat.to_i / 1024 }
  [total.to_s, cache.to_s, free.to_s, used.to_s, available.to_s]
end
get_mach_memory_stats() click to toggle source
# File lib/tracebin/system_health_sample.rb, line 125
def get_mach_memory_stats
  used, wired, free = `top -l 1 -s 0 | grep PhysMem`.scan(/\d+/)
  total = `sysctl -n hw.memsize`.to_i / 1024 / 1024
  [total.to_i, wired.to_i, free.to_i, used.to_i]
end
get_sysctl_value(key) click to toggle source
# File lib/tracebin/system_health_sample.rb, line 153
def get_sysctl_value(key)
  `sysctl -n #{key} 2>/dev/null`
end
linux?() click to toggle source
# File lib/tracebin/system_health_sample.rb, line 45
def linux?
  !!(ruby_os_identifier =~ /linux/i)
end
machine_info() click to toggle source
# File lib/tracebin/system_health_sample.rb, line 49
def machine_info
  ip_string = `dig +short myip.opendns.com @resolver1.opendns.com`.strip
  hostname = `hostname`.strip

  kernel = nil

  if darwin?
    kernel = 'darwin'
  elsif linux?
    kernel = 'linux'
  end

  {
    hostname: hostname,
    ip: ip_string,
    kernel: kernel
  }
end
mem_info() click to toggle source
# File lib/tracebin/system_health_sample.rb, line 104
def mem_info
  if darwin?
    total, wired, free, used = get_mach_memory_stats
    return {
      total_memory: total,
      wired_memory: wired,
      free_memory: free,
      used_memory: used
    }
  elsif linux?
    total, cache, free, used, available = get_linux_memory_stats
    return {
      total_memory: total,
      wired_memory: cache,
      free_memory: free,
      used_memory: used,
      available_memory: available
    }
  end
end
parse_proc() click to toggle source
# File lib/tracebin/system_health_sample.rb, line 76
def parse_proc
  {
    load_average: `cat /proc/loadavg | awk '{print $1,$2,$3}'`.strip
  }
end
parse_proc_cpuinfo_string(proc_string) click to toggle source
# File lib/tracebin/system_health_sample.rb, line 162
def parse_proc_cpuinfo_string(proc_string)
  threads = proc_string.split(/\n\n/).map { |core| core.split(/\n/) }

  units = {}
  cores = {}
  model_name = nil

  threads.each do |thread|
    thread.each do |line|
      if matched_line = line.match(/physical\ id\s*\:\s*(\d)/i)
        id = matched_line[1]
        units[id] = true
      elsif matched_line = line.match(/core\ id\s*\:\s*(\d)/i)
        id = matched_line[1]
        cores[id] = true
      elsif matched_line = line.match(/model\ name\s*\:\s*(.*)/i)
        model_name = matched_line[1] unless model_name
      end
    end
  end

  {
    model_name: model_name,
    processor_count: units.count,
    core_count: cores.count,
    logical_cpu_count: threads.count
  }
end
processor_info() click to toggle source
# File lib/tracebin/system_health_sample.rb, line 136
def processor_info
  info = {}

  if darwin?
    info[:model_name] = get_sysctl_value('machdep.cpu.brand_string')
    info[:processor_count] = get_sysctl_value('hw.packages').to_i
    info[:core_count] = get_sysctl_value('hw.physicalcpu_max').to_i,
    info[:logical_cpu_count] = get_sysctl_value('hw.logicalcpu_max').to_i
    info[:usage] = get_darwin_cpu_usage
  elsif linux?
    proc_string = read_proc('/proc/cpuinfo')
    info = parse_proc_cpuinfo_string(proc_string)
    info[:usage] = get_linux_cpu_usage
  end
  info
end
read_iostat(disks) click to toggle source
# File lib/tracebin/system_health_sample.rb, line 82
def read_iostat(disks)
  disks_info = {}
  captured_data = []

  disks.each do |disk|
    disk_data = `iostat -Ud #{disk}`.strip.split(/\n/)
    captured_data << disk_data
    disks_info["load_average"] = disk_data.last.strip.split(/\s+/)[3..-1].map(&:to_f) unless disks_info["load_average"]
  end

  captured_data.each_with_index do |disk, index|
    disk_name = disks[index]
    disk_stats = disk.last.strip.split(/\s+/)[0, 3]
    disks_info[disk_name] = {
      kb_per_trans: disk_stats[0].to_f,
      trans_num: disk_stats[1].to_f,
      mb_per_sec: disk_stats[2].to_f
    }
  end
  disks_info
end
read_proc(path) click to toggle source
# File lib/tracebin/system_health_sample.rb, line 157
def read_proc(path)
  return nil unless File.exist? path
  `cat #{path} 2>/dev/null`
end
ruby_os_identifier() click to toggle source
# File lib/tracebin/system_health_sample.rb, line 37
def ruby_os_identifier
  RbConfig::CONFIG['target_os']
end
sample_metrics() click to toggle source
# File lib/tracebin/system_health_sample.rb, line 27
def sample_metrics
  {
    process: @process.to_s,
    cpu: processor_info,
    memory: mem_info,
    disks: disk_info,
    machine_id: machine_info
  }
end