diff --git a/docs/installation/k8s.md b/docs/installation/k8s.md
index 6805139b65c..24be2c341fc 100644
--- a/docs/installation/k8s.md
+++ b/docs/installation/k8s.md
@@ -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:
diff --git a/docs/widgets/info/resources.md b/docs/widgets/info/resources.md
index 19323dc30c9..7fcf9c5cdf3 100644
--- a/docs/widgets/info/resources.md
+++ b/docs/widgets/info/resources.md
@@ -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,
diff --git a/src/components/widgets/resources/network.jsx b/src/components/widgets/resources/network.jsx
new file mode 100644
index 00000000000..5b5cc004360
--- /dev/null
+++ b/src/components/widgets/resources/network.jsx
@@ -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 ;
+ }
+
+ if (!data || !data.network) {
+ return (
+
+ );
+ }
+
+ return (
+
+ );
+}
diff --git a/src/components/widgets/resources/resources.jsx b/src/components/widgets/resources/resources.jsx
index 634e0ff5330..db26caa78ee 100644
--- a/src/components/widgets/resources/resources.jsx
+++ b/src/components/widgets/resources/resources.jsx
@@ -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 }) {
))
: options.disk && }
+ {options.network && }
{options.cputemp && (
)}
diff --git a/src/components/widgets/widget/resource.jsx b/src/components/widgets/widget/resource.jsx
index 8c9759284f0..b1f737407b6 100644
--- a/src/components/widgets/widget/resource.jsx
+++ b/src/components/widgets/widget/resource.jsx
@@ -10,6 +10,7 @@ export default function Resource({
percentage,
expanded = false,
additionalClassNames = "",
+ wide = false,
}) {
const Icon = icon;
@@ -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}`}
>
-
+
{value}
{label}
diff --git a/src/pages/api/widgets/resources.js b/src/pages/api/widgets/resources.js
index 66449bff0c1..fa7cc7663bd 100644
--- a/src/pages/api/widgets/resources.js
+++ b/src/pages/api/widgets/resources.js
@@ -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();
@@ -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",
});