pub mod config;
pub mod core;
pub mod error;
pub mod monitor;
#[cfg(target_os = "linux")]
pub mod cpu_sampler;
#[cfg(target_os = "linux")]
pub mod perf;
pub mod psi;
#[cfg(feature = "ebpf")]
pub mod ebpf;
#[cfg(feature = "ebpf")]
pub mod symbolication;
#[cfg(feature = "gpu")]
pub mod gpu;
#[cfg(feature = "python")]
mod python;
pub use core::{ProcessMonitor, ProcessResult};
pub use monitor::*;
pub use config::{DenetConfig, MonitorConfig, OutputConfig, OutputFormat};
pub use error::{DenetError, Result};
#[cfg(feature = "python")]
mod python_bindings {
use super::python;
use pyo3::prelude::*;
#[pymodule]
pub fn _denet(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> {
python::register_python_module(m)
}
}
pub fn run_monitor(
cmd: Vec<String>,
base_interval_ms: u64,
max_interval_ms: u64,
since_process_start: bool,
) -> Result<()> {
let monitor = create_monitor(cmd, base_interval_ms, max_interval_ms, since_process_start)?;
execute_monitoring_loop(monitor, base_interval_ms)
}
fn create_monitor(
cmd: Vec<String>,
base_interval_ms: u64,
max_interval_ms: u64,
since_process_start: bool,
) -> Result<ProcessMonitor> {
use std::time::Duration;
ProcessMonitor::new_with_options(
cmd,
Duration::from_millis(base_interval_ms),
Duration::from_millis(max_interval_ms),
since_process_start,
)
.map_err(DenetError::Io)
}
fn execute_monitoring_loop(monitor: ProcessMonitor, interval_ms: u64) -> Result<()> {
use crate::core::constants::timeouts;
use crate::core::monitoring_utils::monitor_until_completion;
use std::time::Duration;
let timeout = if cfg!(test) {
Some(timeouts::SHORT)
} else {
None
};
let _result = monitor_until_completion(monitor, Duration::from_millis(interval_ms), timeout);
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_run_monitor_with_invalid_command() {
use crate::core::constants::sampling;
let result = run_monitor(
vec!["non_existent_command_12345".to_string()],
sampling::STANDARD.as_millis() as u64,
sampling::MAX_ADAPTIVE.as_millis() as u64,
false,
);
assert!(result.is_err());
}
#[test]
fn test_run_monitor_with_valid_command() {
use crate::core::constants::sampling;
#[cfg(target_family = "unix")]
{
let result = run_monitor(
vec!["true".to_string()],
sampling::STANDARD.as_millis() as u64,
sampling::MAX_ADAPTIVE.as_millis() as u64,
false,
);
assert!(result.is_ok());
}
#[cfg(target_family = "windows")]
{
let result = run_monitor(
vec!["cmd".to_string(), "/c".to_string(), "exit".to_string()],
sampling::STANDARD.as_millis() as u64,
sampling::MAX_ADAPTIVE.as_millis() as u64,
false,
);
assert!(result.is_ok());
}
}
#[test]
fn test_run_monitor_since_process_start() {
use crate::core::constants::sampling;
#[cfg(target_family = "unix")]
{
let result = run_monitor(
vec!["true".to_string()],
sampling::STANDARD.as_millis() as u64,
sampling::MAX_ADAPTIVE.as_millis() as u64,
true,
);
assert!(result.is_ok());
}
}
#[test]
fn test_create_monitor_success() {
use crate::core::constants::sampling;
#[cfg(target_family = "unix")]
{
let monitor = create_monitor(
vec!["true".to_string()],
sampling::STANDARD.as_millis() as u64,
sampling::MAX_ADAPTIVE.as_millis() as u64,
false,
);
assert!(monitor.is_ok());
}
}
#[test]
fn test_create_monitor_failure() {
use crate::core::constants::sampling;
let monitor = create_monitor(
vec!["non_existent_command_12345".to_string()],
sampling::STANDARD.as_millis() as u64,
sampling::MAX_ADAPTIVE.as_millis() as u64,
false,
);
assert!(monitor.is_err());
}
#[test]
fn test_execute_monitoring_loop() {
use crate::core::constants::{delays, sampling};
let monitor = ProcessMonitor::from_pid_with_options(
999999, delays::MINIMAL,
sampling::FAST,
false,
);
if let Ok(monitor) = monitor {
let result = execute_monitoring_loop(monitor, delays::MINIMAL.as_millis() as u64);
assert!(result.is_ok());
}
}
#[test]
fn test_re_exports() {
use crate::core::constants::sampling;
use crate::ProcessMonitor;
use crate::{DenetConfig, MonitorConfig, OutputConfig, OutputFormat};
use crate::{DenetError, Result};
let pid = std::process::id() as usize;
let monitor = ProcessMonitor::from_pid_with_options(
pid,
sampling::STANDARD,
sampling::MAX_ADAPTIVE,
false,
);
assert!(monitor.is_ok());
let _config = DenetConfig::default();
let _monitor_config = MonitorConfig::default();
let _output_config = OutputConfig::default();
let _format = OutputFormat::default();
let _error = DenetError::Other("test".to_string());
let _result: Result<()> = Ok(());
}
#[test]
fn test_different_intervals() {
use crate::core::constants::sampling;
let result = run_monitor(
vec![],
sampling::FAST.as_millis() as u64,
sampling::SLOW.as_millis() as u64,
false,
);
assert!(result.is_err());
let result = run_monitor(
vec![],
sampling::SLOW.as_millis() as u64,
(sampling::SLOW.as_millis() * 10) as u64,
true,
);
assert!(result.is_err()); }
#[cfg(feature = "python")]
#[test]
fn test_python_module_exists() {
use crate::python_bindings::_denet;
assert!(std::mem::size_of_val(&_denet) > 0);
}
}