Skip to content

Commit

Permalink
feat: Display the actual CPU usage instead of the system load
Browse files Browse the repository at this point in the history
  • Loading branch information
Hypfer committed Sep 2, 2024
1 parent b8afd4d commit d0f754b
Show file tree
Hide file tree
Showing 7 changed files with 148 additions and 54 deletions.
43 changes: 36 additions & 7 deletions backend/lib/utils/Tools.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const zooIDs = require("zoo-ids");

const env = require("../res/env");
const LinuxTools = require("./LinuxTools");
const {sleep} = require("./misc");

let SYSTEM_ID;

Expand Down Expand Up @@ -82,24 +83,52 @@ class Tools {
}
}

static GET_SYSTEM_STATS() {
const normalizedLoad = os.loadavg().map(v => {
return v / os.cpus().length;
});
static async GET_SYSTEM_STATS() {
const cpus = [];

const cpuInfoStart = os.cpus();
const normalizedLoad = os.loadavg().map(v => v / cpuInfoStart.length);

await sleep(100);

const cpuInfoEnd = os.cpus();

for (let i = 0; i < cpuInfoEnd.length; i++) {
const startCPU = cpuInfoStart[i];
const endCPU = cpuInfoEnd[i];

const cpuTime = {};
const cpuUsage = {};
let totalTime = 0;

Object.entries(endCPU.times).forEach(([type, value]) => {
cpuTime[type] = endCPU.times[type] - startCPU.times[type];

totalTime += cpuTime[type];
});

Object.entries(cpuTime).forEach(([type, value]) => {
cpuUsage[type] = parseFloat(((cpuTime[type] / totalTime) * 100).toFixed(2));
});

cpus.push({
usage: cpuUsage
});
}

return {
mem: {
total: os.totalmem(),
free: Tools.GET_FREE_SYSTEM_MEMORY(),
//@ts-ignore
valetudo_current: process.memoryUsage.rss(),
valetudo_max: process.resourceUsage()?.maxRSS * 1024
valetudo_max: process.resourceUsage().maxRSS * 1024
},
load: {
"1": normalizedLoad[0],
"5": normalizedLoad[1],
"15": normalizedLoad[2]
}
},
cpus: cpus
};
}

