summaryrefslogtreecommitdiffstats
path: root/src/data_collection/processes/windows.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/data_collection/processes/windows.rs')
-rw-r--r--src/data_collection/processes/windows.rs128
1 files changed, 128 insertions, 0 deletions
diff --git a/src/data_collection/processes/windows.rs b/src/data_collection/processes/windows.rs
new file mode 100644
index 00000000..08309a55
--- /dev/null
+++ b/src/data_collection/processes/windows.rs
@@ -0,0 +1,128 @@
+//! Process data collection for Windows. Uses sysinfo.
+
+use std::time::Duration;
+
+use sysinfo::{CpuExt, PidExt, ProcessExt, SystemExt, UserExt};
+
+use super::ProcessHarvest;
+
+use crate::data_collection::DataCollector;
+
+pub fn sysinfo_process_data(
+ collector: &mut DataCollector,
+) -> crate::utils::error::Result<Vec<ProcessHarvest>> {
+ let sys = &collector.sys;
+ let use_current_cpu_total = collector.use_current_cpu_total;
+ let unnormalized_cpu = collector.unnormalized_cpu;
+ let total_memory = collector.total_memory();
+
+ let mut process_vector: Vec<ProcessHarvest> = Vec::new();
+ let process_hashmap = sys.processes();
+ let cpu_usage = sys.global_cpu_info().cpu_usage() as f64 / 100.0;
+ let num_processors = sys.cpus().len();
+
+ for process_val in process_hashmap.values() {
+ let name = if process_val.name().is_empty() {
+ let process_cmd = process_val.cmd();
+ if process_cmd.len() > 1 {
+ process_cmd[0].clone()
+ } else {
+ let process_exe = process_val.exe().file_stem();
+ if let Some(exe) = process_exe {
+ let process_exe_opt = exe.to_str();
+ if let Some(exe_name) = process_exe_opt {
+ exe_name.to_string()
+ } else {
+ "".to_string()
+ }
+ } else {
+ "".to_string()
+ }
+ }
+ } else {
+ process_val.name().to_string()
+ };
+ let command = {
+ let command = process_val.cmd().join(" ");
+ if command.is_empty() {
+ name.to_string()
+ } else {
+ command
+ }
+ };
+
+ let pcu = {
+ let usage = process_val.cpu_usage() as f64;
+ if unnormalized_cpu || num_processors == 0 {
+ usage
+ } else {
+ usage / (num_processors as f64)
+ }
+ };
+ let process_cpu_usage = if use_current_cpu_total && cpu_usage > 0.0 {
+ pcu / cpu_usage
+ } else {
+ pcu
+ } as f32;
+
+ let disk_usage = process_val.disk_usage();
+ let process_state = (process_val.status().to_string(), 'R');
+
+ #[cfg(feature = "gpu")]
+ let (gpu_mem, gpu_util, gpu_mem_percent) = {
+ let mut gpu_mem = 0;
+ let mut gpu_util = 0;
+ let mut gpu_mem_percent = 0.0;
+ if let Some(gpus) = &collector.gpu_pids {
+ gpus.iter().for_each(|gpu| {
+ // add mem/util for all gpus to pid
+ if let Some((mem, util)) = gpu.get(&process_val.pid().as_u32()) {
+ gpu_mem += mem;
+ gpu_util += util;
+ }
+ });
+ }
+ if let Some(gpu_total_mem) = &collector.gpus_total_mem {
+ gpu_mem_percent = (gpu_mem as f64 / *gpu_total_mem as f64 * 100.0) as f32;
+ }
+ (gpu_mem, gpu_util, gpu_mem_percent)
+ };
+ process_vector.push(ProcessHarvest {
+ pid: process_val.pid().as_u32() as _,
+ parent_pid: process_val.parent().map(|p| p.as_u32() as _),
+ name,
+ command,
+ mem_usage_percent: if total_memory > 0 {
+ process_val.memory() as f64 * 100.0 / total_memory as f64
+ } else {
+ 0.0
+ } as f32,
+ mem_usage_bytes: process_val.memory(),
+ cpu_usage_percent: process_cpu_usage,
+ read_bytes_per_sec: disk_usage.read_bytes,
+ write_bytes_per_sec: disk_usage.written_bytes,
+ total_read_bytes: disk_usage.total_read_bytes,
+ total_write_bytes: disk_usage.total_written_bytes,
+ process_state,
+ user: process_val
+ .user_id()
+ .and_then(|uid| sys.get_user_by_id(uid))
+ .map_or_else(|| "N/A".into(), |user| user.name().to_owned().into()),
+ time: if process_val.start_time() == 0 {
+ // Workaround for Windows occasionally returning a start time equal to UNIX epoch, giving a run time
+ // in the range of 50+ years. We just return a time of zero in this case for simplicity.
+ Duration::ZERO
+ } else {
+ Duration::from_secs(process_val.run_time())
+ },
+ #[cfg(feature = "gpu")]
+ gpu_mem,
+ #[cfg(feature = "gpu")]
+ gpu_util,
+ #[cfg(feature = "gpu")]
+ gpu_mem_percent,
+ });
+ }
+
+ Ok(process_vector)
+}