From b95508ecba6affaec06822cab5fad75b34048e9b Mon Sep 17 00:00:00 2001 From: SpikeHD Date: Sun, 24 Sep 2023 17:27:58 -0700 Subject: [PATCH] feat(all): networking --- backend/src/api.rs | 11 ++++ backend/src/resource_watcher.rs | 23 +++++++- frontend/src/components/QuickStats.css | 39 ++++++++++--- frontend/src/components/QuickStats.tsx | 63 ++++++++++++++------- frontend/src/components/icons/ArrowDown.tsx | 9 +++ frontend/src/components/icons/ArrowUp.tsx | 9 +++ frontend/src/components/icons/icon.css | 4 ++ frontend/src/index.tsx | 1 - frontend/src/pages/Home/index.tsx | 6 ++ frontend/types.d.ts | 6 ++ package.json | 4 +- 11 files changed, 143 insertions(+), 32 deletions(-) create mode 100644 frontend/src/components/icons/ArrowDown.tsx create mode 100644 frontend/src/components/icons/ArrowUp.tsx create mode 100644 frontend/src/components/icons/icon.css diff --git a/backend/src/api.rs b/backend/src/api.rs index ca72bcd..e3e62d2 100644 --- a/backend/src/api.rs +++ b/backend/src/api.rs @@ -38,6 +38,7 @@ pub fn register_routes(app: &mut tide::Server, settings: ApiSettings) { app.at("/api/swap").get(swap); app.at("/api/cpu").get(cpu); app.at("/api/disk").get(disk); + app.at("/api/network").get(network); app.at("/api/processes").get(processes); app.at("/api/sysinfo").get(sysinfo); } @@ -112,6 +113,16 @@ pub async fn disk(_req: tide::Request) -> Result) -> Result { + let watcher = unsafe { RESOURCE_WATCHER.as_ref().unwrap() }; + let mut res = tide::Response::new(200); + + res.set_body(serde_json::to_vec(&watcher.network).unwrap()); + res.set_content_type("application/json"); + + Ok(res) +} + pub async fn sysinfo(_req: tide::Request) -> Result { unsafe { if SYSTEM_INFO.is_none() { diff --git a/backend/src/resource_watcher.rs b/backend/src/resource_watcher.rs index 7b25ea1..a96fca6 100644 --- a/backend/src/resource_watcher.rs +++ b/backend/src/resource_watcher.rs @@ -1,6 +1,6 @@ use std::sync::{Arc, Mutex}; use serde::Serialize; -use sysinfo::{System, SystemExt, CpuExt, ProcessExt, PidExt, DiskExt}; +use sysinfo::{System, SystemExt, CpuExt, ProcessExt, PidExt, DiskExt, NetworkExt}; use crate::api::ApiSettings; @@ -34,6 +34,13 @@ pub struct Disk { used: u64, } +#[derive(Clone, Serialize)] +pub struct Network { + name: String, + recieve: u64, + transmit: u64, +} + #[derive(Clone)] pub struct ResourceWatcher { update_rate: u64, @@ -41,6 +48,7 @@ pub struct ResourceWatcher { pub swap_history: Arc>>, pub cpu_history: Arc>>, pub disks: Arc>>, + pub network: Arc>>, pub mem_history_max: usize, pub cpu_history_max: usize, pub process_list: Arc>>, @@ -55,6 +63,7 @@ impl ResourceWatcher { swap_history: Arc::new(Mutex::new(Vec::new())), cpu_history: Arc::new(Mutex::new(Vec::new())), disks: Arc::new(Mutex::new(Vec::new())), + network: Arc::new(Mutex::new(Vec::new())), mem_history_max: settings.mem_history_max as usize, cpu_history_max: settings.cpu_history_max as usize, process_list: Arc::new(Mutex::new(Vec::new())), @@ -80,6 +89,7 @@ impl ResourceWatcher { let mut swap_history = self.swap_history.as_ref().lock().unwrap(); let mut cpu_history = self.cpu_history.as_ref().lock().unwrap(); let mut disks = self.disks.as_ref().lock().unwrap(); + let mut network = self.network.as_ref().lock().unwrap(); let mut process_list = self.process_list.as_ref().lock().unwrap(); system.refresh_cpu(); @@ -143,6 +153,17 @@ impl ResourceWatcher { }); } + // Clear the old network list + network.clear(); + + for (name, data) in system.networks() { + network.push(Network { + name: name.to_string(), + recieve: data.received(), + transmit: data.transmitted(), + }); + } + // Clear the old process list process_list.clear(); diff --git a/frontend/src/components/QuickStats.css b/frontend/src/components/QuickStats.css index d4e9453..f9803dc 100644 --- a/frontend/src/components/QuickStats.css +++ b/frontend/src/components/QuickStats.css @@ -1,16 +1,39 @@ +.quick-stats-outer { + display: flex; + flex-direction: column; + justify-content: space-evenly; + align-items: center; + + width: 90%; + height: 120px; +} + .quick-stats { display: flex; flex-direction: row; - justify-content: space-around; + justify-content: space-evenly; align-items: center; - width: 80%; - height: 120px; + width: 100%; + height: 100%; - margin: 24px; + text-align: center; +} + +.quick-stats-header { + margin: 18px; +} + +.quick-stats-title { + width: 100%; + text-align: center; + + font-size: 24px; + font-weight: bold; +} - border: 1px solid var(--color-accent); - border-radius: 6px; +.stat-mini { + font-size: 12px; } .stat { @@ -23,11 +46,11 @@ } .stat-big { - font-size: 32px; + font-size: 28px; font-weight: bold; } .stat-small { - font-size: 16px; + font-size: 14px; font-weight: normal; } \ No newline at end of file diff --git a/frontend/src/components/QuickStats.tsx b/frontend/src/components/QuickStats.tsx index edefaab..e3eaa37 100644 --- a/frontend/src/components/QuickStats.tsx +++ b/frontend/src/components/QuickStats.tsx @@ -1,5 +1,7 @@ import { bytesToReadable } from '../util/byte' import './QuickStats.css' +import { ArrowDown } from './icons/ArrowDown' +import { ArrowUp } from './icons/ArrowUp' interface Props { sysinfo: SystemInfo; @@ -7,6 +9,7 @@ interface Props { swapData: Memory[]; cpuData: CPU[]; diskData: Disk[]; + networkData: Network[]; processList: Process[]; } @@ -15,35 +18,53 @@ export function QuickStats(props: Props) { const swapUse = props.swapData[props.swapData.length - 1]?.used const diskUse = props.diskData.map(d => d.used).reduce((a, b) => a + b) const diskTotal = props.diskData.map(d => d.total).reduce((a, b) => a + b) + const netRecieve = props.networkData.map(n => n.recieve).reduce((a, b) => a + b) + const netTransmit = props.networkData.map(n => n.transmit).reduce((a, b) => a + b) const cpuPct = props.cpuData[props.cpuData.length - 1]?.used return ( -
-
- {bytesToReadable(memoryUse)} - { - (memoryUse / props.sysinfo.mem_size * 100).toFixed(2) - }% of total memory ({bytesToReadable(props.sysinfo.mem_size)}) +
+
+ Quick Stats
-
- {bytesToReadable(swapUse)} - { - (swapUse / props.sysinfo.swap_size * 100).toFixed(2) - }% of total swap ({bytesToReadable(props.sysinfo.swap_size)}) -
+
+
+ {bytesToReadable(memoryUse)} + { + (memoryUse / props.sysinfo.mem_size * 100).toFixed(2) + }% of total memory ({bytesToReadable(props.sysinfo.mem_size)}) +
-
- {cpuPct.toFixed(2)}% - CPU usage -
+
+ {bytesToReadable(swapUse)} + { + (swapUse / props.sysinfo.swap_size * 100).toFixed(2) + }% of total swap ({bytesToReadable(props.sysinfo.swap_size)}) +
+ +
+ {cpuPct.toFixed(2)}% + + ({props.sysinfo.cpu_brand}) + +
-
- {bytesToReadable(diskUse)} - { - (diskUse / diskTotal * 100).toFixed(2) - }% of {props.diskData.length} disks +
+ + {bytesToReadable(netRecieve)} / {bytesToReadable(netTransmit)} + + Network RX / TX ({props.networkData.length} devices) +
+ +
+ {bytesToReadable(diskUse)} + { + (diskUse / diskTotal * 100).toFixed(2) + }% of {props.diskData.length} disks +
+ ) } \ No newline at end of file diff --git a/frontend/src/components/icons/ArrowDown.tsx b/frontend/src/components/icons/ArrowDown.tsx new file mode 100644 index 0000000..3cd7bfd --- /dev/null +++ b/frontend/src/components/icons/ArrowDown.tsx @@ -0,0 +1,9 @@ +import './icon.css' + +export function ArrowDown() { + return ( + + ) +} \ No newline at end of file diff --git a/frontend/src/components/icons/ArrowUp.tsx b/frontend/src/components/icons/ArrowUp.tsx new file mode 100644 index 0000000..b0fbed5 --- /dev/null +++ b/frontend/src/components/icons/ArrowUp.tsx @@ -0,0 +1,9 @@ +import './icon.css' + +export function ArrowUp() { + return ( + + ) +} \ No newline at end of file diff --git a/frontend/src/components/icons/icon.css b/frontend/src/components/icons/icon.css new file mode 100644 index 0000000..b2dca43 --- /dev/null +++ b/frontend/src/components/icons/icon.css @@ -0,0 +1,4 @@ +.icon { + display: inline-block; + height: 20px; +} \ No newline at end of file diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx index 731f47f..278c6f2 100644 --- a/frontend/src/index.tsx +++ b/frontend/src/index.tsx @@ -24,7 +24,6 @@ export function App() {
- ) } diff --git a/frontend/src/pages/Home/index.tsx b/frontend/src/pages/Home/index.tsx index 66f96f8..c10433a 100644 --- a/frontend/src/pages/Home/index.tsx +++ b/frontend/src/pages/Home/index.tsx @@ -9,6 +9,7 @@ export function Home() { const [swapData, setSwapData] = useState([] as Memory[]) const [cpuData, setCpuData] = useState([] as CPU[]) const [diskData, setDiskData] = useState([] as Disk[]) + const [networkData, setNetworkData] = useState([] as Network[]) const [processList, setProcessList] = useState([] as Process[]) useEffect(() => { @@ -29,6 +30,10 @@ export function Home() { const ddata = await dres.json() setDiskData(ddata) + const nres = await fetch('/api/network') + const ndata = await nres.json() + setNetworkData(ndata) + const pres = await fetch('/api/processes') const pdata = await pres.json() setProcessList(pdata) @@ -57,6 +62,7 @@ export function Home() { swapData={swapData} cpuData={cpuData} diskData={diskData} + networkData={networkData} processList={processList} /> diff --git a/frontend/types.d.ts b/frontend/types.d.ts index 3e5bfd3..8e72917 100644 --- a/frontend/types.d.ts +++ b/frontend/types.d.ts @@ -16,6 +16,12 @@ interface Disk { used: number, } +interface Network { + name: string, + recieve: number, + transmit: number, +} + interface Process { name: string; pid: number; diff --git a/package.json b/package.json index 4fee9db..d04fcd4 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,8 @@ "name": "procchi", "scripts": { "start": "cd ./frontend && bun run build && cd ../backend && cargo run -- -u test -k test", - "build": "cd ./frontend && bun run build && cd ../backend && cargo build --release" + "start:win": "cd ./frontend && pnpm run build && cd ../backend && cargo run -- -u test -k test", + "build": "cd ./frontend && bun run build && cd ../backend && cargo build --release", + "build:win": "cd ./frontend && pnpm run build && cd ../backend && cargo build --release" } } \ No newline at end of file