diff --git a/bin/core/src/monitor/record.rs b/bin/core/src/monitor/record.rs index 8c072977b..0c40f06ee 100644 --- a/bin/core/src/monitor/record.rs +++ b/bin/core/src/monitor/record.rs @@ -28,9 +28,6 @@ pub async fn record_server_stats(ts: i64) { disks: stats.disks.clone(), network_ingress_bytes: stats.network_ingress_bytes, network_egress_bytes: stats.network_egress_bytes, - network_usage_interface: stats - .network_usage_interface - .clone(), }) }) .collect::>(); diff --git a/bin/periphery/src/stats.rs b/bin/periphery/src/stats.rs index a472a5873..d473ba8e2 100644 --- a/bin/periphery/src/stats.rs +++ b/bin/periphery/src/stats.rs @@ -2,8 +2,7 @@ use std::{cmp::Ordering, sync::OnceLock}; use async_timing_util::wait_until_timelength; use komodo_client::entities::stats::{ - SingleDiskUsage, SingleNetworkInterfaceUsage, SystemInformation, - SystemProcess, SystemStats, + SingleDiskUsage, SystemInformation, SystemProcess, SystemStats, }; use sysinfo::{ProcessesToUpdate, System}; use tokio::sync::RwLock; @@ -84,40 +83,21 @@ impl StatsClient { let total_mem = self.system.total_memory(); let available_mem = self.system.available_memory(); - let mut total_ingress: u64 = 0; - let mut total_egress: u64 = 0; + let mut network_ingress_bytes: u64 = 0; + let mut network_egress_bytes: u64 = 0; - // Fetch network data (Ingress and Egress) - let network_usage: Vec = self - .networks - .iter() - .map(|(interface_name, network)| { - let ingress = network.received(); - let egress = network.transmitted(); - - // Update total ingress and egress - total_ingress += ingress; - total_egress += egress; - - // Return per-interface network stats - SingleNetworkInterfaceUsage { - name: interface_name.clone(), - ingress_bytes: ingress as f64, - egress_bytes: egress as f64, - } - }) - .collect(); + for (_, network) in self.networks.iter() { + network_ingress_bytes += network.received(); + network_egress_bytes += network.transmitted(); + } SystemStats { cpu_perc: self.system.global_cpu_usage(), mem_free_gb: self.system.free_memory() as f64 / BYTES_PER_GB, mem_used_gb: (total_mem - available_mem) as f64 / BYTES_PER_GB, mem_total_gb: total_mem as f64 / BYTES_PER_GB, - // Added total ingress and egress - network_ingress_bytes: total_ingress as f64, - network_egress_bytes: total_egress as f64, - network_usage_interface: network_usage, - + network_ingress_bytes: network_ingress_bytes as f64, + network_egress_bytes: network_egress_bytes as f64, disks: self.get_disks(), polling_rate: self.stats.polling_rate, refresh_ts: self.stats.refresh_ts, diff --git a/client/core/rs/src/entities/stats.rs b/client/core/rs/src/entities/stats.rs index 7d4d84edf..4b501b235 100644 --- a/client/core/rs/src/entities/stats.rs +++ b/client/core/rs/src/entities/stats.rs @@ -49,17 +49,17 @@ pub struct SystemStatsRecord { pub disk_used_gb: f64, /// Total disk size in GB pub disk_total_gb: f64, - /// Breakdown of individual disks, ie their usages, sizes, and mount points + /// Breakdown of individual disks, including their usage, total size, and mount point pub disks: Vec, - /// Network ingress usage in bytes + /// Total network ingress in bytes #[serde(default)] pub network_ingress_bytes: f64, - /// Network egress usage in bytes + /// Total network egress in bytes #[serde(default)] pub network_egress_bytes: f64, - /// Network usage by interface name (ingress, egress in bytes) - #[serde(default)] - pub network_usage_interface: Vec, // interface -> (ingress, egress) + // /// Network usage by interface name (ingress, egress in bytes) + // #[serde(default)] + // pub network_usage_interface: Vec, // interface -> (ingress, egress) } /// Realtime system stats data. @@ -86,9 +86,9 @@ pub struct SystemStats { /// Network egress usage in MB #[serde(default)] pub network_egress_bytes: f64, - /// Network usage by interface name (ingress, egress in bytes) - #[serde(default)] - pub network_usage_interface: Vec, // interface -> (ingress, egress) + // /// Network usage by interface name (ingress, egress in bytes) + // #[serde(default)] + // pub network_usage_interface: Vec, // interface -> (ingress, egress) // metadata /// The rate the system stats are being polled from the system pub polling_rate: Timelength, diff --git a/client/core/ts/src/types.ts b/client/core/ts/src/types.ts index 085b54b3b..9f7c535f9 100644 --- a/client/core/ts/src/types.ts +++ b/client/core/ts/src/types.ts @@ -1820,16 +1820,6 @@ export interface SingleDiskUsage { total_gb: number; } -/** Info for network interface usage. */ -export interface SingleNetworkInterfaceUsage { - /** The network interface name */ - name: string; - /** The ingress in bytes */ - ingress_bytes: number; - /** The egress in bytes */ - egress_bytes: number; -} - export enum Timelength { OneSecond = "1-sec", FiveSeconds = "5-sec", @@ -1875,8 +1865,6 @@ export interface SystemStats { network_ingress_bytes?: number; /** Network egress usage in MB */ network_egress_bytes?: number; - /** Network usage by interface name (ingress, egress in bytes) */ - network_usage_interface?: SingleNetworkInterfaceUsage[]; /** The rate the system stats are being polled from the system */ polling_rate: Timelength; /** Unix timestamp in milliseconds when stats were last polled */ @@ -5099,14 +5087,12 @@ export interface SystemStatsRecord { disk_used_gb: number; /** Total disk size in GB */ disk_total_gb: number; - /** Breakdown of individual disks, ie their usages, sizes, and mount points */ + /** Breakdown of individual disks, including their usage, total size, and mount point */ disks: SingleDiskUsage[]; - /** Network ingress usage in bytes */ + /** Total network ingress in bytes */ network_ingress_bytes?: number; - /** Network egress usage in bytes */ + /** Total network egress in bytes */ network_egress_bytes?: number; - /** Network usage by interface name (ingress, egress in bytes) */ - network_usage_interface?: SingleNetworkInterfaceUsage[]; } /** Response to [GetHistoricalServerStats]. */ @@ -6833,6 +6819,16 @@ export interface SetUsersInUserGroup { users: string[]; } +/** Info for network interface usage. */ +export interface SingleNetworkInterfaceUsage { + /** The network interface name */ + name: string; + /** The ingress in bytes */ + ingress_bytes: number; + /** The egress in bytes */ + egress_bytes: number; +} + /** Configuration for a Slack alerter. */ export interface SlackAlerterEndpoint { /** The Slack app webhook url */ diff --git a/frontend/public/client/types.d.ts b/frontend/public/client/types.d.ts index 57ba023fd..52b59ecd7 100644 --- a/frontend/public/client/types.d.ts +++ b/frontend/public/client/types.d.ts @@ -1910,15 +1910,6 @@ export interface SingleDiskUsage { /** Total size of the disk in GB */ total_gb: number; } -/** Info for network interface usage. */ -export interface SingleNetworkInterfaceUsage { - /** The network interface name */ - name: string; - /** The ingress in bytes */ - ingress_bytes: number; - /** The egress in bytes */ - egress_bytes: number; -} export declare enum Timelength { OneSecond = "1-sec", FiveSeconds = "5-sec", @@ -1963,8 +1954,6 @@ export interface SystemStats { network_ingress_bytes?: number; /** Network egress usage in MB */ network_egress_bytes?: number; - /** Network usage by interface name (ingress, egress in bytes) */ - network_usage_interface?: SingleNetworkInterfaceUsage[]; /** The rate the system stats are being polled from the system */ polling_rate: Timelength; /** Unix timestamp in milliseconds when stats were last polled */ @@ -4852,14 +4841,12 @@ export interface SystemStatsRecord { disk_used_gb: number; /** Total disk size in GB */ disk_total_gb: number; - /** Breakdown of individual disks, ie their usages, sizes, and mount points */ + /** Breakdown of individual disks, including their usage, total size, and mount point */ disks: SingleDiskUsage[]; - /** Network ingress usage in bytes */ + /** Total network ingress in bytes */ network_ingress_bytes?: number; - /** Network egress usage in bytes */ + /** Total network egress in bytes */ network_egress_bytes?: number; - /** Network usage by interface name (ingress, egress in bytes) */ - network_usage_interface?: SingleNetworkInterfaceUsage[]; } /** Response to [GetHistoricalServerStats]. */ export interface GetHistoricalServerStatsResponse { @@ -6411,6 +6398,15 @@ export interface SetUsersInUserGroup { /** The user ids or usernames to hard set as the group's users. */ users: string[]; } +/** Info for network interface usage. */ +export interface SingleNetworkInterfaceUsage { + /** The network interface name */ + name: string; + /** The ingress in bytes */ + ingress_bytes: number; + /** The egress in bytes */ + egress_bytes: number; +} /** Configuration for a Slack alerter. */ export interface SlackAlerterEndpoint { /** The Slack app webhook url */ diff --git a/frontend/src/components/resources/server/hooks.ts b/frontend/src/components/resources/server/hooks.ts index 008b09cad..aadd6e73e 100644 --- a/frontend/src/components/resources/server/hooks.ts +++ b/frontend/src/components/resources/server/hooks.ts @@ -8,10 +8,3 @@ const statsGranularityAtom = atomWithStorage( ); export const useStatsGranularity = () => useAtom(statsGranularityAtom); - -const selectedNetworkInterfaceAtom = atomWithStorage( - "selected-network-interface-v0", - undefined // Default value is `undefined` (Global view) -); - -export const useSelectedNetworkInterface = () => useAtom(selectedNetworkInterfaceAtom); diff --git a/frontend/src/components/resources/server/stat-chart.tsx b/frontend/src/components/resources/server/stat-chart.tsx index f87c3b018..30f77664c 100644 --- a/frontend/src/components/resources/server/stat-chart.tsx +++ b/frontend/src/components/resources/server/stat-chart.tsx @@ -2,14 +2,14 @@ import { hex_color_by_intention } from "@lib/color"; import { useRead } from "@lib/hooks"; import { Types } from "komodo_client"; import { useMemo } from "react"; -import { useStatsGranularity, useSelectedNetworkInterface } from "./hooks"; +import { useStatsGranularity } from "./hooks"; import { Loader2 } from "lucide-react"; import { AxisOptions, Chart } from "react-charts"; import { convertTsMsToLocalUnixTsInMs } from "@lib/utils"; import { useTheme } from "@ui/theme"; import { fmt_utc_date } from "@lib/formatting"; -type StatType = "cpu" | "mem" | "disk" | "network_ingress" | "network_egress" | "network_interface_ingress" | "network_interface_egress"; +type StatType = "cpu" | "mem" | "disk" | "network_ingress" | "network_egress"; type StatDatapoint = { date: number; value: number }; @@ -22,13 +22,11 @@ export const StatChart = ({ type: StatType; className?: string; }) => { - const [selectedInterface] = useSelectedNetworkInterface(); const [granularity] = useStatsGranularity(); const { data, isPending } = useRead("GetHistoricalServerStats", { server: server_id, granularity, - selectedInterface, }); const stats = useMemo( @@ -37,7 +35,7 @@ export const StatChart = ({ .map((stat) => { return { date: convertTsMsToLocalUnixTsInMs(stat.ts), - value: getStat(stat, type, selectedInterface), + value: getStat(stat, type), }; }) .reverse(), @@ -58,6 +56,10 @@ export const StatChart = ({ ); }; +const BYTES_PER_GB = 1073741824.0; +const BYTES_PER_MB = 1048576.0; +const BYTES_PER_KB = 1024.0; + export const InnerStatChart = ({ type, stats, @@ -72,12 +74,11 @@ export const InnerStatChart = ({ ? "dark" : "light" : _theme; - const BYTES_PER_GB = 1073741824.0; - const BYTES_PER_MB = 1048576.0; - const BYTES_PER_KB = 1024.0; + const min = stats?.[0]?.date ?? 0; const max = stats?.[stats.length - 1]?.date ?? 0; const diff = max - min; + const timeAxis = useMemo((): AxisOptions => { return { getValue: (datum) => new Date(datum.date), @@ -177,27 +178,14 @@ export const InnerStatChart = ({ }} /> ); - }; -const getStat = (stat: Types.SystemStatsRecord, type: StatType, selectedInterface?: string) => { +const getStat = (stat: Types.SystemStatsRecord, type: StatType) => { if (type === "cpu") return stat.cpu_perc || 0; if (type === "mem") return (100 * stat.mem_used_gb) / stat.mem_total_gb; if (type === "disk") return (100 * stat.disk_used_gb) / stat.disk_total_gb; if (type === "network_ingress") return stat.network_ingress_bytes || 0; if (type === "network_egress") return stat.network_egress_bytes || 0; - if (type === "network_interface_ingress") - return selectedInterface - ? stat.network_usage_interface?.find( - (networkInterface) => networkInterface.name === selectedInterface - )?.ingress_bytes || 0 - : stat.network_ingress_bytes || 0; - if (type === "network_interface_egress") - return selectedInterface - ? stat.network_usage_interface?.find( - (networkInterface) => networkInterface.name === selectedInterface - )?.egress_bytes || 0 - : stat.network_egress_bytes || 0; return 0; }; @@ -205,7 +193,7 @@ const getColor = (type: StatType) => { if (type === "cpu") return hex_color_by_intention("Good"); if (type === "mem") return hex_color_by_intention("Warning"); if (type === "disk") return hex_color_by_intention("Neutral"); - if (type === "network_interface_ingress") return hex_color_by_intention("Critical"); - if (type === "network_interface_egress") return hex_color_by_intention("Unknown"); + if (type === "network_ingress") return hex_color_by_intention("Good"); + if (type === "network_egress") return hex_color_by_intention("Critical"); return hex_color_by_intention("Unknown"); -}; \ No newline at end of file +}; diff --git a/frontend/src/components/resources/server/stats.tsx b/frontend/src/components/resources/server/stats.tsx index 76e296135..c326798cc 100644 --- a/frontend/src/components/resources/server/stats.tsx +++ b/frontend/src/components/resources/server/stats.tsx @@ -1,11 +1,5 @@ import { Section } from "@components/layouts"; -import { - Card, - CardContent, - CardDescription, - CardHeader, - CardTitle, -} from "@ui/card"; +import { Card, CardContent, CardHeader, CardTitle } from "@ui/card"; import { Progress } from "@ui/progress"; import { Cpu, Database, Loader2, MemoryStick } from "lucide-react"; import { useRead } from "@lib/hooks"; @@ -14,7 +8,7 @@ import { DataTable, SortableHeader } from "@ui/data-table"; import { ReactNode, useMemo, useState } from "react"; import { Input } from "@ui/input"; import { StatChart } from "./stat-chart"; -import { useStatsGranularity, useSelectedNetworkInterface } from "./hooks"; +import { useStatsGranularity } from "./hooks"; import { Select, SelectContent, @@ -32,7 +26,6 @@ export const ServerStats = ({ titleOther?: ReactNode; }) => { const [interval, setInterval] = useStatsGranularity(); - const [networkInterface, setNetworkInterface] = useSelectedNetworkInterface(); const stats = useRead( "GetSystemStats", @@ -75,6 +68,10 @@ export const ServerStats = ({ header: "Kernel", accessorKey: "kernel", }, + { + header: "CPU", + accessorKey: "cpu_brand", + }, { header: "Core Count", accessorFn: ({ core_count }) => @@ -93,11 +90,11 @@ export const ServerStats = ({
-
+
- +
@@ -136,39 +133,6 @@ export const ServerStats = ({ - - {/* Network Interface Dropdown */} -
-
Interface:
- -
} > @@ -355,44 +319,62 @@ const ProcessesInner = ({ ); }; -const CPU = ({ stats }: { stats: Types.SystemStats | undefined }) => { - const perc = stats?.cpu_perc; - +const StatBar = ({ + title, + icon, + percentage, +}: { + title: string; + icon: ReactNode; + percentage: number | undefined; +}) => { return ( - - CPU Usage + + {title}
- {perc?.toFixed(2)}% - +
{percentage?.toFixed(2)}%
+ {icon}
- +
); }; +const CPU = ({ stats }: { stats: Types.SystemStats | undefined }) => { + return ( + } + percentage={stats?.cpu_perc} + /> + ); +}; + const RAM = ({ stats }: { stats: Types.SystemStats | undefined }) => { const used = stats?.mem_used_gb; const total = stats?.mem_total_gb; - - const perc = ((used ?? 0) / (total ?? 0)) * 100; - return ( - - - RAM Usage -
- {perc.toFixed(2)}% - -
-
- - - -
+ } + percentage={((used ?? 0) / (total ?? 0)) * 100} + /> + ); +}; + +const DISK = ({ stats }: { stats: Types.SystemStats | undefined }) => { + const used = stats?.disks.reduce((acc, curr) => (acc += curr.used_gb), 0); + const total = stats?.disks.reduce((acc, curr) => (acc += curr.total_gb), 0); + return ( + } + percentage={((used ?? 0) / (total ?? 0)) * 100} + /> ); }; @@ -441,25 +423,3 @@ const NETWORK = ({ stats }: { stats: Types.SystemStats | undefined }) => { ); }; - -const DISK = ({ stats }: { stats: Types.SystemStats | undefined }) => { - const used = stats?.disks.reduce((acc, curr) => (acc += curr.used_gb), 0); - const total = stats?.disks.reduce((acc, curr) => (acc += curr.total_gb), 0); - - const perc = ((used ?? 0) / (total ?? 0)) * 100; - - return ( - - - Disk Usage -
- {perc?.toFixed(2)}% - -
-
- - - -
- ); -};