From ff31ee773fdd87bf22865ee1923a1d3594301e85 Mon Sep 17 00:00:00 2001 From: Owaise Date: Thu, 14 Aug 2025 19:35:12 +0530 Subject: [PATCH] Added a drop down so that we have choice to make about which network interface to choose. --- .../Components/Charts/Utils/chartUtils.jsx | 2 +- .../Components/NetworkStats/NetworkCharts.jsx | 29 ++++---- .../Details/Components/NetworkStats/index.jsx | 72 +++++++++++++++---- .../Details/Hooks/useHardwareUtils.jsx | 50 ++++++++++--- client/src/locales/en.json | 9 +++ 5 files changed, 124 insertions(+), 38 deletions(-) diff --git a/client/src/Components/Charts/Utils/chartUtils.jsx b/client/src/Components/Charts/Utils/chartUtils.jsx index ce15d27cd..e24881c1c 100644 --- a/client/src/Components/Charts/Utils/chartUtils.jsx +++ b/client/src/Components/Charts/Utils/chartUtils.jsx @@ -109,7 +109,7 @@ export const NetworkTick = ({ x, y, payload, index, formatter }) => { formatter = (value, space = false) => { if (typeof value !== "number") return value; // need to add space between value and unit - return `${(value / 1024).toFixed(2)}${space ? " " : ""}Kbps`; + return `${(value / 1024).toFixed(1)}${space ? " " : ""}Kbps`; }; } diff --git a/client/src/Pages/Infrastructure/Details/Components/NetworkStats/NetworkCharts.jsx b/client/src/Pages/Infrastructure/Details/Components/NetworkStats/NetworkCharts.jsx index 98eced859..9157a3432 100644 --- a/client/src/Pages/Infrastructure/Details/Components/NetworkStats/NetworkCharts.jsx +++ b/client/src/Pages/Infrastructure/Details/Components/NetworkStats/NetworkCharts.jsx @@ -15,7 +15,7 @@ const NetworkCharts = ({ ethernetData, dateRange }) => { const theme = useTheme(); const { t } = useTranslation(); - const { formatBytesString } = useHardwareUtils(); + const { formatBytesPerSecondString, formatPacketsPerSecondString } = useHardwareUtils(); if (!ethernetData?.length) { return {t("noNetworkStatsAvailable")}; @@ -26,19 +26,19 @@ const NetworkCharts = ({ ethernetData, dateRange }) => { type: "network-bytes", data: ethernetData, dataKeys: ["bytesPerSec"], - heading: t("bytesPerSecond"), + heading: t("dataReceived"), strokeColor: theme.palette.info.main, gradientStartColor: theme.palette.info.main, - yLabel: t("bytesPerSecond"), + yLabel: t("rate"), xTick: , - yTick: , + yTick: , toolTip: ( ), }, @@ -46,18 +46,19 @@ const NetworkCharts = ({ ethernetData, dateRange }) => { type: "network-packets", data: ethernetData, dataKeys: ["packetsPerSec"], - heading: t("packetsPerSecond"), + heading: t("packetsReceivedRate"), strokeColor: theme.palette.success.main, gradientStartColor: theme.palette.success.main, - yLabel: t("packetsPerSecond"), + yLabel: t("rate"), xTick: , + yTick: , toolTip: ( Math.round(value).toLocaleString()} + formatter={formatPacketsPerSecondString} /> ), }, @@ -65,7 +66,7 @@ const NetworkCharts = ({ ethernetData, dateRange }) => { type: "network-errors", data: ethernetData, dataKeys: ["errors"], - heading: t("errors"), + heading: t("networkErrors"), strokeColor: theme.palette.error.main, gradientStartColor: theme.palette.error.main, yLabel: t("errors"), @@ -74,7 +75,7 @@ const NetworkCharts = ({ ethernetData, dateRange }) => { Math.round(value).toLocaleString()} /> @@ -84,7 +85,7 @@ const NetworkCharts = ({ ethernetData, dateRange }) => { type: "network-drops", data: ethernetData, dataKeys: ["drops"], - heading: t("drops"), + heading: t("networkDrops"), strokeColor: theme.palette.warning.main, gradientStartColor: theme.palette.warning.main, yLabel: t("drops"), @@ -93,7 +94,7 @@ const NetworkCharts = ({ ethernetData, dateRange }) => { Math.round(value).toLocaleString()} /> diff --git a/client/src/Pages/Infrastructure/Details/Components/NetworkStats/index.jsx b/client/src/Pages/Infrastructure/Details/Components/NetworkStats/index.jsx index 623720aba..227523439 100644 --- a/client/src/Pages/Infrastructure/Details/Components/NetworkStats/index.jsx +++ b/client/src/Pages/Infrastructure/Details/Components/NetworkStats/index.jsx @@ -1,15 +1,21 @@ import PropTypes from "prop-types"; +import { useState, useEffect } from "react"; +import { FormControl, InputLabel, Select, MenuItem, Box } from "@mui/material"; +import { useTranslation } from "react-i18next"; +import { useTheme } from "@emotion/react"; import NetworkStatBoxes from "./NetworkStatBoxes"; import NetworkCharts from "./NetworkCharts"; import MonitorTimeFrameHeader from "../../../../../Components/MonitorTimeFrameHeader"; -const getInterfaceName = (net) => { - const interfaceNames = ["eth0", "Ethernet", "en0"]; - const found = (net || []).find((iface) => interfaceNames.includes(iface.name)); - return found ? found.name : null; +const getAvailableInterfaces = (net) => { + return (net || []).map((iface) => iface.name).filter(Boolean); }; const getNetworkInterfaceData = (checks, ifaceName) => { + if (!ifaceName) return []; + + // Transform backend data structure for the selected interface + // Backend already calculates deltas, we just reshape the data return (checks || []) .map((check) => { const networkInterface = (check.net || []).find( @@ -28,21 +34,63 @@ const getNetworkInterfaceData = (checks, ifaceName) => { }; const Network = ({ net, checks, isLoading, dateRange, setDateRange }) => { - const ifaceName = getInterfaceName(net); - const ethernetData = getNetworkInterfaceData(checks, ifaceName); + const { t } = useTranslation(); + const theme = useTheme(); + + const availableInterfaces = getAvailableInterfaces(net); + const [selectedInterface, setSelectedInterface] = useState(""); + + // Set default interface when data loads + useEffect(() => { + if (availableInterfaces.length > 0 && !selectedInterface) { + setSelectedInterface(availableInterfaces[0]); + } + }, [availableInterfaces, selectedInterface]); + + const ethernetData = getNetworkInterfaceData(checks, selectedInterface); return ( <> - + + {availableInterfaces.length > 0 && ( + + {t("networkInterface")} + + + )} + + { } }; - const formatBytesString = (bytes, space = false) => { + const formatBytesPerSecondString = (bytesPerSec, space = false) => { if ( - bytes === undefined || - bytes === null || - typeof bytes !== "number" || - bytes === 0 + bytesPerSec === undefined || + bytesPerSec === null || + typeof bytesPerSec !== "number" || + bytesPerSec === 0 ) { - return `0${space ? " " : ""}${t("gb")}`; + return `0${space ? " " : ""}B/s`; } - const GB = bytes / (1024 * 1024 * 1024); - const MB = bytes / (1024 * 1024); + const GB = bytesPerSec / (1024 * 1024 * 1024); + const MB = bytesPerSec / (1024 * 1024); + const KB = bytesPerSec / 1024; if (GB >= 1) { - return `${Number(GB.toFixed(2))}${space ? " " : ""}${t("gb")}`; + return `${Number(GB.toFixed(1))}${space ? " " : ""}GB/s`; + } else if (MB >= 1) { + return `${Number(MB.toFixed(1))}${space ? " " : ""}MB/s`; + } else if (KB >= 1) { + return `${Number(KB.toFixed(1))}${space ? " " : ""}KB/s`; } else { - return `${Number(MB.toFixed(2))}${space ? " " : ""}${t("mb")}`; + return `${Number(bytesPerSec.toFixed(1))}${space ? " " : ""}B/s`; + } + }; + + const formatPacketsPerSecondString = (packetsPerSec, space = false) => { + if ( + packetsPerSec === undefined || + packetsPerSec === null || + typeof packetsPerSec !== "number" || + packetsPerSec === 0 + ) { + return `0${space ? " " : ""}pps`; + } + + const M = packetsPerSec / (1000 * 1000); + const K = packetsPerSec / 1000; + + if (M >= 1) { + return `${Number(M.toFixed(1))}${space ? " " : ""}Mpps`; + } else if (K >= 1) { + return `${Number(K.toFixed(1))}${space ? " " : ""}Kpps`; + } else { + return `${Math.round(packetsPerSec)}${space ? " " : ""}pps`; } }; @@ -154,7 +181,8 @@ const useHardwareUtils = () => { decimalToPercentage, buildTemps, getDimensions, - formatBytesString, + formatBytesPerSecondString, + formatPacketsPerSecondString, }; }; diff --git a/client/src/locales/en.json b/client/src/locales/en.json index 08c60c372..857825c9f 100644 --- a/client/src/locales/en.json +++ b/client/src/locales/en.json @@ -205,6 +205,10 @@ "bytesPerSecond": "Bytes per second", "bytesReceived": "Bytes Received", "bytesSent": "Bytes Sent", + "dataReceived": "Data Received", + "dataSent": "Data Sent", + "dataRate": "Data Rate", + "rate": "Rate", "bulkImport": { "fallbackPage": "Import a file to upload a list of servers in bulk", "invalidFileType": "Invalid file type", @@ -341,6 +345,10 @@ "errors": "Errors", "errorsIn": "Errors In", "errorsOut": "Errors Out", + "networkErrors": "Network Errors", + "networkDrops": "Network Drops", + "networkInterface": "Network Interface", + "selectInterface": "Select Interface", "details": "Details", "displayName": "Display name", "distributedRightCategoryTitle": "Monitor", @@ -763,6 +771,7 @@ }, "packetsPerSecond": "Packets per second", "packetsReceived": "Packets Received", + "packetsReceivedRate": "Packets Received Rate", "packetsSent": "Packets Sent", "pause": "Pause", "pingMonitoring": "Ping monitoring",