Expand Down
6 changes: 4 additions & 2 deletions backend/lib/webserver/SystemRouter.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ class SystemRouter {


initRoutes() {
this.router.get("/host/info", (req, res) => {
this.router.get("/host/info", async (req, res) => {
const systemStats = await Tools.GET_SYSTEM_STATS();

res.json({
hostname: os.hostname(),
arch: os.arch(),
uptime: Math.floor(os.uptime()),
...Tools.GET_SYSTEM_STATS(),
...systemStats,
});
});

Expand Down
28 changes: 28 additions & 0 deletions backend/lib/webserver/doc/SystemRouter.openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,34 @@
"description": "Normalized system load in the last 15 minutes"
}
}
},
"cpus": {
"type": "array",
"items": {
"type": "object",
"properties": {
"usage": {
"type": "object",
"properties": {
"user": {
"type": "number"
},
"nice": {
"type": "number"
},
"sys": {
"type": "number"
},
"idle": {
"type": "number"
},
"irq": {
"type": "number"
}
}
}
}
}
}
}
}
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/api/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -690,7 +690,10 @@ export const useValetudoVersionQuery = () => {
export const useSystemHostInfoQuery = () => {
return useQuery({
queryKey: [QueryKey.SystemHostInfo],
queryFn: fetchSystemHostInfo
queryFn: fetchSystemHostInfo,

staleTime: 5_000,
refetchInterval: 5_000
});
};

Expand Down
11 changes: 11 additions & 0 deletions frontend/src/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,14 @@ export interface ValetudoVersion {
commit: string;
}

export enum CPUUsageType {
USER = "user",
NICE = "nice",
SYS = "sys",
IDLE = "idle",
IRQ = "irq"
}

export interface SystemHostInfo {
hostname: string;
arch: string;
Expand All @@ -118,6 +126,9 @@ export interface SystemHostInfo {
5: number;
15: number;
};
cpus: Array<{
usage: Record<CPUUsageType, number>
}>
}

export interface SystemRuntimeInfo {
Expand Down
47 changes: 29 additions & 18 deletions frontend/src/components/RatioBar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {CSSProperties, FunctionComponent} from "react";
import React, {CSSProperties, FunctionComponent} from "react";
import styles from "./RatioBar.module.css";
import {darken, lighten, useTheme} from "@mui/material";

Expand All @@ -10,9 +10,12 @@ type RatioBarPartition = {
};

type RatioBarProps = {
style?: React.CSSProperties,
total: number;
totalLabel?: string;
partitions: Array<RatioBarPartition>;
hideLegend?: boolean;
noneLegendLabel?: string;
};

//Mostly adapted from the Material-UI LinearProgress bar https://github.com/mui-org/material-ui/blob/master/packages/material-ui/src/LinearProgress/LinearProgress.js
Expand Down Expand Up @@ -45,7 +48,8 @@ const RatioBar: FunctionComponent<RatioBarProps> = (props) => {
<span
className={styles.ratioBarBase}
style={{
backgroundColor: progressBackgroundColor
backgroundColor: progressBackgroundColor,
...props.style
}}
title={props.totalLabel}
>
Expand All @@ -64,22 +68,29 @@ const RatioBar: FunctionComponent<RatioBarProps> = (props) => {
);
})}
</span>
<span>
{mappedPartitions.reverse().map((mp, i) => {
return (
<span
key={"legend." + i}
style={{
paddingRight: "5px",
fontSize: "0.75rem",
color: theme.palette.text.secondary,
}}
>
<span style={{color: mp.color}}></span> {mp.label}
</span>
);
})}
</span>
{
props.hideLegend !== true &&
<span>
{
[
...mappedPartitions.reverse(),
props.noneLegendLabel ? { color: progressBackgroundColor, label: props.noneLegendLabel} : undefined
].filter(e => e !== undefined).map((mp, i) => {
return (
<span
key={"legend." + i}
style={{
paddingRight: "5px",
fontSize: "0.75rem",
color: theme.palette.text.secondary,
}}
>
<span style={{color: mp!.color}}></span> {mp!.label}
</span>
);
})}
</span>
}
</>
);
};
Expand Down
62 changes: 36 additions & 26 deletions frontend/src/valetudo/SystemInformation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,9 @@ import {
DialogTitle,
Divider,
Grid,
LinearProgress,
Paper,
Skeleton,
Stack,
styled,
Table,
TableBody,
TableCell,
Expand All @@ -29,7 +27,7 @@ import {
useSystemRuntimeInfoQuery,
useValetudoVersionQuery,
useRobotPropertiesQuery,
useValetudoInformationQuery,
useValetudoInformationQuery, CPUUsageType,
} from "../api";
import RatioBar from "../components/RatioBar";
import {convertSecondsToHumans} from "../utils";
Expand All @@ -38,12 +36,13 @@ import ReloadableCard from "../components/ReloadableCard";
import PaperContainer from "../components/PaperContainer";
import TextInformationGrid from "../components/TextInformationGrid";

const ThickLinearProgressWithTopMargin = styled(LinearProgress)({
marginTop: "2px",
height: "6px"
});


const cpuUsageTypeColors: Record<CPUUsageType, string> = {
[CPUUsageType.USER]: "#7AC037",
[CPUUsageType.NICE]: "#19A1A1",
[CPUUsageType.SYS]: "#DF5618",
[CPUUsageType.IRQ]: "#9966CC",
[CPUUsageType.IDLE]: "#000000", //not used
};

const SystemRuntimeInfo = (): React.ReactElement => {
const {
Expand Down Expand Up @@ -391,28 +390,39 @@ const SystemInformation = (): React.ReactElement => {
}
]
}
noneLegendLabel={"Free"}
/>
</Grid>

<Grid item xs={12}>
<Typography variant="caption" color="textSecondary">
System Load (1, 5, 15 Minutes)
CPU Usage
</Typography>

<ThickLinearProgressWithTopMargin
variant="determinate"
value={Math.min(100, systemHostInfo.load["1"] * 100)}
title={systemHostInfo.load["1"].toFixed(2)}
/>
<ThickLinearProgressWithTopMargin
variant="determinate"
value={Math.min(100, systemHostInfo.load["5"] * 100)}
title={systemHostInfo.load["5"].toFixed(2)}
/>
<ThickLinearProgressWithTopMargin
variant="determinate"
value={Math.min(100, systemHostInfo.load["15"] * 100)}
title={systemHostInfo.load["15"].toFixed(2)}
/>
{
systemHostInfo.cpus.map((cpu, i) => {
return (
<RatioBar
key={`cpu_${i}`}
style={{marginTop: "4px"}}
total={100}
partitions={
Object.entries(cpu.usage).filter(
([type, value]) => type !== CPUUsageType.IDLE
).map(([type, value]) => {
return {
label: type,
value: value,
valueLabel: `${value} %`,
color: cpuUsageTypeColors[type as CPUUsageType],
};
})
}
hideLegend={i !== systemHostInfo.cpus.length -1}
noneLegendLabel={"idle"}
/>
);
})
}
</Grid>
</Grid>

Expand Down

0 comments on commit d0f754b

Please sign in to comment.