Get system graphs working for inference time

This commit is contained in:
Nicolas Mowen 2024-03-29 14:57:33 -06:00
parent b9d8cc14de
commit 8295a0d11a
4 changed files with 151 additions and 54 deletions

View File

@ -14,6 +14,9 @@ from frigate.types import StatsTrackingTypes
logger = logging.getLogger(__name__)
MAX_STATS_POINTS = 120
class StatsEmitter(threading.Thread):
def __init__(
self,
@ -55,7 +58,7 @@ class StatsEmitter(threading.Thread):
self.config, self.stats_tracking, self.hwaccel_errors
)
self.stats_history.append(stats)
self.stats_history = self.stats_history[-10:]
self.stats_history = self.stats_history[-MAX_STATS_POINTS:]
self.requestor.send_data("stats", json.dumps(stats))
logger.debug("Finished stats collection")
logger.info("Exiting stats emitter...")

View File

@ -1,18 +1,36 @@
import { Threshold } from "@/types/graph";
import { useMemo } from "react";
import Chart from "react-apexcharts";
type SystemGraphProps = {
graphId: string;
title?: string;
name: string;
unit: string;
threshold: Threshold;
data: ApexAxisChartSeries;
};
export default function SystemGraph({
graphId,
title,
name,
unit,
threshold,
data,
}: SystemGraphProps) {
const lastValue = useMemo<number>(
// @ts-expect-error y is valid
() => data[0].data[data[0].data.length - 1]?.y ?? 0,
[data],
);
return (
<div className="w-full flex flex-col">
<div className="flex items-center gap-1">
<div className="text-xs text-muted-foreground">{name}</div>
<div className="text-xs text-primary-foreground">
{lastValue}
{unit}
</div>
</div>
<Chart
type="bar"
options={{
@ -28,27 +46,47 @@ export default function SystemGraph({
enabled: false,
},
},
legend: {
show: true,
showForSingleSeries: true,
position: "top",
horizontalAlign: "left",
onItemClick: {
toggleDataSeries: true,
colors: [
({ value }: { value: number }) => {
if (value >= threshold.error) {
return "#FA5252";
} else if (value >= threshold.warning) {
return "#aa00aa";
} else {
return "#404040";
}
},
],
grid: {
show: false,
},
legend: {
show: false,
},
dataLabels: {
enabled: false,
},
xaxis: {
type: "datetime",
axisBorder: {
show: false,
},
axisTicks: {
show: false,
},
labels: {
format: "h:mm",
datetimeUTC: false,
},
},
yaxis: {
show: false,
max: lastValue * 2,
},
}}
series={data}
height="120"
/>
</div>
);
}

View File

@ -1,4 +1,3 @@
import Heading from "@/components/ui/heading";
import useSWR from "swr";
import { FrigateStats } from "@/types/stats";
import { useEffect, useMemo, useState } from "react";
@ -6,11 +5,17 @@ import SystemGraph from "@/components/graph/SystemGraph";
import { useFrigateStats } from "@/api/ws";
import TimeAgo from "@/components/dynamic/TimeAgo";
import { FrigateConfig } from "@/types/frigateConfig";
import {
DetectorCpuThreshold,
DetectorMemThreshold,
InferenceThreshold,
} from "@/types/graph";
function System() {
const { data: config } = useSWR<FrigateConfig>("config");
// stats
const { data: initialStats } = useSWR<FrigateStats[]>("stats/history", {
revalidateOnFocus: false,
});
@ -42,9 +47,10 @@ function System() {
}
setStatsHistory([...statsHistory, updatedStats]);
}, [initialStats, updatedStats, statsHistory]);
}, [initialStats, updatedStats]);
// stats data pieces
const detInferenceTimeSeries = useMemo(() => {
if (!statsHistory) {
return [];
@ -200,6 +206,10 @@ function System() {
const statTime = new Date(stats.service.last_updated * 1000);
Object.entries(stats.cameras).forEach(([key, camStats]) => {
if (!config?.cameras[key].enabled) {
return;
}
if (!(key in series)) {
const camName = key.replaceAll("_", " ");
series[key] = {};
@ -210,11 +220,11 @@ function System() {
series[key]["ffmpeg"].data.push({
x: statTime,
y: stats.cpu_usages[camStats.ffmpeg_pid.toString()].cpu,
y: stats.cpu_usages[camStats.ffmpeg_pid.toString()]?.cpu ?? 0.0,
});
series[key]["capture"].data.push({
x: statTime,
y: stats.cpu_usages[camStats.capture_pid.toString()].cpu,
y: stats.cpu_usages[camStats.capture_pid?.toString()]?.cpu ?? 0,
});
series[key]["detect"].data.push({
x: statTime,
@ -348,32 +358,45 @@ function System() {
</div>
</div>
<div className="grid grid-cols-1 sm:grid-cols-3 gap-2">
<div className="mt-4 grid grid-cols-1 sm:grid-cols-3 gap-2">
<div className="p-2.5 bg-primary rounded-2xl flex-col">
<div>Inference Speed</div>
<div className="mb-5">Detector Inference Speed</div>
{detInferenceTimeSeries.map((series) => (
<SystemGraph
key={series.name}
graphId="detector-inference"
name={series.name}
unit="ms"
threshold={InferenceThreshold}
data={[series]}
/>
))}
</div>
<div className="bg-primary rounded-2xl flex-col">
<div className="p-2.5 bg-primary rounded-2xl flex-col">
<div className="mb-5">Detector CPU Usage</div>
{detCpuSeries.map((series) => (
<SystemGraph
graphId="detector-usages"
title="CPU"
key={series.name}
graphId="detector-cpu-usages"
unit="%"
data={detCpuSeries}
name={series.name}
threshold={DetectorCpuThreshold}
data={[series]}
/>
))}
</div>
<div className="bg-primary rounded-2xl flex-col">
<div className="p-2.5 bg-primary rounded-2xl flex-col">
<div className="mb-5">Detector Memory Usage</div>
{detMemSeries.map((series) => (
<SystemGraph
graphId="detector-usages"
title="Memory"
key={series.name}
graphId="detector-mem-usages"
unit="%"
data={detMemSeries}
name={series.name}
threshold={DetectorMemThreshold}
data={[series]}
/>
))}
</div>
</div>
</div>
@ -383,6 +406,19 @@ function System() {
export default System;
/**
* <div className="bg-primary rounded-2xl flex-col">
</div>
<div className="bg-primary rounded-2xl flex-col">
<SystemGraph
graphId="detector-usages"
unit="%"
name={""}
threshold={InferenceThreshold}
data={detMemSeries}
/>
</div>
*
* <Heading as="h4">Detectors</Heading>
<div className="grid grid-cols-1 sm:grid-cols-3">
<SystemGraph

View File

@ -7,3 +7,23 @@ export type GraphData = {
name?: string;
data: GraphDataPoint[];
};
export type Threshold = {
warning: number;
error: number;
};
export const InferenceThreshold = {
warning: 50,
error: 100,
} as Threshold;
export const DetectorCpuThreshold = {
warning: 25,
error: 50,
} as Threshold;
export const DetectorMemThreshold = {
warning: 20,
error: 50,
} as Threshold;