mirror of
https://github.com/ClementTsang/bottom
synced 2024-11-22 12:13:06 +00:00
refactor: Remove ps calls
Removes and refactor ps calls that... should have not been there in the first place.
This commit is contained in:
parent
4b03b4b0b0
commit
1dc9346d3b
10 changed files with 151 additions and 137 deletions
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
|
@ -13,6 +13,7 @@
|
|||
"WASD",
|
||||
"Wojnarowski",
|
||||
"andys",
|
||||
"cmdline",
|
||||
"crossterm",
|
||||
"curr",
|
||||
"czvf",
|
||||
|
@ -29,9 +30,12 @@
|
|||
"paren",
|
||||
"processthreadsapi",
|
||||
"regexes",
|
||||
"rsplitn",
|
||||
"rustfmt",
|
||||
"shilangyu",
|
||||
"softirq",
|
||||
"splitn",
|
||||
"statm",
|
||||
"stime",
|
||||
"subwidget",
|
||||
"sysconf",
|
||||
|
@ -43,6 +47,7 @@
|
|||
"use curr usage",
|
||||
"utime",
|
||||
"virt",
|
||||
"vsize",
|
||||
"whitespaces",
|
||||
"winapi",
|
||||
"winnt",
|
||||
|
|
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -145,6 +145,7 @@ dependencies = [
|
|||
"heim",
|
||||
"itertools",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"log",
|
||||
"predicates",
|
||||
"regex",
|
||||
|
|
|
@ -40,7 +40,7 @@ backtrace = "0.3"
|
|||
serde = {version = "1.0", features = ["derive"] }
|
||||
unicode-segmentation = "1.6.0"
|
||||
unicode-width = "0.1.7"
|
||||
# libc = "0.2.74"
|
||||
libc = "0.2.74"
|
||||
# tui = {version = "0.10.0", features = ["crossterm"], default-features = false, git = "https://github.com/fdehau/tui-rs.git"}
|
||||
tui = {version = "0.9.5", features = ["crossterm"], default-features = false }
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ pub struct DataCollector {
|
|||
pub data: Data,
|
||||
sys: System,
|
||||
#[cfg(target_os = "linux")]
|
||||
prev_pid_stats: HashMap<u32, processes::PrevProcDetails>,
|
||||
pid_mapping: HashMap<u32, processes::PrevProcDetails>,
|
||||
#[cfg(target_os = "linux")]
|
||||
prev_idle: f64,
|
||||
#[cfg(target_os = "linux")]
|
||||
|
@ -87,7 +87,7 @@ pub struct DataCollector {
|
|||
widgets_to_harvest: UsedWidgets,
|
||||
battery_manager: Option<Manager>,
|
||||
battery_list: Option<Vec<Battery>>,
|
||||
// page_file_size_kb: u64,
|
||||
page_file_size_kb: u64,
|
||||
}
|
||||
|
||||
impl Default for DataCollector {
|
||||
|
@ -96,7 +96,7 @@ impl Default for DataCollector {
|
|||
data: Data::default(),
|
||||
sys: System::new_all(),
|
||||
#[cfg(target_os = "linux")]
|
||||
prev_pid_stats: HashMap::new(),
|
||||
pid_mapping: HashMap::new(),
|
||||
#[cfg(target_os = "linux")]
|
||||
prev_idle: 0_f64,
|
||||
#[cfg(target_os = "linux")]
|
||||
|
@ -111,11 +111,15 @@ impl Default for DataCollector {
|
|||
widgets_to_harvest: UsedWidgets::default(),
|
||||
battery_manager: None,
|
||||
battery_list: None,
|
||||
// page_file_size_kb: if cfg!(target_os = "linux") {
|
||||
// unsafe { libc::sysconf(libc::_SC_PAGESIZE) as u64 / 1024 }
|
||||
// } else {
|
||||
// 0
|
||||
// },
|
||||
page_file_size_kb: {
|
||||
#[cfg(target_os = "linux")]
|
||||
unsafe {
|
||||
libc::sysconf(libc::_SC_PAGESIZE) as u64 / 1024
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
0
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -201,12 +205,13 @@ impl DataCollector {
|
|||
processes::linux_get_processes_list(
|
||||
&mut self.prev_idle,
|
||||
&mut self.prev_non_idle,
|
||||
&mut self.prev_pid_stats,
|
||||
&mut self.pid_mapping,
|
||||
self.use_current_cpu_total,
|
||||
current_instant
|
||||
.duration_since(self.last_collection_time)
|
||||
.as_secs(),
|
||||
self.mem_total_kb,
|
||||
self.page_file_size_kb,
|
||||
)
|
||||
}
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
|
|
|
@ -2,12 +2,10 @@ use std::path::PathBuf;
|
|||
use sysinfo::ProcessStatus;
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
use crate::utils::error;
|
||||
use crate::utils::error::{self, BottomError};
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
use std::{
|
||||
collections::{hash_map::RandomState, HashMap},
|
||||
process::Command,
|
||||
};
|
||||
use std::collections::{hash_map::RandomState, HashMap};
|
||||
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
use sysinfo::{ProcessExt, ProcessorExt, System, SystemExt};
|
||||
|
@ -66,7 +64,7 @@ pub struct ProcessHarvest {
|
|||
// pub rss_kb: u64,
|
||||
// pub virt_kb: u64,
|
||||
pub name: String,
|
||||
pub path: String,
|
||||
pub command: String,
|
||||
pub read_bytes_per_sec: u64,
|
||||
pub write_bytes_per_sec: u64,
|
||||
pub total_read_bytes: u64,
|
||||
|
@ -81,17 +79,21 @@ pub struct PrevProcDetails {
|
|||
pub total_write_bytes: u64,
|
||||
pub cpu_time: f64,
|
||||
pub proc_stat_path: PathBuf,
|
||||
// pub proc_statm_path: PathBuf,
|
||||
pub proc_exe_path: PathBuf,
|
||||
pub proc_io_path: PathBuf,
|
||||
pub proc_cmdline_path: PathBuf,
|
||||
pub just_read: bool,
|
||||
}
|
||||
|
||||
impl PrevProcDetails {
|
||||
pub fn new(pid: u32) -> Self {
|
||||
let pid_string = pid.to_string();
|
||||
PrevProcDetails {
|
||||
proc_io_path: PathBuf::from(format!("/proc/{}/io", pid_string)),
|
||||
proc_exe_path: PathBuf::from(format!("/proc/{}/exe", pid_string)),
|
||||
proc_stat_path: PathBuf::from(format!("/proc/{}/stat", pid_string)),
|
||||
proc_io_path: PathBuf::from(format!("/proc/{}/io", pid)),
|
||||
proc_exe_path: PathBuf::from(format!("/proc/{}/exe", pid)),
|
||||
proc_stat_path: PathBuf::from(format!("/proc/{}/stat", pid)),
|
||||
// proc_statm_path: PathBuf::from(format!("/proc/{}/statm", pid)),
|
||||
proc_cmdline_path: PathBuf::from(format!("/proc/{}/cmdline", pid)),
|
||||
..PrevProcDetails::default()
|
||||
}
|
||||
}
|
||||
|
@ -172,23 +174,32 @@ fn get_process_io(path: &PathBuf) -> std::io::Result<String> {
|
|||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn get_linux_process_io_usage(io_stats: &[&str]) -> (u64, u64) {
|
||||
fn get_linux_process_io_usage(stat: &[&str]) -> (u64, u64) {
|
||||
// Represents read_bytes and write_bytes
|
||||
(
|
||||
io_stats[9].parse::<u64>().unwrap_or(0),
|
||||
io_stats[11].parse::<u64>().unwrap_or(0),
|
||||
stat[9].parse::<u64>().unwrap_or(0),
|
||||
stat[11].parse::<u64>().unwrap_or(0),
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn get_process_stats(path: &PathBuf) -> std::io::Result<String> {
|
||||
fn get_linux_process_vsize_rss(stat: &[&str]) -> (u64, u64) {
|
||||
// Represents vsize and rss (bytes and page numbers respectively)
|
||||
(
|
||||
stat[20].parse::<u64>().unwrap_or(0),
|
||||
stat[21].parse::<u64>().unwrap_or(0),
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn read_path_contents(path: &PathBuf) -> std::io::Result<String> {
|
||||
Ok(std::fs::read_to_string(path)?)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn get_linux_process_state(proc_stats: &[&str]) -> (char, String) {
|
||||
fn get_linux_process_state(stat: &[&str]) -> (char, String) {
|
||||
// The -2 offset is because of us cutting off name + pid
|
||||
if let Some(first_char) = proc_stats[0].chars().collect::<Vec<char>>().first() {
|
||||
if let Some(first_char) = stat[0].chars().collect::<Vec<char>>().first() {
|
||||
(
|
||||
*first_char,
|
||||
ProcessStatus::from(*first_char).to_string().to_string(),
|
||||
|
@ -201,103 +212,98 @@ fn get_linux_process_state(proc_stats: &[&str]) -> (char, String) {
|
|||
/// Note that cpu_fraction should be represented WITHOUT the x100 factor!
|
||||
#[cfg(target_os = "linux")]
|
||||
fn get_linux_cpu_usage(
|
||||
proc_stats: &[&str], cpu_usage: f64, cpu_fraction: f64, before_proc_val: f64,
|
||||
proc_stats: &[&str], cpu_usage: f64, cpu_fraction: f64, prev_proc_val: &mut f64,
|
||||
use_current_cpu_total: bool,
|
||||
) -> std::io::Result<(f64, f64)> {
|
||||
fn get_process_cpu_stats(stats: &[&str]) -> f64 {
|
||||
// utime + stime (matches top), the -2 offset is because of us cutting off name + pid
|
||||
stats[11].parse::<f64>().unwrap_or(0_f64) + stats[12].parse::<f64>().unwrap_or(0_f64)
|
||||
) -> std::io::Result<f64> {
|
||||
fn get_process_cpu_stats(stat: &[&str]) -> f64 {
|
||||
// utime + stime (matches top), the -2 offset is because of us cutting off name + pid (normally 13, 14)
|
||||
stat[11].parse::<f64>().unwrap_or(0_f64) + stat[12].parse::<f64>().unwrap_or(0_f64)
|
||||
}
|
||||
|
||||
// Based heavily on https://stackoverflow.com/a/23376195 and https://stackoverflow.com/a/1424556
|
||||
let after_proc_val = get_process_cpu_stats(&proc_stats);
|
||||
let new_proc_val = get_process_cpu_stats(&proc_stats);
|
||||
|
||||
if cpu_usage == 0.0 {
|
||||
Ok((0_f64, after_proc_val))
|
||||
Ok(0_f64)
|
||||
} else if use_current_cpu_total {
|
||||
Ok((
|
||||
(after_proc_val - before_proc_val) / cpu_usage * 100_f64,
|
||||
after_proc_val,
|
||||
))
|
||||
let res = Ok((new_proc_val - *prev_proc_val) / cpu_usage * 100_f64);
|
||||
*prev_proc_val = new_proc_val;
|
||||
res
|
||||
} else {
|
||||
Ok((
|
||||
(after_proc_val - before_proc_val) / cpu_usage * 100_f64 * cpu_fraction,
|
||||
after_proc_val,
|
||||
))
|
||||
let res = Ok((new_proc_val - *prev_proc_val) / cpu_usage * 100_f64 * cpu_fraction);
|
||||
*prev_proc_val = new_proc_val;
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
#[cfg(target_os = "linux")]
|
||||
fn convert_ps<S: core::hash::BuildHasher>(
|
||||
process: &str, cpu_usage: f64, cpu_fraction: f64,
|
||||
prev_pid_stats: &mut HashMap<u32, PrevProcDetails, S>,
|
||||
new_pid_stats: &mut HashMap<u32, PrevProcDetails, S>, use_current_cpu_total: bool,
|
||||
time_difference_in_secs: u64, mem_total_kb: u64,
|
||||
) -> std::io::Result<ProcessHarvest> {
|
||||
let pid = (&process[..10])
|
||||
.trim()
|
||||
.to_string()
|
||||
.parse::<u32>()
|
||||
.unwrap_or(0);
|
||||
let name = (&process[11..111]).trim().to_string();
|
||||
let mem_usage_percent = (&process[112..116])
|
||||
.trim()
|
||||
.to_string()
|
||||
.parse::<f64>()
|
||||
.unwrap_or(0_f64);
|
||||
let path = (&process[117..]).trim().to_string();
|
||||
|
||||
let mut new_pid_stat = if let Some(prev_proc_stats) = prev_pid_stats.remove(&pid) {
|
||||
prev_proc_stats
|
||||
} else {
|
||||
PrevProcDetails::new(pid)
|
||||
};
|
||||
|
||||
let (cpu_usage_percent, process_state_char, process_state) =
|
||||
if let Ok(stat_results) = get_process_stats(&new_pid_stat.proc_stat_path) {
|
||||
if let Some(tmp_split) = stat_results.split(')').collect::<Vec<_>>().last() {
|
||||
let proc_stats = tmp_split.split_whitespace().collect::<Vec<&str>>();
|
||||
let (process_state_char, process_state) = get_linux_process_state(&proc_stats);
|
||||
|
||||
let (cpu_usage_percent, after_proc_val) = get_linux_cpu_usage(
|
||||
&proc_stats,
|
||||
cpu_usage,
|
||||
cpu_fraction,
|
||||
new_pid_stat.cpu_time,
|
||||
use_current_cpu_total,
|
||||
)?;
|
||||
new_pid_stat.cpu_time = after_proc_val;
|
||||
|
||||
(cpu_usage_percent, process_state_char, process_state)
|
||||
} else {
|
||||
(0.0, '?', String::new())
|
||||
}
|
||||
fn read_proc<S: core::hash::BuildHasher>(
|
||||
pid: u32, cpu_usage: f64, cpu_fraction: f64,
|
||||
pid_mapping: &mut HashMap<u32, PrevProcDetails, S>, use_current_cpu_total: bool,
|
||||
time_difference_in_secs: u64, mem_total_kb: u64, page_file_kb: u64,
|
||||
) -> error::Result<ProcessHarvest> {
|
||||
let pid_stat = pid_mapping
|
||||
.entry(pid)
|
||||
.or_insert_with(|| PrevProcDetails::new(pid));
|
||||
let stat_results = read_path_contents(&pid_stat.proc_stat_path)?;
|
||||
let name = stat_results
|
||||
.splitn(2, '(')
|
||||
.collect::<Vec<_>>()
|
||||
.last()
|
||||
.ok_or(BottomError::MinorError())?
|
||||
.rsplitn(2, ')')
|
||||
.collect::<Vec<_>>()
|
||||
.last()
|
||||
.ok_or(BottomError::MinorError())?
|
||||
.to_string();
|
||||
let command = {
|
||||
let cmd = read_path_contents(&pid_stat.proc_cmdline_path)?;
|
||||
if cmd.trim().is_empty() {
|
||||
format!("[{}]", name)
|
||||
} else {
|
||||
(0.0, '?', String::new())
|
||||
};
|
||||
cmd
|
||||
}
|
||||
};
|
||||
let stat = stat_results
|
||||
.split(')')
|
||||
.collect::<Vec<_>>()
|
||||
.last()
|
||||
.ok_or(BottomError::MinorError())?
|
||||
.split_whitespace()
|
||||
.collect::<Vec<&str>>();
|
||||
let (process_state_char, process_state) = get_linux_process_state(&stat);
|
||||
let cpu_usage_percent = get_linux_cpu_usage(
|
||||
&stat,
|
||||
cpu_usage,
|
||||
cpu_fraction,
|
||||
&mut pid_stat.cpu_time,
|
||||
use_current_cpu_total,
|
||||
)?;
|
||||
let (_vsize, rss) = get_linux_process_vsize_rss(&stat);
|
||||
let mem_usage_kb = rss * page_file_kb;
|
||||
let mem_usage_percent = mem_usage_kb as f64 * 100.0 / mem_total_kb as f64;
|
||||
|
||||
// This can fail if permission is denied!
|
||||
let (total_read_bytes, total_write_bytes, read_bytes_per_sec, write_bytes_per_sec) =
|
||||
if let Ok(io_results) = get_process_io(&new_pid_stat.proc_io_path) {
|
||||
if let Ok(io_results) = get_process_io(&pid_stat.proc_io_path) {
|
||||
let io_stats = io_results.split_whitespace().collect::<Vec<&str>>();
|
||||
|
||||
let (total_read_bytes, total_write_bytes) = get_linux_process_io_usage(&io_stats);
|
||||
let read_bytes_per_sec = if time_difference_in_secs == 0 {
|
||||
0
|
||||
} else {
|
||||
total_read_bytes.saturating_sub(new_pid_stat.total_read_bytes)
|
||||
/ time_difference_in_secs
|
||||
total_read_bytes.saturating_sub(pid_stat.total_read_bytes) / time_difference_in_secs
|
||||
};
|
||||
let write_bytes_per_sec = if time_difference_in_secs == 0 {
|
||||
0
|
||||
} else {
|
||||
total_write_bytes.saturating_sub(new_pid_stat.total_write_bytes)
|
||||
total_write_bytes.saturating_sub(pid_stat.total_write_bytes)
|
||||
/ time_difference_in_secs
|
||||
};
|
||||
|
||||
new_pid_stat.total_read_bytes = total_read_bytes;
|
||||
new_pid_stat.total_write_bytes = total_write_bytes;
|
||||
pid_stat.total_read_bytes = total_read_bytes;
|
||||
pid_stat.total_write_bytes = total_write_bytes;
|
||||
|
||||
(
|
||||
total_read_bytes,
|
||||
|
@ -309,15 +315,12 @@ fn convert_ps<S: core::hash::BuildHasher>(
|
|||
(0, 0, 0, 0)
|
||||
};
|
||||
|
||||
new_pid_stats.insert(pid, new_pid_stat);
|
||||
|
||||
// TODO: Is there a way to re-use these stats so I don't have to do so many syscalls?
|
||||
Ok(ProcessHarvest {
|
||||
pid,
|
||||
name,
|
||||
path,
|
||||
command,
|
||||
mem_usage_percent,
|
||||
mem_usage_kb: (mem_usage_percent * mem_total_kb as f64 / 100.0) as u64,
|
||||
mem_usage_kb,
|
||||
cpu_usage_percent,
|
||||
total_read_bytes,
|
||||
total_write_bytes,
|
||||
|
@ -331,45 +334,35 @@ fn convert_ps<S: core::hash::BuildHasher>(
|
|||
#[cfg(target_os = "linux")]
|
||||
pub fn linux_get_processes_list(
|
||||
prev_idle: &mut f64, prev_non_idle: &mut f64,
|
||||
prev_pid_stats: &mut HashMap<u32, PrevProcDetails, RandomState>, use_current_cpu_total: bool,
|
||||
time_difference_in_secs: u64, mem_total_kb: u64,
|
||||
pid_mapping: &mut HashMap<u32, PrevProcDetails, RandomState>, use_current_cpu_total: bool,
|
||||
time_difference_in_secs: u64, mem_total_kb: u64, page_file_kb: u64,
|
||||
) -> crate::utils::error::Result<Vec<ProcessHarvest>> {
|
||||
let ps_result = Command::new("ps")
|
||||
.args(&["-axo", "pid:10,comm:100,%mem:5,args:100", "--noheader"])
|
||||
.output()?;
|
||||
let ps_stdout = String::from_utf8_lossy(&ps_result.stdout);
|
||||
let split_string = ps_stdout.split('\n');
|
||||
if let Ok((cpu_usage, cpu_fraction)) = cpu_usage_calculation(prev_idle, prev_non_idle) {
|
||||
let process_list = split_string.collect::<Vec<&str>>();
|
||||
let mut new_pid_stats = HashMap::new();
|
||||
|
||||
let process_vector: Vec<ProcessHarvest> = process_list
|
||||
.iter()
|
||||
.filter_map(|process| {
|
||||
if process.trim().is_empty() {
|
||||
None
|
||||
} else if let Ok(process_object) = convert_ps(
|
||||
process,
|
||||
cpu_usage,
|
||||
cpu_fraction,
|
||||
prev_pid_stats,
|
||||
&mut new_pid_stats,
|
||||
use_current_cpu_total,
|
||||
time_difference_in_secs,
|
||||
mem_total_kb,
|
||||
) {
|
||||
if !process_object.name.is_empty() {
|
||||
Some(process_object)
|
||||
} else {
|
||||
None
|
||||
let process_vector: Vec<ProcessHarvest> = std::fs::read_dir("/proc")?
|
||||
.filter_map(|dir| {
|
||||
if let Ok(dir) = dir {
|
||||
let pid = dir.file_name().to_string_lossy().trim().parse::<u32>();
|
||||
if let Ok(pid) = pid {
|
||||
// I skip checking if the path is also a directory, it's not needed I think?
|
||||
if let Ok(process_object) = read_proc(
|
||||
pid,
|
||||
cpu_usage,
|
||||
cpu_fraction,
|
||||
pid_mapping,
|
||||
use_current_cpu_total,
|
||||
time_difference_in_secs,
|
||||
mem_total_kb,
|
||||
page_file_kb,
|
||||
) {
|
||||
return Some(process_object);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
||||
None
|
||||
})
|
||||
.collect();
|
||||
|
||||
*prev_pid_stats = new_pid_stats;
|
||||
Ok(process_vector)
|
||||
} else {
|
||||
Ok(Vec::new())
|
||||
|
@ -405,12 +398,12 @@ pub fn windows_macos_get_processes_list(
|
|||
} else {
|
||||
process_val.name().to_string()
|
||||
};
|
||||
let path = {
|
||||
let path = process_val.cmd().join(" ");
|
||||
if path.is_empty() {
|
||||
let command = {
|
||||
let command = process_val.cmd().join(" ");
|
||||
if command.is_empty() {
|
||||
name.to_string()
|
||||
} else {
|
||||
path
|
||||
command
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -430,7 +423,7 @@ pub fn windows_macos_get_processes_list(
|
|||
process_vector.push(ProcessHarvest {
|
||||
pid: process_val.pid() as u32,
|
||||
name,
|
||||
path,
|
||||
command,
|
||||
mem_usage_percent: if mem_total_kb > 0 {
|
||||
process_val.memory() as f64 * 100.0 / mem_total_kb as f64
|
||||
} else {
|
||||
|
|
|
@ -35,6 +35,7 @@ impl Process {
|
|||
/// Kills a process, given a PID.
|
||||
pub fn kill_process_given_pid(pid: u32) -> crate::utils::error::Result<()> {
|
||||
if cfg!(target_os = "linux") || cfg!(target_os = "macos") {
|
||||
// FIXME: Use libc instead of a command...
|
||||
let output = Command::new("kill").arg(pid.to_string()).output()?;
|
||||
if !(output.status).success() {
|
||||
return Err(BottomError::GenericError(
|
||||
|
|
|
@ -674,6 +674,7 @@ impl Prefix {
|
|||
process.cpu_percent_usage,
|
||||
numerical_query.value,
|
||||
),
|
||||
// FIXME: This doesn't work with mem values!
|
||||
PrefixType::Mem => matches_condition(
|
||||
&numerical_query.condition,
|
||||
process.mem_percent_usage,
|
||||
|
|
|
@ -398,7 +398,7 @@ pub fn convert_process_data(
|
|||
pid: process.pid,
|
||||
name: match name_type {
|
||||
ProcessNamingType::Name => process.name.to_string(),
|
||||
ProcessNamingType::Path => process.path.to_string(),
|
||||
ProcessNamingType::Path => process.command.to_string(),
|
||||
},
|
||||
cpu_percent_usage: process.cpu_usage_percent,
|
||||
mem_percent_usage: process.mem_usage_percent,
|
||||
|
@ -425,7 +425,7 @@ pub fn convert_process_data(
|
|||
let entry = grouped_hashmap
|
||||
.entry(match name_type {
|
||||
ProcessNamingType::Name => process.name.to_string(),
|
||||
ProcessNamingType::Path => process.path.to_string(),
|
||||
ProcessNamingType::Path => process.command.to_string(),
|
||||
})
|
||||
.or_insert(SingleProcessData {
|
||||
pid: process.pid,
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
#![warn(rust_2018_idioms)]
|
||||
#[allow(unused_imports)]
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
use std::{
|
||||
boxed::Box,
|
||||
io::{stdout, Write},
|
||||
|
|
|
@ -24,6 +24,8 @@ pub enum BottomError {
|
|||
ConversionError(String),
|
||||
/// An error to represent errors with querying.
|
||||
QueryError(Cow<'static, str>),
|
||||
/// An error that just signifies something minor went wrong; no message.
|
||||
MinorError(),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for BottomError {
|
||||
|
@ -50,6 +52,7 @@ impl std::fmt::Display for BottomError {
|
|||
write!(f, "unable to convert: {}", message)
|
||||
}
|
||||
BottomError::QueryError(ref message) => write!(f, "{}", message),
|
||||
BottomError::MinorError() => write!(f, "Minor error."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue