Module: OneApm::Support::SystemInfo
- Defined in:
- lib/one_apm/support/system_info.rb
Class Method Summary collapse
- .clear_processor_info ⇒ Object
- .docker_container_id ⇒ Object
- .get_processor_info ⇒ Object
- .num_logical_processors ⇒ Object
- .num_physical_cores ⇒ Object
- .num_physical_packages ⇒ Object
- .os_version ⇒ Object
- .parse_cgroup_ids(cgroup_info) ⇒ Object
- .parse_cpuinfo(cpuinfo) ⇒ Object
- .parse_docker_container_id(cgroup_info) ⇒ Object
-
.proc_try_read(path) ⇒ Object
A File.read against /(proc|sysfs)/* can hang with some older Linuxes.
- .processor_arch ⇒ Object
- .ruby_os_identifier ⇒ Object
- .sysctl_value(name) ⇒ Object
Class Method Details
.clear_processor_info ⇒ Object
12 13 14 |
# File 'lib/one_apm/support/system_info.rb', line 12 def self.clear_processor_info @processor_info = nil end |
.docker_container_id ⇒ Object
138 139 140 141 142 143 144 145 |
# File 'lib/one_apm/support/system_info.rb', line 138 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 ⇒ Object
16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/one_apm/support/system_info.rb', line 16 def self.get_processor_info if @processor_info.nil? case ruby_os_identifier when /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 when /linux/ cpuinfo = proc_try_read('/proc/cpuinfo') @processor_info = cpuinfo ? parse_cpuinfo(cpuinfo) : {} when /freebsd/ @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 |
.num_logical_processors ⇒ Object
119 120 121 122 123 124 125 126 127 128 |
# File 'lib/one_apm/support/system_info.rb', line 119 def self.num_logical_processors processor_count = get_processor_info[:num_logical_processors] if processor_count.nil? OneApm::Manager.logger.warn("Failed to determine processor count, assuming 1") processor_count = 1 end processor_count end |
.num_physical_cores ⇒ Object
118 |
# File 'lib/one_apm/support/system_info.rb', line 118 def self.num_physical_cores ; get_processor_info[:num_physical_cores ] end |
.num_physical_packages ⇒ Object
117 |
# File 'lib/one_apm/support/system_info.rb', line 117 def self.num_physical_packages ; get_processor_info[:num_physical_packages ] end |
.os_version ⇒ Object
134 135 136 |
# File 'lib/one_apm/support/system_info.rb', line 134 def self.os_version proc_try_read('/proc/version') end |
.parse_cgroup_ids(cgroup_info) ⇒ Object
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/one_apm/support/system_info.rb', line 167 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) ⇒ Object
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/one_apm/support/system_info.rb', line 68 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) ⇒ Object
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/one_apm/support/system_info.rb', line 147 def self.parse_docker_container_id(cgroup_info) cpu_cgroup = parse_cgroup_ids(cgroup_info)['cpu'] return unless cpu_cgroup 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 else OneApm::Manager.logger.debug("Ignoring unrecognized cgroup ID format: '#{cpu_cgroup}'") nil end end |
.proc_try_read(path) ⇒ Object
A File.read against /(proc|sysfs)/* can hang with some older Linuxes. See bugzilla.redhat.com/show_bug.cgi?id=604887, RUBY-736, and github.com/opscode/ohai/commit/518d56a6cb7d021b47ed3d691ecf7fba7f74a6a7 for details on why we do it this way.
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
# File 'lib/one_apm/support/system_info.rb', line 187 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 ⇒ Object
130 131 132 |
# File 'lib/one_apm/support/system_info.rb', line 130 def self.processor_arch RbConfig::CONFIG['target_cpu'] end |
.ruby_os_identifier ⇒ Object
8 9 10 |
# File 'lib/one_apm/support/system_info.rb', line 8 def self.ruby_os_identifier RbConfig::CONFIG['target_os'] end |
.sysctl_value(name) ⇒ Object
63 64 65 66 |
# File 'lib/one_apm/support/system_info.rb', line 63 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 |