mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-10-28 09:12:08 +08:00
* feat: migrate logs API from REST to IPC streaming - Replace REST API `/logs` calls with IPC streaming implementation - Add new `src-tauri/src/ipc/logs.rs` with `LogsMonitor` for real-time log streaming - Implement duplicate stream prevention with level tracking - Add frontend-backend communication via Tauri commands for log management - Remove WebSocket compatibility, maintain IPC-only mode - Fix duplicate monitoring task startup when toggling log service - Add proper task lifecycle management with JoinHandle cleanup * refactor: remove dead code from logs.rs to fix clippy warnings - Remove unused `timestamp` field from LogItem struct - Remove unused `client` field from LogsMonitor struct - Remove unused methods: `is_fresh`, `get_current_monitoring_level`, `get_current_logs` - Simplify LogsMonitor initialization by removing client dependency - All clippy warnings with -D warnings now resolved * refactor: extract duplicate fmt_bytes function to utils module - Create new utils/format.rs module with fmt_bytes function - Remove duplicate fmt_bytes implementations from traffic.rs and memory.rs - Update imports to use shared utils::format::fmt_bytes - Add comprehensive unit tests for fmt_bytes function - Ensure DRY principle compliance and code maintainability
126 lines
3.4 KiB
Rust
126 lines
3.4 KiB
Rust
use kode_bridge::IpcStreamClient;
|
|
use serde::{Deserialize, Serialize};
|
|
use std::{
|
|
sync::{Arc, OnceLock},
|
|
time::Instant,
|
|
};
|
|
use tokio::{sync::RwLock, time::Duration};
|
|
|
|
use crate::{
|
|
logging,
|
|
utils::{dirs::ipc_path, format::fmt_bytes, logging::Type},
|
|
};
|
|
|
|
#[derive(Debug, Clone, Deserialize, Serialize)]
|
|
pub struct MemoryData {
|
|
pub inuse: u64,
|
|
pub oslimit: u64,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct CurrentMemory {
|
|
pub inuse: u64,
|
|
pub oslimit: u64,
|
|
pub last_updated: Instant,
|
|
}
|
|
|
|
impl Default for CurrentMemory {
|
|
fn default() -> Self {
|
|
Self {
|
|
inuse: 0,
|
|
oslimit: 0,
|
|
last_updated: Instant::now(),
|
|
}
|
|
}
|
|
}
|
|
|
|
// Minimal memory monitor
|
|
pub struct MemoryMonitor {
|
|
current: Arc<RwLock<CurrentMemory>>,
|
|
}
|
|
|
|
static INSTANCE: OnceLock<MemoryMonitor> = OnceLock::new();
|
|
|
|
impl MemoryMonitor {
|
|
pub fn global() -> &'static MemoryMonitor {
|
|
INSTANCE.get_or_init(|| {
|
|
let ipc_path_buf = ipc_path().unwrap();
|
|
let ipc_path = ipc_path_buf.to_str().unwrap_or_default();
|
|
let client = IpcStreamClient::new(ipc_path).unwrap();
|
|
|
|
let instance = MemoryMonitor::new(client);
|
|
logging!(
|
|
info,
|
|
Type::Ipc,
|
|
true,
|
|
"MemoryMonitor initialized with IPC path: {}",
|
|
ipc_path
|
|
);
|
|
instance
|
|
})
|
|
}
|
|
|
|
fn new(client: IpcStreamClient) -> Self {
|
|
let current = Arc::new(RwLock::new(CurrentMemory::default()));
|
|
let monitor_current = current.clone();
|
|
|
|
tokio::spawn(async move {
|
|
loop {
|
|
let _ = client
|
|
.get("/memory")
|
|
.timeout(Duration::from_secs(10))
|
|
.process_lines(|line| {
|
|
if let Ok(memory) = serde_json::from_str::<MemoryData>(line.trim()) {
|
|
tokio::spawn({
|
|
let current = monitor_current.clone();
|
|
async move {
|
|
*current.write().await = CurrentMemory {
|
|
inuse: memory.inuse,
|
|
oslimit: memory.oslimit,
|
|
last_updated: Instant::now(),
|
|
};
|
|
}
|
|
});
|
|
}
|
|
Ok(())
|
|
})
|
|
.await;
|
|
tokio::time::sleep(Duration::from_secs(2)).await; // Memory updates less frequently
|
|
}
|
|
});
|
|
|
|
Self { current }
|
|
}
|
|
|
|
pub async fn current(&self) -> CurrentMemory {
|
|
self.current.read().await.clone()
|
|
}
|
|
|
|
pub async fn is_fresh(&self) -> bool {
|
|
self.current.read().await.last_updated.elapsed() < Duration::from_secs(10)
|
|
}
|
|
}
|
|
|
|
pub async fn get_current_memory() -> CurrentMemory {
|
|
MemoryMonitor::global().current().await
|
|
}
|
|
|
|
pub async fn get_formatted_memory() -> (String, String, f64, bool) {
|
|
let monitor = MemoryMonitor::global();
|
|
let memory = monitor.current().await;
|
|
let is_fresh = monitor.is_fresh().await;
|
|
|
|
let usage_percent = if memory.oslimit > 0 {
|
|
(memory.inuse as f64 / memory.oslimit as f64) * 100.0
|
|
} else {
|
|
0.0
|
|
};
|
|
|
|
(
|
|
fmt_bytes(memory.inuse),
|
|
fmt_bytes(memory.oslimit),
|
|
usage_percent,
|
|
is_fresh,
|
|
)
|
|
}
|