Show statusbar with cpu and gpu stats (#9968)

* Show statusbar with cpu and gpu stats

* fix gif logic
This commit is contained in:
Nicolas Mowen
2024-02-21 19:27:02 -07:00
committed by GitHub
parent 33c77d03c7
commit 6626b8d758
8 changed files with 170 additions and 6 deletions

View File

@@ -15,6 +15,8 @@ import NoMatch from "@/pages/NoMatch";
import Settings from "@/pages/Settings";
import UIPlayground from "./pages/UIPlayground";
import Events from "./pages/Events";
import { isDesktop } from "react-device-detect";
import Statusbar from "./components/Statusbar";
function App() {
const [sheetOpen, setSheetOpen] = useState(false);
@@ -30,9 +32,10 @@ function App() {
<Header onToggleNavbar={toggleNavbar} />
<div className="w-full h-full pt-2 overflow-hidden">
<Sidebar sheetOpen={sheetOpen} setSheetOpen={setSheetOpen} />
{isDesktop && <Statusbar />}
<div
id="pageRoot"
className="absolute left-0 md:left-16 top-16 md:top-2 right-0 bottom-0 overflow-hidden"
className="absolute left-0 md:left-16 top-16 md:top-2 right-0 bottom-0 md:bottom-8 overflow-hidden"
>
<Routes>
<Route path="/" element={<Live />} />

View File

@@ -11,6 +11,7 @@ import { produce, Draft } from "immer";
import useWebSocket, { ReadyState } from "react-use-websocket";
import { FrigateConfig } from "@/types/frigateConfig";
import { FrigateEvent, ToggleableSetting } from "@/types/ws";
import { FrigateStats } from "@/types/stats";
type ReducerState = {
[topic: string]: {
@@ -221,6 +222,13 @@ export function useFrigateEvents(): { payload: FrigateEvent } {
return { payload };
}
export function useFrigateStats(): { payload: FrigateStats } {
const {
value: { payload },
} = useWs("stats", "");
return { payload };
}
export function useMotionActivity(camera: string): { payload: string } {
const {
value: { payload },

View File

@@ -34,7 +34,7 @@ function Sidebar({
/>
))}
</div>
<SettingsNavItems className="hidden md:flex flex-col items-center" />
<SettingsNavItems className="hidden md:flex flex-col items-center mb-8" />
</aside>
);

View File

@@ -0,0 +1,84 @@
import { useFrigateStats } from "@/api/ws";
import { FrigateStats } from "@/types/stats";
import { useMemo } from "react";
import { MdCircle } from "react-icons/md";
import useSWR from "swr";
export default function Statusbar({}) {
const { data: initialStats } = useSWR<FrigateStats>("stats", {
revalidateOnFocus: false,
});
const { payload: latestStats } = useFrigateStats();
const stats = useMemo(() => {
if (latestStats) {
return latestStats;
}
return initialStats;
}, [initialStats, latestStats]);
const cpuPercent = useMemo(() => {
const systemCpu = stats?.cpu_usages["frigate.full_system"]?.cpu;
if (!systemCpu || systemCpu == "0.0") {
return null;
}
return parseInt(systemCpu);
}, [stats]);
return (
<div className="absolute left-0 bottom-0 right-0 w-full h-8 flex items-center px-4">
{cpuPercent && (
<div className="flex items-center text-sm mr-4">
<MdCircle
className={`w-2 h-2 mr-2 ${
cpuPercent < 50
? "text-green-500"
: cpuPercent < 80
? "text-orange-400"
: "text-danger"
}`}
/>
CPU {cpuPercent}%
</div>
)}
{Object.entries(stats?.gpu_usages || {}).map(([name, stats]) => {
if (name == "error-gpu") {
return;
}
let gpuTitle;
switch (name) {
case "amd-vaapi":
gpuTitle = "AMD GPU";
break;
case "intel-vaapi":
case "intel-qsv":
gpuTitle = "Intel GPU";
break;
default:
gpuTitle = name;
break;
}
const gpu = parseInt(stats.gpu);
return (
<div className="flex items-center text-sm">
<MdCircle
className={`w-2 h-2 mr-2 ${
gpu < 50
? "text-green-500"
: gpu < 80
? "text-orange-400"
: "text-danger"
}`}
/>
{gpuTitle} {gpu}%
</div>
);
})}
</div>
);
}

View File

@@ -79,7 +79,7 @@ function Live() {
}, []);
return (
<div className="w-full h-full overflow-scroll">
<div className="w-full h-full overflow-scroll px-2">
{events && events.length > 0 && (
<ScrollArea>
<TooltipProvider>

60
web/src/types/stats.ts Normal file
View File

@@ -0,0 +1,60 @@
export interface FrigateStats {
cameras: { [camera_name: string]: CameraStats };
cpu_usages: { [pid: string]: CpuStats };
detectors: { [detectorKey: string]: DetectorStats };
gpu_usages?: { [gpuKey: string]: GpuStats };
processes: { [processKey: string]: ExtraProcessStats };
service: ServiceStats;
detection_fps: number;
}
export type CameraStats = {
audio_dBFPS: number;
audio_rms: number;
camera_fps: number;
capture_pid: number;
detection_enabled: number;
detection_fps: number;
ffmpeg_pid: number;
pid: number;
process_fps: number;
skipped_fps: number;
};
export type CpuStats = {
cmdline: string;
cpu: string;
cpu_average: string;
mem: string;
};
export type DetectorStats = {
detection_start: number;
inference_speed: number;
pid: number;
};
export type ExtraProcessStats = {
pid: number;
};
export type GpuStats = {
gpu: string;
mem: string;
};
export type ServiceStats = {
last_updated: number;
storage: { [path: string]: StorageStats };
temperatures: { [apex: string]: number };
update: number;
latest_version: string;
version: string;
};
export type StorageStats = {
free: number;
total: number;
used: number;
mount_type: string;
};