diff --git a/src/server_monitor_agent/service/server/model.py b/src/server_monitor_agent/service/server/model.py index b11a582..060062a 100644 --- a/src/server_monitor_agent/service/server/model.py +++ b/src/server_monitor_agent/service/server/model.py @@ -82,10 +82,26 @@ class ProcessResult(agent_model.OpResult): user: typing.Optional[str] = None pid: typing.Optional[int] = None cpu_percent: typing.Optional[float] = None + """gauge of percent of total system cpu usage since last call""" mem_percent: typing.Optional[float] = None + """gauge of percent of total system memory used by process rss""" vms: typing.Optional[int] = None + """gauge of 'Virtual Memory Size', the total amount of virtual memory used by a process""" rss: typing.Optional[int] = None + """gauge of 'Resident Set Size', the non-swapped physical memory used by a process""" cmdline: typing.Optional[str] = None + io_read_ops_count: typing.Optional[int] = None + """counter (cumulative) of number of process I/O read operations""" + io_write_ops_count: typing.Optional[int] = None + """counter (cumulative) of number of process I/O write operations""" + io_read_bytes_count: typing.Optional[int] = None + """counter (cumulative) of number of process I/O bytes read""" + io_write_bytes_count: typing.Optional[int] = None + """counter (cumulative) of number of process I/O bytes written""" + cpu_time_count: typing.Optional[float] = None + """counter (cumulative) of cpu time used by system and user""" + cpu_usable_count: typing.Optional[int] = None + """gauge of number of cpus process can use""" @beartype.beartype diff --git a/src/server_monitor_agent/service/server/operation.py b/src/server_monitor_agent/service/server/operation.py index 1079ebe..d62d48e 100644 --- a/src/server_monitor_agent/service/server/operation.py +++ b/src/server_monitor_agent/service/server/operation.py @@ -145,6 +145,10 @@ def cpu_usage(interval: float = 2.0) -> float: def processes() -> typing.List[server_model.ProcessResult]: """Get a list of the local processes.""" + # Note: Linux doesn't seem to expose easily usable per-process network stats. + # Maybe `sudo lsof -niTCP` combined with `iftop`? + # See https://github.com/giampaolo/psutil/issues/1900 + result = [] attrs = { "pid": "PID", @@ -154,6 +158,8 @@ def processes() -> typing.List[server_model.ProcessResult]: "cpu_percent": "%CPU", "memory_info": ["VSZ", "RSS"], "username": "USER", + "io_counters": "", + "cpu_times": "", } count = 0 for p in psutil.process_iter(attrs=list(attrs.keys()), ad_value=None): @@ -168,9 +174,15 @@ def processes() -> typing.List[server_model.ProcessResult]: vms = info.get("memory_info").vms if info.get("memory_info") else 0 rss = info.get("memory_info").rss if info.get("memory_info") else 0 + # ignore a process that is using no memory + if (vms + rss) < 1: + continue + + # note that memory percent can be 0 if there is no previous information mem_raw = info.get("memory_percent") mem_p = round(mem_raw, 1) if mem_raw is not None else None + # note that cpu percent can be 0 if there is no previous information cpu_raw = info.get("cpu_percent") cpu_p = round(cpu_raw, 1) if cpu_raw is not None else None @@ -179,6 +191,17 @@ def processes() -> typing.List[server_model.ProcessResult]: else: cmdline = info.get("name") + io_counters = info.get("io_counters") + io_read_ops_count = io_counters.read_count + io_write_ops_count = io_counters.write_count + io_read_bytes_count = io_counters.read_bytes + io_write_bytes_count = io_counters.write_bytes + + cpu_times = info.get("cpu_times") + cpu_time_count = cpu_times.user + cpu_times.system + + cpu_usable_count = len(p.cpu_affinity()) + result.append( server_model.ProcessResult( exit_code=0, @@ -189,6 +212,12 @@ def processes() -> typing.List[server_model.ProcessResult]: vms=vms, rss=rss, cmdline=cmdline, + io_read_ops_count=io_read_ops_count, + io_write_ops_count=io_write_ops_count, + io_read_bytes_count=io_read_bytes_count, + io_write_bytes_count=io_write_bytes_count, + cpu_time_count=cpu_time_count, + cpu_usable_count=cpu_usable_count, ) )