def test_single_process_no_children(self): # override # process id 0 is basically no process. PID 1 is the main process of a terminal self.ps.processes = [ { "pid": 2, "ppid": 1, "cmd": "python hello.py" }, { "pid": 1, "ppid": 0, "cmd": "/bin/bash" }, ] self.ps.parent_to_children_map = defaultdict(list) self.ps.parent_to_children_map[1] = [2] self.ps.parent_to_children_map[0] = [1] self.assertEqual(self.ps.get_child_processes("bad pid"), []) self.assertEqual(self.ps.get_child_processes(1), [2]) # positive match self.assertEqual(set(self.ps.get_matches_commandline(".*")), set([1, 2])) self.assertEqual(self.ps.get_matches_commandline(".*bash.*"), [1]) self.assertEqual(self.ps.get_matches_commandline(".*py.*"), [2]) self.assertEqual( set(self.ps.get_matches_commandline_with_children(".*")), set([1, 2]))
def test_single_process_with_children(self): # override # process id 0 is basically no process. PID 1 is the main process of a terminal self.ps.processes = [{ 'pid': 2, 'ppid': 1, 'cmd': 'python hello.py' }, { 'pid': 3, 'ppid': 2, 'cmd': 'sleep 2' }, { 'pid': 1, 'ppid': 0, 'cmd': '/bin/bash' }] self.ps.parent_to_children_map = defaultdict(list) self.ps.parent_to_children_map[1] = [2] self.ps.parent_to_children_map[2] = [3] self.ps.parent_to_children_map[0] = [1] self.assertEqual(self.ps.get_child_processes('bad pid'), []) self.assertEqual(set(self.ps.get_child_processes(1)), set([2, 3])) self.assertEqual(self.ps.get_child_processes(2), [3]) # positive match self.assertEqual(set(self.ps.get_matches_commandline('.*')), set([1, 2, 3])) self.assertEqual(self.ps.get_matches_commandline('.*bash.*'), [1]) self.assertEqual(self.ps.get_matches_commandline('.*py.*'), [2]) self.assertEqual( set(self.ps.get_matches_commandline_with_children('.*')), set([1, 2, 3]))
def test_initialize_monitor(self): monitor = ProcessMonitor( self.config_commandline, scalyr_logging.getLogger("syslog_monitor[test]")) self.assertEqual(monitor._ProcessMonitor__metrics_history, defaultdict(dict)) self.assertEqual(monitor._ProcessMonitor__aggregated_metrics, {})
def _initialize(self): """Performs monitor-specific initialization.""" # The ids of the processes being monitored, if one has been matched. self.__pids = [] self.__id = self._config.get("id", required_field=True, convert_to=str) self.__commandline_matcher = self._config.get("commandline", default=None, convert_to=str) self.__aggregate_multiple_processes = self._config.get( "aggregate_multiple_processes", default=False, convert_to=bool) self.__include_child_processes = self._config.get( "include_child_processes", default=False, convert_to=bool) self.__trackers = { } # key -> process id, value -> ProcessTracker object # poll interval (in seconds) for matching processes when we are monitoring multiple processes # alive for all epochs of the monitor. self.__last_discovered = None self.__process_discovery_interval = self._config.get( "process_discovery_interval", default=120, convert_to=int) self.__target_pids = self._config.get("pid", default=None, convert_to=str) if self.__target_pids: self.__target_pids = self.__target_pids.split(",") else: self.__target_pids = [] # Last 2 values of all metrics which has form: # { # '<process id>: { # <metric name>: [<metric at time 0>, <metric at time 1>], # <metric name>: [<metric at time 0>, <metric at time 1>], # } # '<process id>: { # <metric name>: [<metric at time 0>, <metric at time 1>], # <metric name>: [<metric at time 0>, <metric at time 1>], # } # } self.__metrics_history = defaultdict(dict) # running total of metric values, both for cumulative and non-cumulative metrics self.__aggregated_metrics = {} if not (self.__commandline_matcher or self.__target_pids): raise BadMonitorConfiguration( "At least one of the following fields must be provide: commandline or pid", "commandline", ) # Make sure to set our configuration so that the proper parser is used. self.log_config = { "parser": "agent-metrics", "path": "linux_process_metrics.log", }
def __init__(self): # list of {'pid': processid, 'ppid': parentprocessid, 'cmd': command } self.processes = [] # key -> parent process id, value -> [child process ids...] self.parent_to_children_map = defaultdict(list) cmd = ["ps", "axo", "pid,ppid,command"] sub_proc = Popen(cmd, shell=False, stdout=PIPE) # regex intended to capture pid, ppid and the command eg: # 593 0 /bin/bash regex = r"\s*(\d+)\s+(\d+)\s+(.*)" # 2->TODO stdout is binary in Python3 sub_proc_output = sub_proc.stdout.read() sub_proc_output = sub_proc_output.decode("utf-8") for line in sub_proc_output.splitlines(True): match = re.search(regex, line) if match: _pid, _ppid, _cmd = match.groups() self.processes.append({ "pid": int(_pid), "ppid": int(_ppid), "cmd": _cmd }) for _process in self.processes: ppid = _process["ppid"] pid = _process["pid"] if ppid != pid: self.parent_to_children_map[ppid].append(pid)
def __init__(self): # list of {'pid': processid, 'ppid': parentprocessid, 'cmd': command } self.processes = [] # key -> parent process id, value -> [child process ids...] self.parent_to_children_map = defaultdict(list) cmd = ['ps', 'axo', 'pid,ppid,command'] sub_proc = Popen(cmd, shell=False, stdout=PIPE) # regex intended to capture pid, ppid and the command eg: # 593 0 /bin/bash regex = r"\s*(\d+)\s+(\d+)\s+(.*)" lines = sub_proc.stdout.readlines() for line in lines: match = re.search(regex, line) if match: _pid, _ppid, _cmd = match.groups() self.processes.append({ 'pid': int(_pid), 'ppid': int(_ppid), 'cmd': _cmd }) for _process in self.processes: ppid = _process['ppid'] pid = _process['pid'] if ppid != pid: self.parent_to_children_map[ppid].append(pid)
def test_no_process(self): # override self.ps.parent_to_children_map = defaultdict(list) self.ps.processes = [] self.assertEqual(self.ps.get_child_processes('bad pid'), []) self.assertEqual(self.ps.get_matches_commandline('.*'), []) self.assertEqual(self.ps.get_matches_commandline_with_children('.*'), [])
def test_no_process(self): # override self.ps.parent_to_children_map = defaultdict(list) self.ps.processes = [] self.assertEqual(self.ps.get_child_processes("bad pid"), []) self.assertEqual(self.ps.get_matches_commandline(".*"), []) self.assertEqual(self.ps.get_matches_commandline_with_children(".*"), [])
def _initialize(self): """Performs monitor-specific initialization.""" # The ids of the processes being monitored, if one has been matched. self.__pids = [] self.__id = self._config.get('id', required_field=True, convert_to=str) self.__commandline_matcher = self._config.get('commandline', default=None, convert_to=str) self.__aggregate_multiple_processes = self._config.get( 'aggregate_multiple_processes', default=False, convert_to=bool ) self.__include_child_processes = self._config.get( 'include_child_processes', default=False, convert_to=bool ) self.__trackers = {} # key -> process id, value -> ProcessTracker object # poll interval (in seconds) for matching processes when we are monitoring multiple processes # alive for all epochs of the monitor. self.__last_discovered = None self.__process_discovery_interval = self._config.get('process_discovery_interval', default=120, convert_to=int) self.__target_pids = self._config.get('pid', default=None, convert_to=str) if self.__target_pids: self.__target_pids = self.__target_pids.split(",") else: self.__target_pids = [] # Last 2 values of all metrics which has form: # { # '<process id>: { # <metric name>: [<metric at time 0>, <metric at time 1>], # <metric name>: [<metric at time 0>, <metric at time 1>], # } # '<process id>: { # <metric name>: [<metric at time 0>, <metric at time 1>], # <metric name>: [<metric at time 0>, <metric at time 1>], # } # } self.__metrics_history = defaultdict(dict) # running total of metric values, both for cumulative and non-cumulative metrics self.__aggregated_metrics = {} if not (self.__commandline_matcher or self.__target_pids): raise BadMonitorConfiguration( 'At least one of the following fields must be provide: commandline or pid', 'commandline' ) # Make sure to set our configuration so that the proper parser is used. self.log_config = { 'parser': 'agent-metrics', 'path': 'linux_process_metrics.log', }
def test_single_process_no_children(self): # override # process id 0 is basically no process. PID 1 is the main process of a terminal self.ps.processes = [ {'pid': 2, 'ppid': 1, 'cmd': 'python hello.py'}, {'pid': 1, 'ppid': 0, 'cmd': '/bin/bash'} ] self.ps.parent_to_children_map = defaultdict(list) self.ps.parent_to_children_map[1] = [2] self.ps.parent_to_children_map[0] = [1] self.assertEqual(self.ps.get_child_processes('bad pid'), []) self.assertEqual(self.ps.get_child_processes(1), [2]) # positive match self.assertEqual(set(self.ps.get_matches_commandline('.*')), set([1, 2])) self.assertEqual(self.ps.get_matches_commandline('.*bash.*'), [1]) self.assertEqual(self.ps.get_matches_commandline('.*py.*'), [2]) self.assertEqual(set(self.ps.get_matches_commandline_with_children('.*')), set([1, 2]))
def __init__(self): # list of {'pid': processid, 'ppid': parentprocessid, 'cmd': command } self.processes = [] # key -> parent process id, value -> [child process ids...] self.parent_to_children_map = defaultdict(list) cmd = ['ps', 'axo', 'pid,ppid,command'] sub_proc = Popen(cmd, shell=False, stdout=PIPE) # regex intended to capture pid, ppid and the command eg: # 593 0 /bin/bash regex = r"\s*(\d+)\s+(\d+)\s+(.*)" lines = sub_proc.stdout.readlines() for line in lines: match = re.search(regex, line) if match: _pid, _ppid, _cmd = match.groups() self.processes.append({'pid': int(_pid), 'ppid': int(_ppid), 'cmd': _cmd}) for _process in self.processes: ppid = _process['ppid'] pid = _process['pid'] if ppid != pid: self.parent_to_children_map[ppid].append(pid)
def test_empty_metrics(self): self.monitor.record_metrics(666, {}) self.assertEqual(self.monitor._ProcessMonitor__metrics_history, defaultdict(dict))
def test_initialize_monitor(self): monitor = ProcessMonitor(self.config_commandline, scalyr_logging.getLogger("syslog_monitor[test]")) self.assertEqual(monitor._ProcessMonitor__metrics_history, defaultdict(dict)) self.assertEqual(monitor._ProcessMonitor__aggregated_metrics, {})