class General
General process information.
Definitions
def as_json
Convert the object to a JSON serializable hash.
Implementation
def as_json
{
process_id: self.process_id,
parent_process_id: self.parent_process_id,
process_group_id: self.process_group_id,
processor_utilization: self.processor_utilization,
total_size: self.total_size,
virtual_size: self.virtual_size,
resident_size: self.resident_size,
processor_time: self.processor_time,
elapsed_time: self.elapsed_time,
command: self.command,
memory: self.memory&.as_json,
}
end
def to_json(*arguments)
Convert the object to a JSON string.
Implementation
def to_json(*arguments)
as_json.to_json(*arguments)
end
def total_size
The total size of the process in memory, in kilobytes.
Implementation
def total_size
if memory = self.memory
memory.proportional_size
else
self.resident_size
end
end
def self.expand_children(children, hierarchy, pids)
Recursively expand a set of child PIDs into a collection.
Signature
-
parameter
childrenArray<Integer> The list of child process IDs to expand.
-
parameter
hierarchyHash<Integer, Array<Integer>> The parent-to-children process hierarchy.
-
parameter
pidsSet<Integer> The set to populate with process IDs.
Implementation
def self.expand_children(children, hierarchy, pids)
children.each do |pid|
self.expand(pid, hierarchy, pids)
end
end
def self.expand(pid, hierarchy, pids)
Recursively expand a process and its descendants into a collection.
Signature
-
parameter
pidInteger The process ID to expand.
-
parameter
hierarchyHash<Integer, Array<Integer>> The parent-to-children process hierarchy.
-
parameter
pidsSet<Integer> The set to populate with process IDs.
Implementation
def self.expand(pid, hierarchy, pids)
unless pids.include?(pid)
pids << pid
if children = hierarchy.fetch(pid, nil)
self.expand_children(children, hierarchy, pids)
end
end
end
def self.build_tree(processes)
Build a parent-to-children process hierarchy from a set of processes.
Signature
-
parameter
processesHash<Integer, General> A hash mapping PIDs to General instances.
-
returns
Hash<Integer, Array<Integer>> A hash mapping each parent PID to an array of child PIDs.
Implementation
def self.build_tree(processes)
hierarchy = Hash.new{|h,k| h[k] = []}
processes.each_value do |process|
if parent_process_id = process.parent_process_id
hierarchy[parent_process_id] << process.process_id
end
end
return hierarchy
end
def self.capture_memory(processes)
Capture detailed memory metrics for each process in the given collection.
Signature
-
parameter
processesHash<Integer, General> A hash mapping PIDs to General instances.
Implementation
def self.capture_memory(processes)
count = processes.size
processes.each do |pid, process|
process.memory = Memory.capture(pid, count: count)
end
end
def self.capture(pid: nil, ppid: nil, memory: Memory.supported?)
Capture process information. If given a pid, it will capture the details of that process. If given a ppid, it will capture the details of all child processes. Specify both pid and ppid if you want to capture a process and all its children.
Signature
-
parameter
pidInteger The process ID to capture.
-
parameter
ppidInteger The parent process ID to capture.
Implementation
def self.capture(pid: nil, ppid: nil, memory: Memory.supported?)
ps_pid = nil
# Extract the information from the `ps` command:
header, *lines = IO.pipe do |input, output|
arguments = [PS]
if pid && ppid.nil?
arguments.push("-p", Array(pid).join(","))
else
arguments.push("ax")
end
arguments.push("-o", FIELDS.keys.join(","))
ps_pid = Process.spawn(*arguments, out: output)
output.close
input.readlines.map(&:strip)
ensure
input.close
if ps_pid
begin
# Make sure to kill the ps process if it's still running:
Process.kill(:KILL, ps_pid)
# Reap the process:
Process.wait(ps_pid)
rescue => error
warn "Failed to cleanup ps process #{ps_pid}:\n#{error.full_message}"
end
end
end
processes = {}
lines.map do |line|
record = FIELDS.
zip(line.split(/\s+/, FIELDS.size)).
map{|(key, type), value| type.call(value)}
instance = self.new(*record)
processes[instance.process_id] = instance
end
if ppid
pids = Set.new
hierarchy = self.build_tree(processes)
self.expand_children(Array(pid), hierarchy, pids)
self.expand_children(Array(ppid), hierarchy, pids)
processes.select! do |pid, process|
if pid != ps_pid
pids.include?(pid)
end
end
end
if memory
self.capture_memory(processes)
end
return processes
end