Improve stats (#10911)

* Add overview stats for overall detection and skipped fps

* Fix intel memory stats

* Fix iOS image long pressing

* Cleanup
This commit is contained in:
Nicolas Mowen
2024-04-09 17:08:11 -06:00
committed by GitHub
parent 15e4f5c771
commit 524732ec73
5 changed files with 156 additions and 35 deletions

View File

@@ -19,7 +19,7 @@ export default function CameraMetrics({
// stats
const { data: initialStats } = useSWR<FrigateStats[]>(
["stats/history", { keys: "cpu_usages,cameras,service" }],
["stats/history", { keys: "cpu_usages,cameras,detection_fps,service" }],
{
revalidateOnFocus: false,
},
@@ -57,6 +57,44 @@ export default function CameraMetrics({
// stats data
const overallFpsSeries = useMemo(() => {
if (!statsHistory) {
return [];
}
const series: {
[key: string]: { name: string; data: { x: number; y: number }[] };
} = {};
series["overall_dps"] = { name: "overall detections per second", data: [] };
series["overall_skipped_dps"] = {
name: "overall skipped detections per second",
data: [],
};
statsHistory.forEach((stats, statsIdx) => {
if (!stats) {
return;
}
series["overall_dps"].data.push({
x: statsIdx,
y: stats.detection_fps,
});
let skipped = 0;
Object.values(stats.cameras).forEach(
(camStat) => (skipped += camStat.skipped_fps),
);
series["overall_skipped_dps"].data.push({
x: statsIdx,
y: skipped,
});
});
return Object.values(series);
}, [statsHistory]);
const cameraCpuSeries = useMemo(() => {
if (!statsHistory || statsHistory.length == 0) {
return {};
@@ -147,19 +185,36 @@ export default function CameraMetrics({
}, [statsHistory]);
return (
<div className="size-full mt-4 flex flex-col overflow-y-auto">
<div className="size-full mt-4 flex flex-col gap-3 overflow-y-auto">
<div className="text-muted-foreground text-sm font-medium">Overview</div>
<div className="grid grid-cols-1 md:grid-cols-3">
{statsHistory.length != 0 ? (
<div className="p-2.5 bg-background_alt rounded-2xl">
<div className="mb-5">DPS</div>
<CameraLineGraph
graphId="overall-stats"
unit=" DPS"
dataLabels={["detect", "skipped"]}
updateTimes={updateTimes}
data={overallFpsSeries}
/>
</div>
) : (
<Skeleton className="w-full h-32" />
)}
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{config &&
Object.values(config.cameras).map((camera) => {
if (camera.enabled) {
return (
<div className="w-full flex flex-col">
<div className="mb-6 capitalize">
<div className="w-full flex flex-col gap-3">
<div className="capitalize text-muted-foreground text-sm font-medium">
{camera.name.replaceAll("_", " ")}
</div>
<div key={camera.name} className="grid sm:grid-cols-2 gap-2">
{Object.keys(cameraCpuSeries).includes(camera.name) ? (
<div className="p-2.5 bg-background_alt rounded-2xl flex-col">
<div className="p-2.5 bg-background_alt rounded-2xl">
<div className="mb-5">CPU</div>
<CameraLineGraph
graphId={`${camera.name}-cpu`}
@@ -175,7 +230,7 @@ export default function CameraMetrics({
<Skeleton className="size-full aspect-video" />
)}
{Object.keys(cameraFpsSeries).includes(camera.name) ? (
<div className="p-2.5 bg-background_alt rounded-2xl flex-col">
<div className="p-2.5 bg-background_alt rounded-2xl">
<div className="mb-5">DPS</div>
<CameraLineGraph
graphId={`${camera.name}-dps`}

View File

@@ -193,6 +193,14 @@ export default function GeneralMetrics({
return [];
}
if (
Object.keys(statsHistory?.at(0)?.gpu_usages ?? {}).length == 1 &&
Object.keys(statsHistory?.at(0)?.gpu_usages ?? {})[0].includes("intel")
) {
// intel gpu stats do not support memory
return undefined;
}
const series: {
[key: string]: { name: string; data: { x: number; y: string }[] };
} = {};
@@ -285,7 +293,7 @@ export default function GeneralMetrics({
</div>
<div className="w-full mt-4 grid grid-cols-1 sm:grid-cols-3 gap-2">
{statsHistory.length != 0 ? (
<div className="p-2.5 bg-background_alt rounded-2xl flex-col">
<div className="p-2.5 bg-background_alt rounded-2xl">
<div className="mb-5">Detector Inference Speed</div>
{detInferenceTimeSeries.map((series) => (
<ThresholdBarGraph
@@ -303,7 +311,7 @@ export default function GeneralMetrics({
<Skeleton className="w-full aspect-video" />
)}
{statsHistory.length != 0 ? (
<div className="p-2.5 bg-background_alt rounded-2xl flex-col">
<div className="p-2.5 bg-background_alt rounded-2xl">
<div className="mb-5">Detector CPU Usage</div>
{detCpuSeries.map((series) => (
<ThresholdBarGraph
@@ -321,7 +329,7 @@ export default function GeneralMetrics({
<Skeleton className="w-full aspect-video" />
)}
{statsHistory.length != 0 ? (
<div className="p-2.5 bg-background_alt rounded-2xl flex-col">
<div className="p-2.5 bg-background_alt rounded-2xl">
<div className="mb-5">Detector Memory Usage</div>
{detMemSeries.map((series) => (
<ThresholdBarGraph
@@ -358,7 +366,7 @@ export default function GeneralMetrics({
</div>
<div className=" mt-4 grid grid-cols-1 sm:grid-cols-2 gap-2">
{statsHistory.length != 0 ? (
<div className="p-2.5 bg-background_alt rounded-2xl flex-col">
<div className="p-2.5 bg-background_alt rounded-2xl">
<div className="mb-5">GPU Usage</div>
{gpuSeries.map((series) => (
<ThresholdBarGraph
@@ -376,20 +384,24 @@ export default function GeneralMetrics({
<Skeleton className="w-full aspect-video" />
)}
{statsHistory.length != 0 ? (
<div className="p-2.5 bg-background_alt rounded-2xl flex-col">
<div className="mb-5">GPU Memory</div>
{gpuMemSeries.map((series) => (
<ThresholdBarGraph
key={series.name}
graphId={`${series.name}-mem`}
unit=""
name={series.name}
threshold={GPUMemThreshold}
updateTimes={updateTimes}
data={[series]}
/>
))}
</div>
<>
{gpuMemSeries && (
<div className="p-2.5 bg-background_alt rounded-2xl">
<div className="mb-5">GPU Memory</div>
{gpuMemSeries.map((series) => (
<ThresholdBarGraph
key={series.name}
graphId={`${series.name}-mem`}
unit=""
name={series.name}
threshold={GPUMemThreshold}
updateTimes={updateTimes}
data={[series]}
/>
))}
</div>
)}
</>
) : (
<Skeleton className="w-full aspect-video" />
)}
@@ -402,7 +414,7 @@ export default function GeneralMetrics({
</div>
<div className="mt-4 grid grid-cols-1 sm:grid-cols-2 gap-2">
{statsHistory.length != 0 ? (
<div className="p-2.5 bg-background_alt rounded-2xl flex-col">
<div className="p-2.5 bg-background_alt rounded-2xl">
<div className="mb-5">Process CPU Usage</div>
{otherProcessCpuSeries.map((series) => (
<ThresholdBarGraph
@@ -420,7 +432,7 @@ export default function GeneralMetrics({
<Skeleton className="w-full aspect-tall" />
)}
{statsHistory.length != 0 ? (
<div className="p-2.5 bg-background_alt rounded-2xl flex-col">
<div className="p-2.5 bg-background_alt rounded-2xl">
<div className="mb-5">Process Memory Usage</div>
{otherProcessMemSeries.map((series) => (
<ThresholdBarGraph

View File

@@ -43,9 +43,7 @@ export default function StorageMetrics({
return (
<div className="size-full mt-4 flex flex-col overflow-y-auto">
<div className="text-muted-foreground text-sm font-medium">
General Storage
</div>
<div className="text-muted-foreground text-sm font-medium">Overview</div>
<div className="mt-4 grid grid-cols-1 sm:grid-cols-3 gap-2">
<div className="p-2.5 bg-background_alt rounded-2xl flex-col">
<div className="mb-5">Recordings</div>