Page MenuHomePhorge

No OneTemporary

Size
5 KB
Referenced Files
None
Subscribers
None
diff --git a/Cargo.toml b/Cargo.toml
index 43fc476..e5a5731 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,15 +1,15 @@
[package]
name = "pawd"
-version = "0.1.0"
+version = "0.1.1"
edition = "2021"
license = "MIT"
repository = "https://lab.themackabu.dev/crates/pawd"
description = "Process analysis & watcher daemon"
[dependencies]
+serde_json = "1.0.108"
psutil = { version = "3.2.2", features = ["serde"] }
-serde = "1.0.192"
-serde_derive = "1.0.192"
+serde = { version = "1.0.192", features = ["derive"] }
[dev-dependencies]
-assert_matches = "1.5.0"
\ No newline at end of file
+assert_matches = "1.5.0"
diff --git a/src/lib.rs b/src/lib.rs
index 08a4f2e..611890c 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,110 +1,118 @@
mod structs;
use psutil::process::{MemoryInfo, Process};
use std::io::{self, Read};
use std::process::{Command, Stdio};
use std::thread::{sleep, spawn};
use std::time::{Duration, Instant};
use structs::{PawDone, PawInfo, PawProcess, PawResult};
/// Represents a process watcher that monitors the resource usage of a child process.
#[derive(Debug, Clone)]
pub struct Paw {
command: String,
arguments: Vec<String>,
duration: Duration,
}
impl Paw {
/// Creates a new `Paw` instance with the specified command, arguments, and duration.
pub fn new<T: AsRef<str>>(command: &str, arguments: &[T], duration: u64) -> Paw {
Paw {
command: command.to_string(),
arguments: arguments.iter().map(|s| s.as_ref().to_string()).collect(),
duration: Duration::from_millis(duration),
}
}
/// Watches the process and calls the provided callback with the result at regular intervals.
///
/// # Arguments
///
/// * `callback` - A callback function that takes a `PawResult` as its parameter.
///
/// # Returns
///
/// Returns a `Result` containing a `PawDone` indicating the completion status.
pub fn watch<F: Fn(PawResult) + Send + 'static>(&self, callback: F) -> Result<PawDone, Box<dyn std::error::Error>> {
let mut child = Command::new(&self.command).args(&self.arguments).stdout(Stdio::piped()).spawn()?;
let done: PawDone;
let pid = child.id();
let start_time = Instant::now();
let stdout_handle = child.stdout.take().unwrap();
let stdout_thread = spawn(move || {
let mut buffer = String::new();
let mut reader = io::BufReader::new(stdout_handle);
reader.read_to_string(&mut buffer).unwrap();
buffer
});
loop {
let uptime = start_time.elapsed().as_millis();
let mut memory_usage: Option<MemoryInfo> = None;
let mut cpu_percent: Option<f32> = None;
if let Ok(mut process) = Process::new(pid) {
memory_usage = process.memory_info().ok();
cpu_percent = process.cpu_percent().ok();
}
let result = PawResult {
info: PawInfo { memory_usage, cpu_percent, uptime },
process: PawProcess {
cmd: self.command.clone(),
args: self.arguments.clone(),
},
};
callback(result);
sleep(self.duration);
if let Some(status) = child.try_wait()? {
done = PawDone {
stdout: stdout_thread.join().unwrap(),
code: status.code(),
};
break;
}
}
Ok(done)
}
}
+impl PawResult {
+ pub fn to_json(&self) -> String { serde_json::to_string(self).unwrap() }
+}
+
+impl PawDone {
+ pub fn to_json(&self) -> String { serde_json::to_string(self).unwrap() }
+}
+
#[cfg(test)]
mod tests {
use super::*;
use assert_matches::assert_matches;
#[test]
fn watch() {
let paw = Paw::new("node", &["tests/test.js"], 500);
let callback = move |result: PawResult| {
assert_matches!(
result,
PawResult {
info: PawInfo { .. },
process: PawProcess { .. }
}
);
};
match paw.watch(callback) {
Ok(result) => assert_matches!(result, PawDone { .. }),
Err(error) => panic!("{error}"),
}
}
}
diff --git a/src/structs.rs b/src/structs.rs
index 3a67bc7..d838b27 100644
--- a/src/structs.rs
+++ b/src/structs.rs
@@ -1,27 +1,27 @@
use psutil::process::MemoryInfo;
-use serde_derive::{Deserialize, Serialize};
+use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct PawResult {
pub info: PawInfo,
pub process: PawProcess,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct PawProcess {
pub cmd: String,
pub args: Vec<String>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct PawInfo {
pub uptime: u128,
pub memory_usage: Option<MemoryInfo>,
pub cpu_percent: Option<f32>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct PawDone {
pub stdout: String,
pub code: Option<i32>,
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Dec 16, 3:24 AM (5 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
484906
Default Alt Text
(5 KB)

Event Timeline