feat: Added active and total for network usage (dw,up) resources.

upd: Docs updated for network usage.
add: Widget resorce iconChildren param added.
upd: config file default options added.
upd: resources units type added.
This commit is contained in:
Ramazan Sancar 2024-11-25 06:25:52 +03:00 committed by GitHub
parent a06964dd17
commit 15d2eaec02
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 99 additions and 3 deletions

View File

@ -175,6 +175,7 @@ data:
expanded: true
cpu: true
memory: true
network: default
- search:
provider: duckduckgo
target: _blank
@ -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:

View File

@ -20,11 +20,12 @@ _Note: unfortunately, the package used for getting CPU temp ([systeminformation]
cpu: true
memory: true
disk: /disk/mount/path
network: default # options: 'default' or active network interface name
cputemp: true
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 widget, options: 'imperial' or 'metric'
refresh: 3000 # optional, in ms
diskUnits: bytes # optional, bytes (default) or bbytes. Only applies to disk
```

View File

@ -0,0 +1,62 @@
import useSWR from "swr";
import { FaNetworkWired, FaAngleUp, FaAngleDown } 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();
const { data, error } = useSWR(`/api/widgets/resources?type=network${(options.network || ( options.network !== 'default' && options.network === `false`)) ? `&interfaceName=${options.network}` : '' }`, {
refreshInterval: refresh,
});
if (error || data?.error) {
return <Error />;
}
if (!data) {
return (
<Resource
icon={FaNetworkWired}
value="-"
label={<FaAngleUp/>}
expandedValue="-"
expandedLabel={<FaAngleDown/>}
percentage="0"
expanded="true"
/>
);
}
return (
<>
/* Active Usage */
<Resource
icon={FaNetworkWired}
value={t('common.bits', { value: data?.network?.tx_sec })}
label={<FaAngleUp/>}
expandedValue={t('common.bits', { value: data?.network?.rx_sec })}
expandedLabel={<FaAngleDown/>}
percentage="0"
expanded="true"
children={<div className="pt-1 text-theme-800 dark:text-theme-200 text-xs text-center">{t('pyload.speed')}</div>}
iconChildren={<span class="bg-theme-100 text-theme-800 text-xs font-medium px-1 py-1 mt-1 rounded dark:bg-theme-700 dark:text-theme-300 text-center">{data.interface}</span>}
/>
/* Total Usage */
<Resource
icon={FaNetworkWired}
value={t('common.bbytes', { value: data?.network?.tx_bytes })}
label={<FaAngleUp/>}
expandedValue={t('common.bbytes', { value: data?.network?.rx_bytes })}
expandedLabel={<FaAngleDown/>}
percentage="0"
expanded="true"
children={<div className="pt-1 text-theme-800 dark:text-theme-200 text-xs text-center">{t('pyload.total')}</div>}
iconChildren={<span class="bg-theme-100 text-theme-800 text-xs font-medium px-1 py-1 mt-1 rounded dark:bg-theme-700 dark:text-theme-300 text-center">{data.interface}</span>}
/>
</>
);
}

View File

@ -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;
@ -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} />
)}

View File

@ -3,6 +3,7 @@ import UsageBar from "../resources/usage-bar";
export default function Resource({
children,
icon,
iconChildren,
value,
label,
expandedValue = "",
@ -17,7 +18,10 @@ export default function Resource({
<div
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 items-center">
<Icon className="text-theme-800 dark:text-theme-200 w-5 h-5 resource-icon" />
{iconChildren}
</div>
<div className={`flex flex-col ml-3 text-left min-w-[85px] ${expanded ? " expanded" : ""}`}>
<div className="text-theme-800 dark:text-theme-200 text-xs flex flex-row justify-between">
<div className="pl-0.5">{value}</div>

View File

@ -8,6 +8,7 @@ const si = require("systeminformation");
export default async function handler(req, res) {
const { type, target } = req.query;
let { interfaceName } = req.query;
if (type === "cpu") {
const load = await si.currentLoad();
@ -57,6 +58,31 @@ export default async function handler(req, res) {
});
}
if (type === "network"){
let networkData = await si.networkStats();
if(interfaceName !== "default" && interfaceName !== undefined && interfaceName !== "false"){
networkData = networkData.filter((network) => network.iface === interfaceName)['0'];
if(!networkData){
return res.status(404).json({
error: "Interface not found",
});
}
}else{
const interfaceDefault = await si.networkInterfaceDefault();
interfaceName = interfaceDefault
networkData = networkData.filter((network) => network.iface === interfaceDefault)['0'];
if(!networkData){
return res.status(404).json({
error: "Interface not found! Please specify a valid interface name.",
});
}
}
return res.status(200).json({
network: networkData,
interface: interfaceName
});
}
return res.status(400).json({
error: "invalid type",
});