proc-status-0.1.1/.cargo_vcs_info.json0000644000000001120000000000000133100ustar { "git": { "sha1": "4706168f1d40d90b7996269ca3fec14ce8b2292d" } } proc-status-0.1.1/.gitignore000064400000000000000000000000230000000000000140470ustar 00000000000000/target Cargo.lock proc-status-0.1.1/Cargo.toml0000644000000015640000000000000113220ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] edition = "2018" name = "proc-status" version = "0.1.1" authors = ["dystroy "] description = "simple access to proc/status info on unix" readme = "README.md" keywords = ["proc", "memory", "process"] categories = [] license = "MIT" repository = "https://github.com/Canop/proc-status" [dependencies.thiserror] version = "1.0" proc-status-0.1.1/Cargo.toml.orig000064400000000000000000000005400000000000000147520ustar 00000000000000[package] name = "proc-status" version = "0.1.1" authors = ["dystroy "] repository = "https://github.com/Canop/proc-status" description = "simple access to proc/status info on unix" edition = "2018" keywords = ["proc", "memory", "process"] license = "MIT" categories = [] readme = "README.md" [dependencies] thiserror = "1.0" proc-status-0.1.1/README.md000064400000000000000000000027510000000000000133500ustar 00000000000000[![MIT][s2]][l2] [![Latest Version][s1]][l0] [![docs][s3]][l3] [![Chat on Miaou][s4]][l4] [s1]: https://img.shields.io/crates/v/proc-status.svg [l1]: https://crates.io/crates/proc-status [s2]: https://img.shields.io/badge/license-MIT-blue.svg [l2]: LICENSE [s3]: https://docs.rs/proc-status/badge.svg [l3]: https://docs.rs/proc-status/ [s4]: https://miaou.dystroy.org/static/shields/room.svg [l4]: https://miaou.dystroy.org/3 # proc-status basic process information The data comes from `/proc//process` and is only available on unix-like systems. This crate aims at keeping very simple. If it doesn't cover your needs, you should probably have a look at the much more complete [procfs](https://crates.io/crates/procfs). # Examples: ## Dump memory info about the current process: ``` let mem = proc_status::mem_usage().unwrap(); println!("Mem usage in bytes: current={}, peak={}", mem.current, mem.peak); ``` This prints something like ```stdout Mem usage in bytes: current=1232896, peak=141430784 ``` ## Print all the fields of the current process' status: ``` use proc_status::ProcStatus; let ps = ProcStatus::read().unwrap(); for entry in ps.entries() { let entry = entry.unwrap(); println!("{} = {:?}", entry.key, entry.value); } ``` ## Get the raw value of specific entries ``` use proc_status::ProcStatus; let ps = ProcStatus::read().unwrap(); println!("State: {:?}", ps.value("State").unwrap()); println!("VmPeak in bytes: {:?}", ps.value_KiB("VmPeak").unwrap() * 1024); ``` proc-status-0.1.1/src/entries.rs000064400000000000000000000014360000000000000146760ustar 00000000000000use { crate::*, std::{ str::Split, }, }; /// an iterator over the entries of a procstatus. /// /// You get it from the proc status instance. pub struct ProcEntries<'p> { split: Split<'p, char>, } impl<'p> ProcEntries<'p> { pub(crate) fn from_content(content: &'p str) -> Self { let split = content.split('\n'); Self { split } } } impl<'p> Iterator for ProcEntries<'p> { type Item = Result, ProcStatusError>; fn next(&mut self) -> Option, ProcStatusError>> { loop { match self.split.next() { None => { return None; } Some(s) => { if !s.is_empty() { return Some(ProcEntry::new(s)); } } } } } } proc-status-0.1.1/src/entry.rs000064400000000000000000000016020000000000000143610ustar 00000000000000use { crate::errors::ProcStatusError, }; /// a key:value line in the proc/status pseudo-file /// /// key and value fields can be read directly pub struct ProcEntry<'p> { pub key: &'p str, pub value: &'p str, } impl<'p> ProcEntry<'p> { pub(crate) fn new(src: &'p str) -> Result { src.find(':') .map(|i| Self { key: &src[..i], value: src[i+1..].trim(), }) .ok_or_else(|| ProcStatusError::NoColon(src.to_string())) } /// the parsed number before 'kB', meaning the number of KiB /// for a memory related value #[allow(non_snake_case)] pub fn in_KiB(&self) -> Result { if let Some(number) = self.value.strip_suffix(" kB") { Ok(number.parse()?) } else { Err(ProcStatusError::NotInKib) } } } proc-status-0.1.1/src/errors.rs000064400000000000000000000011260000000000000145350ustar 00000000000000 use { thiserror::Error, }; /// any error which can be raised in this crate /// /// If the OS isn't compatible (ie it doesn't have /// a /proc pseudo file system), you'll get a /// ProcStatusError::Io. #[derive(Error, Debug)] pub enum ProcStatusError { #[error("reading /proc file failed")] Io(#[from] std::io::Error), #[error("failed to parse as integer")] ParseInt(#[from] std::num::ParseIntError), #[error("no colon in line '{0}'")] NoColon(String), #[error("no entry with key '{0}'")] EntryNotFound(String), #[error("not a kib entry")] NotInKib, } proc-status-0.1.1/src/lib.rs000064400000000000000000000047650000000000000140030ustar 00000000000000//! //! basic process information //! //! The data comes from `/proc//process` and is only //! available on unix-like systems. //! //! This crate aims at keeping very simple. //! If it doesn't cover your needs, you should probably have a look //! at the much more complete [procfs](https://crates.io/crates/procfs). //! //! # Examples: //! //! ## Dump memory info about the current process: //! //! ``` //! let mem = proc_status::mem_usage().unwrap(); //! println!("Mem usage in bytes: current={}, peak={}", mem.current, mem.peak); //! ``` //! This prints something like //! //! ```stdout //! Mem usage in bytes: current=1232896, peak=141430784 //! ``` //! //! //! ## Print all the fields of the current process' status: //! //! ``` //! use proc_status::ProcStatus; //! //! let ps = ProcStatus::read().unwrap(); //! for entry in ps.entries() { //! let entry = entry.unwrap(); //! println!("{} = {:?}", entry.key, entry.value); //! } //! ``` //! //! ## Get the raw value of specific entries //! //! ``` //! use proc_status::ProcStatus; //! //! let ps = ProcStatus::read().unwrap(); //! println!("State: {:?}", ps.value("State").unwrap()); //! println!("VmPeak in bytes: {:?}", ps.value_KiB("VmPeak").unwrap() * 1024); //! ``` //! mod entry; mod entries; mod errors; mod mem_usage; mod proc_ref; mod status; pub use { entry::ProcEntry, entries::ProcEntries, errors::ProcStatusError, mem_usage::MemUsage, proc_ref::ProcRef, status::ProcStatus, }; /// load information about the current en peak memory /// usage of the current process pub fn mem_usage() -> Result { ProcStatus::read() .and_then(|ps| ps.mem_usage()) } /// get the value of an entry by name /// /// /// If you want to read several entries and you /// want them to be consistent, you should read /// the whole ProcStatus and call the `value` /// function on that instance. This would also /// be more efficient. pub fn value(key: &str) -> Result { ProcStatus::read() .and_then(|ps| ps.value(key).map(|v| v.to_string())) } /// get the value of an entry by name if it is /// a size in KiB. /// /// /// If you want to read several entries and you /// want them to be consistent, you should read /// the whole ProcStatus and call the `value_KiB` /// function on that instance. This would also /// be more efficient. #[allow(non_snake_case)] pub fn value_KiB(key: &str) -> Result { ProcStatus::read() .and_then(|ps| ps.value_KiB(key)) } proc-status-0.1.1/src/mem_usage.rs000064400000000000000000000011770000000000000151710ustar 00000000000000 /// information about the physical RAM usage of a process /// /// Note that the data, while given in bytes for simplicity, /// isn't that precise: /// - the numbers are truncated when written by the OS /// - the proc_info crate own mem usage isn't 0 #[derive(Debug, Clone, Copy)] pub struct MemUsage { /// estimation of the current physical memory used by the /// application, in bytes. /// /// Comes from proc//status/VmRSS pub current: usize, /// estimation of the peak physical memory used by the /// application, in bytes. /// /// Comes from proc//status/VmHWM pub peak: usize, } proc-status-0.1.1/src/proc_ref.rs000064400000000000000000000003050000000000000150160ustar 00000000000000 /// the reference to a process, either the symbolic "self" /// or a process id #[derive(Clone, Copy)] pub enum ProcRef { ProcSelf, // proc/self, it the current process ProcId(usize), } proc-status-0.1.1/src/status.rs000064400000000000000000000056730000000000000145570ustar 00000000000000use { crate::*, std::{ fs::File, io::Read, }, }; /// A snapshot of the status of a process /// /// It's stored in a string to ensure consistency /// and can be kept around and compared. pub struct ProcStatus { content: String, } impl ProcStatus { /// read the proc status info of the current process. /// /// It's the same than `ProcStatus::read(ProcRef::ProcSelf)` pub fn read() -> Result { Self::read_for(ProcRef::ProcSelf) } /// read the proc status info of a process. pub fn read_for(proc_ref: ProcRef) -> Result { let mut file = match proc_ref { ProcRef::ProcSelf => File::open("/proc/self/status"), ProcRef::ProcId(id) => File::open(format!("/proc/{}/status", id)), }?; let mut content = String::new(); file.read_to_string(&mut content)?; Ok(Self { content }) } /// return an iterator over all key:value entries pub fn entries(&self) -> ProcEntries<'_> { ProcEntries::from_content(&self.content) } /// find an entry by name pub fn entry(&self, key: &str) -> Result, ProcStatusError> { for entry in self.entries() { let entry = entry?; if entry.key == key { return Ok(entry); } } Err(ProcStatusError::EntryNotFound(key.to_string())) } /// return the value of an entry found by key /// /// Example: /// ``` /// println!( /// "current process name: {:?}", /// proc_status::ProcStatus::read().unwrap().value("Name").unwrap(), /// ); /// ``` /// Be careful that the values written as "xxx kB" are in /// KiB, not kB, and are written this way for compatibility. pub fn value(&self, key: &str) -> Result<&str, ProcStatusError> { self.entry(key).map(|e| e.value) } /// return the value of a memory related entry in KiB #[allow(non_snake_case)] pub fn value_KiB(&self, key: &str) -> Result { self.entry(key).and_then(|e| e.in_KiB()) } /// return the current and peak ram usage of the process pub fn mem_usage(&self) -> Result { self.value_KiB("VmRSS") .and_then(|current| { self.value_KiB("VmPeak") .map(|peak| MemUsage { current: current * 1024, // proc/status data are in KiB peak: peak * 1024, }) }) } } #[cfg(test)] mod tests { use super::*; #[test] fn test_read() { let ps = ProcStatus::read().unwrap(); let name = ps.value("Name").unwrap(); println!("name: {:?}", name); println!("VM peak: {:?}", ps.value("VmPeak").unwrap()); println!("VM peak KiB: {:?}", ps.entry("VmPeak").unwrap().in_KiB().unwrap()); mem_usage().unwrap(); } }