diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 0153904..224932e 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -1,13 +1,42 @@ #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] -use sysinfo::{CpuExt, SystemExt, ProcessExt, System, PidExt, ProcessStatus}; +use sysinfo::{ + System, + ProcessStatus, + NetworksExt, + NetworkExt, + DiskExt, + SystemExt, + CpuExt, + ProcessExt, + PidExt, +}; use tauri::State; use std::sync::Mutex; use std::collections::HashMap; +use std::time::{Instant}; struct AppState { sys: Mutex, process_cache: Mutex>, + last_network_update: Mutex<(Instant, u64, u64)>, +} + +impl AppState { + pub fn new() -> Self { + let mut sys = System::new(); + sys.refresh_all(); + + // Initialize network stats + let initial_rx = sys.networks().iter().map(|(_, data)| data.total_received()).sum(); + let initial_tx = sys.networks().iter().map(|(_, data)| data.total_transmitted()).sum(); + + Self { + sys: Mutex::new(sys), + process_cache: Mutex::new(HashMap::new()), + last_network_update: Mutex::new((Instant::now(), initial_rx, initial_tx)), + } + } } #[derive(Clone)] @@ -31,14 +60,19 @@ struct ProcessInfo { } #[derive(serde::Serialize)] -struct SystemStats { - cpu_usage: Vec, - memory_total: u64, - memory_used: u64, - memory_free:u64, - memory_cached: u64, - uptime: u64, - load_avg: [f64; 3], +pub struct SystemStats { + pub cpu_usage: Vec, + pub memory_total: u64, + pub memory_used: u64, + pub memory_free: u64, + pub memory_cached: u64, + pub uptime: u64, + pub load_avg: [f64; 3], + pub network_rx_bytes: u64, + pub network_tx_bytes: u64, + pub disk_total_bytes: u64, + pub disk_used_bytes: u64, + pub disk_free_bytes: u64, } #[tauri::command] @@ -50,7 +84,10 @@ async fn get_processes(state: State<'_, AppState>) -> Result<(Vec, { let mut sys = state.sys.lock().map_err(|_| "Failed to lock system state")?; sys.refresh_all(); - + sys.refresh_networks(); + sys.refresh_disks_list(); + sys.refresh_disks(); + // Collect all the process data we need while holding sys lock processes_data = sys .processes() @@ -69,22 +106,43 @@ async fn get_processes(state: State<'_, AppState>) -> Result<(Vec, }) .collect::>(); - // Get system stats while we still have the sys lock - let cpu_usage: Vec = sys.cpus().iter().map(|cpu| cpu.cpu_usage()).collect(); - let load_avg = sys.load_average(); - let memory_total = sys.total_memory(); - let memory_used = sys.used_memory(); - let memory_free = memory_total - memory_used; - let memory_cached = memory_total - (memory_used + memory_free); // Estimated + // Calculate total network I/O + let mut last_update = state.last_network_update.lock().map_err(|_| "Failed to lock network state")?; + let elapsed = last_update.0.elapsed().as_secs_f64(); + let current_time = Instant::now(); + + let current_rx: u64 = sys.networks().iter().map(|(_, data)| data.total_received()).sum(); + let current_tx: u64 = sys.networks().iter().map(|(_, data)| data.total_transmitted()).sum(); + + let network_stats = ( + ((current_rx - last_update.1) as f64 / elapsed) as u64, + ((current_tx - last_update.2) as f64 / elapsed) as u64, + ); + + *last_update = (current_time, current_rx, current_tx); + + // Calculate total disk usage + let disk_stats = sys.disks().iter().fold((0, 0, 0), |acc, disk| { + ( + acc.0 + disk.total_space(), + acc.1 + disk.total_space() - disk.available_space(), + acc.2 + disk.available_space() + ) + }); system_stats = SystemStats { - cpu_usage, - memory_total, - memory_used, - memory_free, - memory_cached, + cpu_usage: sys.cpus().iter().map(|cpu| cpu.cpu_usage()).collect(), + memory_total: sys.total_memory(), + memory_used: sys.used_memory(), + memory_free: sys.total_memory() - sys.used_memory(), + memory_cached: sys.total_memory() - (sys.used_memory() + (sys.total_memory() - sys.used_memory())), uptime: sys.uptime(), - load_avg: [load_avg.one, load_avg.five, load_avg.fifteen], + load_avg: [sys.load_average().one, sys.load_average().five, sys.load_average().fifteen], + network_rx_bytes: network_stats.0, + network_tx_bytes: network_stats.1, + disk_total_bytes: disk_stats.0, + disk_used_bytes: disk_stats.1, + disk_free_bytes: disk_stats.2, }; } // sys lock is automatically dropped here @@ -139,10 +197,7 @@ async fn kill_process(pid: u32, state: State<'_, AppState>) -> Result= 1024 && unitIndex < units.length - 1) { + value /= 1024; + unitIndex++; + } + + return `${value.toFixed(1)} ${units[unitIndex]}`; + } + + $: diskUsagePercentage = systemStats + ? (systemStats.disk_used_bytes / systemStats.disk_total_bytes) * 100 + : 0; -
+
{#if systemStats} -
-
-
-
- - CPU Usage -
+
+ +
+
+ +

CPU Usage

-
+
{#each systemStats.cpu_usage as usage, i} -
- CPU {i} -
+
+
+ Core {i} +
+
+
+ {Math.round(usage)}% +
+
+ {/each} +
+
+ + +
+
+ +

Memory

+
{formatPercentage(memoryPercentage)}
+
+
+
+
+ Memory usage +
- {usage.toFixed(1)}% + {formatPercentage(memoryPercentage)}
- {/each} +
+
+ Total + {formatMemorySize(systemStats.memory_total)} +
+
+ Used + {formatMemorySize(systemStats.memory_used)} +
+
+ Free + {formatMemorySize(systemStats.memory_free)} +
+
+ Cached + {formatMemorySize(systemStats.memory_cached)} +
-
-
-
- - Memory + +
+
+ +

Storage

+
+ {formatPercentage(diskUsagePercentage)}
-
-
-
+
+
+ Total + {formatBytes(systemStats.disk_total_bytes)}
-
-
- Total: - {formatMemorySize(systemStats.memory_total)} -
-
- Used: - {formatMemorySize(systemStats.memory_used)} ({formatPercentage( - memoryPercentage, - )}) -
-
- Free: - {formatMemorySize(systemStats.memory_free)} -
-
- Cached: - {formatMemorySize(systemStats.memory_cached)} -
+
+ Used + {formatBytes(systemStats.disk_used_bytes)} +
+
+ Free + {formatBytes(systemStats.disk_free_bytes)}
-
-
-
- - System Info -
+ +
+
+ +

System

-
-
- Uptime: +
+
+ Uptime {formatUptime(systemStats.uptime)}
-
- Load Average: - {systemStats.load_avg[0].toFixed(2)} (1m) +
+ 1m Load + {systemStats.load_avg[0].toFixed(2)}
-
- - {systemStats.load_avg[1].toFixed(2)} (5m) +
+ 5m Load + {systemStats.load_avg[1].toFixed(2)}
-
- - {systemStats.load_avg[2].toFixed(2)} (15m) +
+ 15m Load + {systemStats.load_avg[2].toFixed(2)} +
+
+
+ + +
+
+ +

Network I/O

+
+
+
+ ↓ Receiving + {formatBytes(systemStats.network_rx_bytes)}/s +
+
+ ↑ Sending + {formatBytes(systemStats.network_tx_bytes)}/s
@@ -116,143 +177,284 @@
diff --git a/src/lib/types/index.ts b/src/lib/types/index.ts index 4ceee22..6704350 100644 --- a/src/lib/types/index.ts +++ b/src/lib/types/index.ts @@ -19,6 +19,11 @@ export interface SystemStats { memory_cached: number; uptime: number; load_avg: [number, number, number]; + network_rx_bytes: number; + network_tx_bytes: number; + disk_total_bytes: number; + disk_used_bytes: number; + disk_free_bytes: number; } export interface Column {