Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop #22

Merged
merged 3 commits into from
Aug 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion FEATURES.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
Supported Features
* ✅ `/proc/<pid>`
* cmdline
* comm
* exe
* cwd
* environ
* exe
* io
* root

* ✅ `/proc/buddyinfo`
Expand Down
14 changes: 14 additions & 0 deletions examples/proc_io.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use procsys::proc;

fn main() {
let sys_proc = proc::collect(2).expect("system proc 2");
let sys_proc_io = sys_proc.io().expect("system proc 2 io");

match serde_json::to_string_pretty(&sys_proc_io) {
Ok(output) => println!("{}", output),
Err(err) => {
log::error!("{}", err);
std::process::exit(1);
}
}
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ pub mod meminfo;
pub mod net_dev;
pub mod net_protocols;
pub mod proc;
pub mod proc_io;
pub mod swaps;
pub mod sysfs;
pub mod utils;
46 changes: 46 additions & 0 deletions src/proc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ impl Proc {
self.id
}

pub fn path(&self) -> PathBuf {
self.path.clone()
}

/// returns the command name of a process
pub fn comm(&self) -> CollectResult<String> {
match utils::collect_info_string("comm", &self.path) {
Expand All @@ -51,6 +55,40 @@ impl Proc {
}
}

/// returns the command line of a process
pub fn cmdline(&self) -> CollectResult<Vec<String>> {
match utils::collect_info_string("cmdline", &self.path) {
Ok(c) => {
let proc_cmdline = c
.unwrap_or_default()
.trim_end_matches("\x00")
.split("\x00")
.map(|v| v.to_string())
.collect::<Vec<String>>();

Ok(proc_cmdline)
}
Err(err) => Err(err),
}
}

/// returns the process environments from `/proc/<pid>/environ`
pub fn environ(&self) -> CollectResult<Vec<String>> {
match utils::collect_info_string("environ", &self.path) {
Ok(c) => {
let proc_cmdline = c
.unwrap_or_default()
.trim_end_matches("\x00")
.split("\x00")
.map(|v| v.to_string())
.collect::<Vec<String>>();

Ok(proc_cmdline)
}
Err(err) => Err(err),
}
}

/// returns the absolute path of the executable command of a process
pub fn executable(&self) -> CollectResult<PathBuf> {
let mut proc_path = self.path.clone();
Expand Down Expand Up @@ -194,6 +232,14 @@ mod tests {
PathBuf::from("/usr/bin/vim"),
);
assert_eq!(sys_single_proc.root_dir().unwrap(), PathBuf::from("/"));
assert_eq!(
sys_single_proc.cmdline().unwrap(),
["vim", "test.go", "+10"],
);
assert_eq!(
sys_single_proc.environ().unwrap(),
["PATH=/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "HOSTNAME=cd24e11f73a5", "TERM=xterm", "GOLANG_VERSION=1.12.5", "GOPATH=/go", "HOME=/root"],
);

let sys_single_proc = collect_from(proc_path, 26232).expect("running proc 26232");
assert_eq!(sys_single_proc.cwd().is_err(), true);
Expand Down
113 changes: 113 additions & 0 deletions src/proc_io.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
use serde::Serialize;

use crate::{
error::{CollectResult, MetricError},
proc::Proc,
utils,
};

enum ProcIOType {
RChar,
WChar,
SyscR,
SyscW,
ReadBytes,
WriteBytes,
CancelledWriteBytes,
Unknown,
}

impl ProcIOType {
fn from(name: &str) -> ProcIOType {
match name {
"rchar" => ProcIOType::RChar,
"wchar" => ProcIOType::WChar,
"syscr" => ProcIOType::SyscR,
"syscw" => ProcIOType::SyscW,
"read_bytes" => ProcIOType::ReadBytes,
"write_bytes" => ProcIOType::WriteBytes,
"cancelled_write_bytes" => ProcIOType::CancelledWriteBytes,
_ => ProcIOType::Unknown,
}
}
}

/// ProcIO models the content of /proc/\<pid\>/io
#[derive(Debug, Serialize, Clone, Default)]
pub struct ProcIO {
pub rchar: u64,
pub wchar: u64,
pub syscr: u64,
pub syscw: u64,
pub read_bytes: u64,
pub write_bytes: u64,
pub cancelled_write_bytes: i64,
}

impl ProcIO {
fn new() -> Self {
Default::default()
}
}

impl Proc {
/// returns proc IO stats
pub fn io(&self) -> CollectResult<ProcIO> {
let mut proc_io = ProcIO::new();
let proc_io_path_str = format!("{:?}", self.path());
let proc_io_file = format!("{}/io", proc_io_path_str.replace("\"", ""));
for line in utils::read_file_lines(&proc_io_file)? {
let item_fields: Vec<&str> = line.trim().split(':').filter(|s| !s.is_empty()).collect();

if item_fields.len() != 2 {
return Err(MetricError::InvalidFieldNumberError(
"proc io".to_string(),
item_fields.len(),
line,
));
}

let item_value = item_fields[1].trim();
match ProcIOType::from(item_fields[0]) {
ProcIOType::RChar => proc_io.rchar = item_value.parse::<u64>().unwrap_or_default(),
ProcIOType::WChar => proc_io.wchar = item_value.parse::<u64>().unwrap_or_default(),
ProcIOType::SyscR => proc_io.syscr = item_value.parse::<u64>().unwrap_or_default(),
ProcIOType::SyscW => proc_io.syscw = item_value.parse::<u64>().unwrap_or_default(),
ProcIOType::ReadBytes => {
proc_io.read_bytes = item_value.parse::<u64>().unwrap_or_default()
}
ProcIOType::WriteBytes => {
proc_io.write_bytes = item_value.parse::<u64>().unwrap_or_default()
}
ProcIOType::CancelledWriteBytes => {
proc_io.cancelled_write_bytes = item_value.parse::<i64>().unwrap_or_default()
}
ProcIOType::Unknown => {}
}
}

Ok(proc_io)
}
}

#[cfg(test)]
mod tests {
use std::path::Path;

use crate::proc::*;

#[test]
fn proc_io() {
let proc_path = Path::new("test_data/fixtures/proc");
let sys_proc = collect_from(proc_path, 26231).expect("running proc 26231");
let sys_proc_io = sys_proc.io().expect("running proc 26231 io stat");

assert_eq!(sys_proc_io.rchar, 750339);
assert_eq!(sys_proc_io.wchar, 818609);
assert_eq!(sys_proc_io.syscr, 7405);
assert_eq!(sys_proc_io.syscw, 5245);
assert_eq!(sys_proc_io.read_bytes, 1024);
assert_eq!(sys_proc_io.write_bytes, 2048);
assert_eq!(sys_proc_io.cancelled_write_bytes, -1024);
}
}
Loading