class Process::Metrics::General

General process information.

def self.build_tree(processes)

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(pid: nil, ppid: nil, ps: PS, memory: Memory.supported?)

@parameter ppid [Integer] The parent process ID to capture.
@parameter pid [Integer] The process ID to capture.

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.
def self.capture(pid: nil, ppid: nil, ps: PS, memory: Memory.supported?)
	input, output = IO.pipe
	
	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, pgroup: true)
	
	output.close
	
	header, *lines = input.readlines.map(&:strip)
	
	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
ensure
	Process.wait(ps_pid) if ps_pid
end

def self.capture_memory(processes)

def self.capture_memory(processes)
	count = processes.size
	
	processes.each do |pid, process|
		process.memory = Memory.capture(pid, count: count)
	end
end

def self.expand(pid, hierarchy, pids)

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.expand_children(children, hierarchy, pids)

def self.expand_children(children, hierarchy, pids)
	children.each do |pid|
		self.expand(pid, hierarchy, pids)
	end
end

def as_json

Convert the object to a JSON serializable hash.
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.
def to_json(*arguments)
	as_json.to_json(*arguments)
end

def total_size

The total size of the process in memory, in kilobytes.
def total_size
	if memory = self.memory
		memory.proportional_size
	else
		self.resident_size
	end
end