mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-24 21:26:28 +00:00
fix(obs): isolate process sampler windows (#4492)
* fix(obs): isolate process sampler windows Refs rustfs/backlog#1004 Refs rustfs/backlog#986 - add a reusable ProcessSampler so callers can own independent sysinfo refresh windows - wire separate sampler instances for obs metrics scheduling and memory observability - keep compatibility helpers while avoiding cross-task CPU and disk delta interference Co-Authored-By: heihutu <heihutu@gmail.com> * fix(obs): import process sampler bundle helper Refs rustfs/backlog#1004 Refs rustfs/backlog#986 - import collect_process_metric_bundle_with in the metrics scheduler - drop the stale collect_process_metric_bundle import after switching scheduler sampling to independent process samplers Co-Authored-By: heihutu <heihutu@gmail.com> * fix(obs): move process sampler into blocking task Refs rustfs/backlog#1004 Refs rustfs/backlog#986 - move the memory observability process sampler into the spawn_blocking closure - satisfy the closure static lifetime required by tokio while keeping the isolated sampler design intact Co-Authored-By: heihutu <heihutu@gmail.com> --------- Co-authored-by: heihutu <heihutu@gmail.com>
This commit is contained in:
@@ -15,21 +15,43 @@
|
||||
use std::sync::{Mutex, OnceLock};
|
||||
use sysinfo::{Pid, ProcessRefreshKind, ProcessStatus, ProcessesToUpdate, System};
|
||||
|
||||
static PROCESS_SYSTEM: OnceLock<Mutex<System>> = OnceLock::new();
|
||||
static PROCESS_SAMPLER: OnceLock<Mutex<ProcessSampler>> = OnceLock::new();
|
||||
|
||||
#[inline]
|
||||
fn current_pid() -> Pid {
|
||||
Pid::from_u32(std::process::id())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn process_system() -> &'static Mutex<System> {
|
||||
PROCESS_SYSTEM.get_or_init(|| {
|
||||
#[derive(Debug)]
|
||||
pub struct ProcessSampler {
|
||||
pid: Pid,
|
||||
sys: System,
|
||||
}
|
||||
|
||||
impl Default for ProcessSampler {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl ProcessSampler {
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
let pid = current_pid();
|
||||
let mut system = System::new();
|
||||
system.refresh_processes_specifics(ProcessesToUpdate::Some(&[pid]), true, ProcessRefreshKind::everything());
|
||||
Mutex::new(system)
|
||||
})
|
||||
let mut sys = System::new();
|
||||
sys.refresh_processes_specifics(ProcessesToUpdate::Some(&[pid]), true, ProcessRefreshKind::everything());
|
||||
Self { pid, sys }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn snapshot_resource_and_system(&mut self) -> (ProcessResourceSnapshot, ProcessSystemSnapshot) {
|
||||
snapshot_process_resource_and_system_with(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn process_sampler() -> &'static Mutex<ProcessSampler> {
|
||||
PROCESS_SAMPLER.get_or_init(|| Mutex::new(ProcessSampler::new()))
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq)]
|
||||
@@ -99,13 +121,21 @@ pub fn snapshot_process_system() -> ProcessSystemSnapshot {
|
||||
/// Collect both resource and system snapshots in one sysinfo refresh.
|
||||
#[inline]
|
||||
pub fn snapshot_process_resource_and_system() -> (ProcessResourceSnapshot, ProcessSystemSnapshot) {
|
||||
let mut sampler = process_sampler().lock().unwrap_or_else(|poisoned| poisoned.into_inner());
|
||||
snapshot_process_resource_and_system_with(&mut sampler)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn snapshot_process_resource_and_system_with(
|
||||
sampler: &mut ProcessSampler,
|
||||
) -> (ProcessResourceSnapshot, ProcessSystemSnapshot) {
|
||||
let platform_stats = crate::snapshot_process_platform_stats();
|
||||
let lock_snapshot = crate::snapshot_process_lock_counts();
|
||||
let pid = current_pid();
|
||||
let mut sys = process_system().lock().unwrap_or_else(|poisoned| poisoned.into_inner());
|
||||
sys.refresh_processes_specifics(ProcessesToUpdate::Some(&[pid]), true, ProcessRefreshKind::everything());
|
||||
sampler
|
||||
.sys
|
||||
.refresh_processes_specifics(ProcessesToUpdate::Some(&[sampler.pid]), true, ProcessRefreshKind::everything());
|
||||
|
||||
if let Some(process) = sys.process(pid) {
|
||||
if let Some(process) = sampler.sys.process(sampler.pid) {
|
||||
let disk_usage = process.disk_usage();
|
||||
let status = ProcessStatusSnapshot::from(process.status());
|
||||
let uptime_seconds = process.run_time();
|
||||
@@ -163,4 +193,13 @@ mod tests {
|
||||
let _ = snapshot_process_system();
|
||||
let _ = snapshot_process_resource_and_system();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn independent_samplers_are_collectable() {
|
||||
let mut sampler_a = ProcessSampler::new();
|
||||
let mut sampler_b = ProcessSampler::new();
|
||||
|
||||
let _ = snapshot_process_resource_and_system_with(&mut sampler_a);
|
||||
let _ = snapshot_process_resource_and_system_with(&mut sampler_b);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user