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:
houseme
2026-07-08 23:51:34 +08:00
committed by GitHub
parent 6bdfdd164a
commit 6cb47049e8
7 changed files with 98 additions and 27 deletions
+4 -2
View File
@@ -93,11 +93,12 @@ use crate::metrics::stats_collector::{
collect_bucket_stats, collect_cluster_and_health_stats, collect_cluster_config_stats, collect_cluster_usage_metric_stats,
collect_compression_cluster_stats, collect_disk_and_system_drive_stats, collect_erasure_set_stats,
collect_host_network_stats, collect_iam_stats, collect_ilm_metric_stats, collect_internode_network_stats,
collect_process_metric_bundle, collect_replication_stats, collect_scanner_metric_stats,
collect_process_metric_bundle_with, collect_replication_stats, collect_scanner_metric_stats,
collect_system_cpu_and_memory_stats_with,
};
use futures_util::FutureExt;
use rustfs_audit::audit_target_metrics;
use rustfs_io_metrics::ProcessSampler;
use rustfs_notify::{notification_metrics_snapshot, notification_target_metrics};
use rustfs_utils::get_env_opt_u64;
use serde::Serialize;
@@ -1274,6 +1275,7 @@ pub fn init_metrics_runtime(token: CancellationToken) {
let labels = current_process_metric_labels();
let mut host_system = System::new_all();
let mut host_networks = Networks::new();
let mut process_sampler = ProcessSampler::new();
let process_interval = config.process_interval;
let mut interval = metrics_interval(process_interval, Duration::ZERO);
let now = Instant::now();
@@ -1311,7 +1313,7 @@ pub fn init_metrics_runtime(token: CancellationToken) {
_ = interval.tick() => {
run_metrics_collector_tick(health, MetricsCollectorTaskId::ProcessMetrics, "process_metrics", async {
let now = Instant::now();
let bundle = collect_process_metric_bundle();
let bundle = collect_process_metric_bundle_with(&mut process_sampler);
if now >= next_resource_run {
let mut metrics = collect_resource_metrics(&bundle.resource);
+17 -1
View File
@@ -37,7 +37,10 @@ use chrono::Utc;
use rustfs_common::heal_channel::HealScanMode;
use rustfs_common::metrics::{ScannerMetricsReport, global_metrics};
use rustfs_io_metrics::internode_metrics::global_internode_metrics;
use rustfs_io_metrics::{ProcessStatusSnapshot, snapshot_process_resource_and_system};
use rustfs_io_metrics::{
ProcessResourceSnapshot, ProcessSampler, ProcessStatusSnapshot, ProcessSystemSnapshot, snapshot_process_resource_and_system,
snapshot_process_resource_and_system_with,
};
use std::{collections::HashMap, sync::Arc, time::SystemTime};
use sysinfo::{Networks, System};
use tracing::{instrument, warn};
@@ -662,6 +665,19 @@ pub async fn collect_system_drive_stats() -> (Vec<DriveDetailedStats>, DriveCoun
#[inline]
pub fn collect_process_metric_bundle() -> ProcessMetricBundle {
let (resource_snapshot, process_snapshot) = snapshot_process_resource_and_system();
process_metric_bundle_from_snapshots(resource_snapshot, process_snapshot)
}
#[inline]
pub fn collect_process_metric_bundle_with(sampler: &mut ProcessSampler) -> ProcessMetricBundle {
let (resource_snapshot, process_snapshot) = snapshot_process_resource_and_system_with(sampler);
process_metric_bundle_from_snapshots(resource_snapshot, process_snapshot)
}
fn process_metric_bundle_from_snapshots(
resource_snapshot: ProcessResourceSnapshot,
process_snapshot: ProcessSystemSnapshot,
) -> ProcessMetricBundle {
let status = match process_snapshot.status {
ProcessStatusSnapshot::Running => ProcessStatusType::Running,
ProcessStatusSnapshot::Sleeping => ProcessStatusType::Sleeping,