Skip to main content

admin/
metrics.rs

1//! System metrics collection using pwrzv
2
3use crate::error::{AdminError, Result};
4use actrix_proto::{ServiceStatus, SystemMetrics};
5use std::sync::Arc;
6
7/// 收集系统指标
8///
9/// pwrzv 0.7 returns ratio-based metrics (0.0–1.0 for most dimensions).
10/// We map the available ratios into the proto `SystemMetrics` as percentages
11/// where possible; absolute byte counts are not available from pwrzv.
12pub async fn collect_system_metrics() -> Result<SystemMetrics> {
13    let (_, details) = pwrzv::get_power_reserve_level_with_details_direct()
14        .await
15        .map_err(|e| {
16            platform::recording::warn!("Failed to read system metrics: {}", e);
17            AdminError::Metrics(e.to_string())
18        })?;
19
20    let val = |key: &str| details.get(key).map(|d| d.value).unwrap_or(0.0);
21
22    Ok(SystemMetrics {
23        cpu_usage_percent: (val("cpu_usage") * 100.0) as f64,
24        memory_usage_percent: (val("memory_usage") * 100.0) as f64,
25        memory_used_bytes: 0, // pwrzv provides ratios only
26        memory_total_bytes: 0,
27        network_rx_bytes: 0,
28        network_tx_bytes: 0,
29        disk_used_bytes: 0,
30        disk_total_bytes: 0,
31        load_average_1m: val("cpu_load") as f64,
32        load_average_5m: None,
33        load_average_15m: None,
34    })
35}
36
37/// 服务状态提供者类型(用于 ReportRequest)
38pub type ServiceStatusProviderForReport = Arc<dyn Fn() -> Vec<ServiceStatus> + Send + Sync>;
39
40/// 收集服务状态
41///
42/// 如果提供了 `service_status_provider`,则使用它来获取服务状态;
43/// 否则返回空列表(向后兼容)。
44pub fn collect_service_status(
45    service_status_provider: Option<ServiceStatusProviderForReport>,
46) -> Vec<ServiceStatus> {
47    if let Some(provider) = service_status_provider {
48        provider()
49    } else {
50        // 向后兼容:如果没有提供 provider,返回空列表
51        Vec::new()
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use super::*;
58
59    #[tokio::test]
60    #[ignore] // 依赖系统环境,CI 可能失败
61    async fn test_collect_metrics() {
62        if let Ok(metrics) = collect_system_metrics().await {
63            assert!(metrics.memory_total_bytes > 0);
64            assert!(metrics.cpu_usage_percent >= 0.0);
65        }
66    }
67}