Skip to content

Commit

Permalink
Enhancement: resources network widget (#4327)
Browse files Browse the repository at this point in the history
  • Loading branch information
shamoon committed Nov 25, 2024
1 parent a06964d commit 23097b7
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 4 deletions.
3 changes: 2 additions & 1 deletion docs/installation/k8s.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ data:
expanded: true
cpu: true
memory: true
network: default
- search:
provider: duckduckgo
target: _blank
Expand Down Expand Up @@ -370,7 +371,7 @@ prevent unnecessary re-renders on page loads and window / tab focusing. The
procedure for enabling sticky sessions depends on your Ingress controller. Below
is an example using Traefik as the Ingress controller.

```
```yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
Expand Down
3 changes: 2 additions & 1 deletion docs/widgets/info/resources.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ _Note: unfortunately, the package used for getting CPU temp ([systeminformation]
tempmin: 0 # optional, minimum cpu temp
tempmax: 100 # optional, maximum cpu temp
uptime: true
units: imperial # only used by cpu temp
units: imperial # only used by cpu temp, options: 'imperial' or 'metric'
refresh: 3000 # optional, in ms
diskUnits: bytes # optional, bytes (default) or bbytes. Only applies to disk
network: true # optional, uses 'default' if true or specify a network interface name
```
You can also pass a `label` option, which allows you to group resources under named sections,
Expand Down
47 changes: 47 additions & 0 deletions src/components/widgets/resources/network.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import useSWR from "swr";
import { FaNetworkWired } from "react-icons/fa";
import { useTranslation } from "next-i18next";

import Resource from "../widget/resource";
import Error from "../widget/error";

export default function Network({ options, refresh = 1500 }) {
const { t } = useTranslation();
// eslint-disable-next-line no-param-reassign
if (options.network === true) options.network = "default";

const { data, error } = useSWR(`/api/widgets/resources?type=network&interfaceName=${options.network}`, {
refreshInterval: refresh,
});

if (error || data?.error) {
return <Error />;
}

if (!data || !data.network) {
return (
<Resource
icon={FaNetworkWired}
value="- ↑"
label="- ↓"
expandedValue="- ↑"
expandedLabel="- ↓"
percentage="0"
wide
/>
);
}

return (
<Resource
icon={FaNetworkWired}
value={`${t("common.byterate", { value: data.network.tx_sec })} ↑`}
label={`${t("common.byterate", { value: data.network.rx_sec })} ↓`}
expandedValue={`${t("common.bytes", { value: data.network.tx_bytes })} ↑`}
expandedLabel={`${t("common.bytes", { value: data.network.rx_bytes })} ↓`}
expanded={options.expanded}
wide
percentage={(100 * data.network.rx_sec) / (data.network.rx_sec + data.network.tx_sec)}
/>
);
}
2 changes: 2 additions & 0 deletions src/components/widgets/resources/resources.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Cpu from "./cpu";
import Memory from "./memory";
import CpuTemp from "./cputemp";
import Uptime from "./uptime";
import Network from "./network";

export default function Resources({ options }) {
const { expanded, units, diskUnits, tempmin, tempmax } = options;
Expand All @@ -23,6 +24,7 @@ export default function Resources({ options }) {
<Disk key={disk} options={{ disk }} expanded={expanded} diskUnits={diskUnits} refresh={refresh} />
))
: options.disk && <Disk options={options} expanded={expanded} diskUnits={diskUnits} refresh={refresh} />}
{options.network && <Network options={options} refresh={refresh} />}
{options.cputemp && (
<CpuTemp expanded={expanded} units={units} refresh={refresh} tempmin={tempmin} tempmax={tempmax} />
)}
Expand Down
7 changes: 6 additions & 1 deletion src/components/widgets/widget/resource.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export default function Resource({
percentage,
expanded = false,
additionalClassNames = "",
wide = false,
}) {
const Icon = icon;

Expand All @@ -18,7 +19,11 @@ export default function Resource({
className={`flex-none flex flex-row items-center mr-3 py-1.5 information-widget-resource ${additionalClassNames}`}
>
<Icon className="text-theme-800 dark:text-theme-200 w-5 h-5 resource-icon" />
<div className={`flex flex-col ml-3 text-left min-w-[85px] ${expanded ? " expanded" : ""}`}>
<div
className={`flex flex-col ml-3 text-left ${expanded ? " expanded" : ""} ${
wide ? " min-w-[120px]" : "min-w-[85px]"
}`}
>
<div className="text-theme-800 dark:text-theme-200 text-xs flex flex-row justify-between">
<div className="pl-0.5">{value}</div>
<div className="pr-1">{label}</div>
Expand Down
28 changes: 27 additions & 1 deletion src/pages/api/widgets/resources.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const logger = createLogger("resources");
const si = require("systeminformation");

export default async function handler(req, res) {
const { type, target } = req.query;
const { type, target, interfaceName = "default" } = req.query;

if (type === "cpu") {
const load = await si.currentLoad();
Expand Down Expand Up @@ -57,6 +57,32 @@ export default async function handler(req, res) {
});
}

if (type === "network") {
let networkData = await si.networkStats();
let interfaceDefault;
logger.debug("networkData:", JSON.stringify(networkData));
if (interfaceName && interfaceName !== "default") {
networkData = networkData.filter((network) => network.iface === interfaceName)[0];
if (!networkData) {
return res.status(404).json({
error: "Interface not found",
});
}
} else {
interfaceDefault = await si.networkInterfaceDefault();
networkData = networkData.filter((network) => network.iface === interfaceDefault)[0];
if (!networkData) {
return res.status(404).json({
error: "Default interface not found",
});
}
}
return res.status(200).json({
network: networkData,
interface: interfaceName !== "default" ? interfaceName : interfaceDefault,
});
}

return res.status(400).json({
error: "invalid type",
});
Expand Down

0 comments on commit 23097b7

Please sign in to comment.