use std::mem::{size_of, MaybeUninit};
use windows::{Win32::Foundation::*, Win32::System::ProcessStatus::*, Win32::System::Threading::*};
use super::Metrics;
pub fn collect() -> Metrics {
let mut metrics = Metrics::default();
unsafe {
let h = GetCurrentProcess();
let (start_time_seconds, cpu_seconds_total) = {
let mut creationtime = MaybeUninit::uninit();
let mut _exittime = MaybeUninit::uninit();
let mut kerneltime = MaybeUninit::uninit();
let mut usertime = MaybeUninit::uninit();
let ret = GetProcessTimes(
h,
creationtime.as_mut_ptr(),
_exittime.as_mut_ptr(),
kerneltime.as_mut_ptr(),
usertime.as_mut_ptr(),
);
if ret.is_ok() {
let start_time_seconds =
filetime_to_unix_epoch_in_seconds(creationtime.assume_init());
let cpu_seconds_total = {
let stime = filetime_to_seconds(kerneltime.assume_init());
let utime = filetime_to_seconds(usertime.assume_init());
stime + utime
};
(Some(start_time_seconds as u64), Some(cpu_seconds_total))
} else {
(None, None)
}
};
metrics.start_time_seconds = start_time_seconds;
metrics.cpu_seconds_total = cpu_seconds_total;
let (virtual_memory_bytes, resident_memory_bytes) = {
let memcounters = {
let m = &PROCESS_MEMORY_COUNTERS_EX::default();
m as *const _ as *mut PROCESS_MEMORY_COUNTERS
};
let cb = size_of::<PROCESS_MEMORY_COUNTERS_EX>();
let ret = GetProcessMemoryInfo(h, memcounters, cb as u32);
if ret.is_ok() {
let memcounters = memcounters as *const _ as *const PROCESS_MEMORY_COUNTERS_EX;
let &memcounters = &*memcounters;
(
Some(memcounters.PrivateUsage as u64),
Some(memcounters.WorkingSetSize as u64),
)
} else {
(None, None)
}
};
metrics.virtual_memory_bytes = virtual_memory_bytes;
metrics.resident_memory_bytes = resident_memory_bytes;
let open_fds = {
let mut handlecount = 0;
let ret = GetProcessHandleCount(h, &mut handlecount);
if ret.is_ok() {
Some(handlecount as u64)
} else {
None
}
};
metrics.open_fds = open_fds;
metrics.max_fds = Some(16 * 1024 * 1024); }
metrics
}
fn filetime_to_seconds(ft: FILETIME) -> f64 {
let low = ft.dwLowDateTime as u64;
let high = ft.dwHighDateTime as u64;
let nsec = high.checked_shl(32).unwrap_or(0) + low;
let nsec = nsec * 100;
nsec as f64 / 1e9
}
fn filetime_to_unix_epoch_in_seconds(ft: FILETIME) -> f64 {
let low = ft.dwLowDateTime as u64;
let high = ft.dwHighDateTime as u64;
let nsec = high.checked_shl(32).unwrap_or(0) + low;
let nsec = nsec - 116444736000000000;
let nsec = nsec * 100;
nsec as f64 / 1e9
}