module Mmtrix::Agent::SystemInfo
Public Class Methods
bsd?()
click to toggle source
# File lib/mmtrix/agent/system_info.rb, line 27 def self.bsd? !!(ruby_os_identifier =~ /bsd/i) end
clear_processor_info()
click to toggle source
# File lib/mmtrix/agent/system_info.rb, line 33 def self.clear_processor_info @processor_info = nil end
darwin?()
click to toggle source
# File lib/mmtrix/agent/system_info.rb, line 19 def self.darwin? !!(ruby_os_identifier =~ /darwin/i) end
docker_container_id()
click to toggle source
# File lib/mmtrix/agent/system_info.rb, line 148 def self.docker_container_id return unless ruby_os_identifier =~ /linux/ cgroup_info = proc_try_read('/proc/self/cgroup') return unless cgroup_info parse_docker_container_id(cgroup_info) end
get_processor_info()
click to toggle source
# File lib/mmtrix/agent/system_info.rb, line 37 def self.get_processor_info if @processor_info.nil? if darwin? @processor_info = { :num_physical_packages => sysctl_value('hw.packages').to_i, :num_physical_cores => sysctl_value('hw.physicalcpu_max').to_i, :num_logical_processors => sysctl_value('hw.logicalcpu_max').to_i } # in case those don't work, try backup values if @processor_info[:num_physical_cores] <= 0 @processor_info[:num_physical_cores] = sysctl_value('hw.physicalcpu').to_i end if @processor_info[:num_logical_processors] <= 0 @processor_info[:num_logical_processors] = sysctl_value('hw.logicalcpu').to_i end if @processor_info[:num_logical_processors] <= 0 @processor_info[:num_logical_processors] = sysctl_value('hw.ncpu').to_i end elsif linux? cpuinfo = proc_try_read('/proc/cpuinfo') @processor_info = cpuinfo ? parse_cpuinfo(cpuinfo) : {} elsif bsd? @processor_info = { :num_physical_packages => nil, :num_physical_cores => nil, :num_logical_processors => sysctl_value('hw.ncpu').to_i } end # give nils for obviously wrong values @processor_info.keys.each do |key| value = @processor_info[key] if value.is_a?(Numeric) && value <= 0 @processor_info[key] = nil end end end @processor_info rescue {} end
linux?()
click to toggle source
# File lib/mmtrix/agent/system_info.rb, line 23 def self.linux? !!(ruby_os_identifier =~ /linux/i) end
num_logical_processors()
click to toggle source
# File lib/mmtrix/agent/system_info.rb, line 138 def self.num_logical_processors; get_processor_info[:num_logical_processors] end
num_physical_cores()
click to toggle source
# File lib/mmtrix/agent/system_info.rb, line 137 def self.num_physical_cores ; get_processor_info[:num_physical_cores ] end
num_physical_packages()
click to toggle source
# File lib/mmtrix/agent/system_info.rb, line 136 def self.num_physical_packages ; get_processor_info[:num_physical_packages ] end
os_version()
click to toggle source
# File lib/mmtrix/agent/system_info.rb, line 144 def self.os_version proc_try_read('/proc/version') end
parse_cgroup_ids(cgroup_info)
click to toggle source
# File lib/mmtrix/agent/system_info.rb, line 189 def self.parse_cgroup_ids(cgroup_info) cgroup_ids = {} cgroup_info.split("\n").each do |line| parts = line.split(':') next unless parts.size == 3 _, subsystems, cgroup_id = parts subsystems = subsystems.split(',') subsystems.each do |subsystem| cgroup_ids[subsystem] = cgroup_id end end cgroup_ids end
parse_cpuinfo(cpuinfo)
click to toggle source
# File lib/mmtrix/agent/system_info.rb, line 87 def self.parse_cpuinfo(cpuinfo) # Build a hash of the form # { [phys_id, core_id] => num_logical_processors_on_this_core } cores = Hash.new(0) phys_id = core_id = nil total_processors = 0 cpuinfo.split("\n").map(&:strip).each do |line| case line when /^processor\s*:/ cores[[phys_id, core_id]] += 1 if phys_id && core_id phys_id = core_id = nil # reset these values total_processors += 1 when /^physical id\s*:(.*)/ phys_id = $1.strip.to_i when /^core id\s*:(.*)/ core_id = $1.strip.to_i end end cores[[phys_id, core_id]] += 1 if phys_id && core_id num_physical_packages = cores.keys.map(&:first).uniq.size num_physical_cores = cores.size num_logical_processors = cores.values.reduce(0,:+) if num_physical_cores == 0 num_logical_processors = total_processors if total_processors == 1 # Some older, single-core processors might not list ids, # so we'll just mark them all 1. num_physical_packages = 1 num_physical_cores = 1 else # We have no way of knowing how many packages or cores # we have, even though we know how many processors there are. num_physical_packages = nil num_physical_cores = nil end end { :num_physical_packages => num_physical_packages, :num_physical_cores => num_physical_cores, :num_logical_processors => num_logical_processors } end
parse_docker_container_id(cgroup_info)
click to toggle source
# File lib/mmtrix/agent/system_info.rb, line 157 def self.parse_docker_container_id(cgroup_info) cpu_cgroup = parse_cgroup_ids(cgroup_info)['cpu'] return unless cpu_cgroup container_id = case cpu_cgroup # docker native driver w/out systemd (fs) when %r{^/docker/([0-9a-f]+)$} then $1 # docker native driver with systemd when %r{^/system\.slice/docker-([0-9a-f]+)\.scope$} then $1 # docker lxc driver when %r{^/lxc/([0-9a-f]+)$} then $1 # not in any cgroup when '/' then nil # in a cgroup, but we don't recognize its format when %r{docker} then ::Mmtrix::Agent.logger.debug("Cgroup indicates docker but container_id unrecognized: '#{cpu_cgroup}'") ::Mmtrix::Agent.increment_metric "Supportability/utilization/docker/error" return else ::Mmtrix::Agent.logger.debug("Ignoring unrecognized cgroup ID format: '#{cpu_cgroup}'") return end if container_id && container_id.size != 64 ::Mmtrix::Agent.logger.debug("Found docker container_id with invalid length: #{container_id}") ::Mmtrix::Agent.increment_metric "Supportability/utilization/docker/error" nil else container_id end end
parse_linux_meminfo_in_mib(meminfo)
click to toggle source
# File lib/mmtrix/agent/system_info.rb, line 239 def self.parse_linux_meminfo_in_mib(meminfo) if mem_total = meminfo[/MemTotal:\s*(\d*)\skB/,1] mem_total.to_i / 1024 else ::Mmtrix::Agent.logger.debug("Failed to parse MemTotal from /proc/meminfo: #{meminfo}") nil end end
proc_try_read(path)
click to toggle source
A File.read against /(proc|sysfs)/* can hang with some older Linuxes. for details on why we do it this way.
# File lib/mmtrix/agent/system_info.rb, line 207 def self.proc_try_read(path) return nil unless File.exist?(path) content = '' File.open(path) do |f| loop do begin content << f.read_nonblock(4096) rescue EOFError break rescue Errno::EWOULDBLOCK, Errno::EAGAIN content = nil break # don't select file handle, just give up end end end content end
processor_arch()
click to toggle source
# File lib/mmtrix/agent/system_info.rb, line 140 def self.processor_arch RbConfig::CONFIG['target_cpu'] end
ram_in_mib()
click to toggle source
# File lib/mmtrix/agent/system_info.rb, line 225 def self.ram_in_mib if darwin? sysctl_value('hw.memsize').to_i / (1024 ** 2) elsif linux? meminfo = proc_try_read('/proc/meminfo') parse_linux_meminfo_in_mib(meminfo) elsif bsd? sysctl_value('hw.realmem').to_i / (1024 ** 2) else ::Mmtrix::Agent.logger.debug("Unable to determine ram_in_mib for host os: #{ruby_os_identifier}") nil end end
ruby_os_identifier()
click to toggle source
# File lib/mmtrix/agent/system_info.rb, line 15 def self.ruby_os_identifier RbConfig::CONFIG['target_os'] end
sysctl_value(name)
click to toggle source
# File lib/mmtrix/agent/system_info.rb, line 82 def self.sysctl_value(name) # make sure to redirect stderr so we don't spew if the name is unknown `sysctl -n #{name} 2>/dev/null` end