mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-10 21:25:24 +03:00
Use optimistic state and skeletons for loading
This commit is contained in:
parent
b8739ba592
commit
dbc830736a
@ -16,7 +16,8 @@ from frigate.types import StatsTrackingTypes
|
|||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
MAX_STATS_POINTS = 120
|
MAX_STATS_POINTS = 80
|
||||||
|
FREQUENCY_STATS_POINTS = 15
|
||||||
|
|
||||||
|
|
||||||
class StatsEmitter(threading.Thread):
|
class StatsEmitter(threading.Thread):
|
||||||
@ -70,9 +71,9 @@ class StatsEmitter(threading.Thread):
|
|||||||
def run(self) -> None:
|
def run(self) -> None:
|
||||||
time.sleep(10)
|
time.sleep(10)
|
||||||
for counter in itertools.cycle(
|
for counter in itertools.cycle(
|
||||||
range(int(self.config.mqtt.stats_interval / 10))
|
range(int(self.config.mqtt.stats_interval / FREQUENCY_STATS_POINTS))
|
||||||
):
|
):
|
||||||
if self.stop_event.wait(10):
|
if self.stop_event.wait(FREQUENCY_STATS_POINTS):
|
||||||
break
|
break
|
||||||
|
|
||||||
logger.debug("Starting stats collection")
|
logger.debug("Starting stats collection")
|
||||||
|
|||||||
@ -87,6 +87,9 @@ export function ThresholdBarGraph({
|
|||||||
tooltip: {
|
tooltip: {
|
||||||
theme: systemTheme || theme,
|
theme: systemTheme || theme,
|
||||||
},
|
},
|
||||||
|
markers: {
|
||||||
|
size: 0,
|
||||||
|
},
|
||||||
xaxis: {
|
xaxis: {
|
||||||
tickAmount: 4,
|
tickAmount: 4,
|
||||||
tickPlacement: "on",
|
tickPlacement: "on",
|
||||||
@ -105,7 +108,7 @@ export function ThresholdBarGraph({
|
|||||||
min: 0,
|
min: 0,
|
||||||
max: threshold.warning + 10,
|
max: threshold.warning + 10,
|
||||||
},
|
},
|
||||||
};
|
} as ApexCharts.ApexOptions;
|
||||||
}, [graphId, threshold, systemTheme, theme, formatTime]);
|
}, [graphId, threshold, systemTheme, theme, formatTime]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@ -12,6 +12,7 @@ import {
|
|||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import VainfoDialog from "@/components/overlay/VainfoDialog";
|
import VainfoDialog from "@/components/overlay/VainfoDialog";
|
||||||
import { ThresholdBarGraph } from "@/components/graph/SystemGraph";
|
import { ThresholdBarGraph } from "@/components/graph/SystemGraph";
|
||||||
|
import { Skeleton } from "@/components/ui/skeleton";
|
||||||
|
|
||||||
type GeneralMetricsProps = {
|
type GeneralMetricsProps = {
|
||||||
lastUpdated: number;
|
lastUpdated: number;
|
||||||
@ -264,10 +265,6 @@ export default function GeneralMetrics({
|
|||||||
return Object.values(series);
|
return Object.values(series);
|
||||||
}, [statsHistory]);
|
}, [statsHistory]);
|
||||||
|
|
||||||
if (statsHistory.length == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<VainfoDialog showVainfo={showVainfo} setShowVainfo={setShowVainfo} />
|
<VainfoDialog showVainfo={showVainfo} setShowVainfo={setShowVainfo} />
|
||||||
@ -276,102 +273,123 @@ export default function GeneralMetrics({
|
|||||||
<div className="text-muted-foreground text-sm font-medium">
|
<div className="text-muted-foreground text-sm font-medium">
|
||||||
Detectors
|
Detectors
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-4 grid grid-cols-1 sm:grid-cols-3 gap-2">
|
<div className="w-full mt-4 grid grid-cols-1 sm:grid-cols-3 gap-2">
|
||||||
<div className="p-2.5 bg-primary rounded-2xl flex-col">
|
{detInferenceTimeSeries.length != 0 ? (
|
||||||
<div className="mb-5">Detector Inference Speed</div>
|
<div className="p-2.5 bg-primary rounded-2xl flex-col">
|
||||||
{detInferenceTimeSeries.map((series) => (
|
<div className="mb-5">Detector Inference Speed</div>
|
||||||
<ThresholdBarGraph
|
{detInferenceTimeSeries.map((series) => (
|
||||||
key={series.name}
|
<ThresholdBarGraph
|
||||||
graphId={`${series.name}-inference`}
|
key={series.name}
|
||||||
name={series.name}
|
graphId={`${series.name}-inference`}
|
||||||
unit="ms"
|
name={series.name}
|
||||||
threshold={InferenceThreshold}
|
unit="ms"
|
||||||
updateTimes={updateTimes}
|
threshold={InferenceThreshold}
|
||||||
data={[series]}
|
updateTimes={updateTimes}
|
||||||
/>
|
data={[series]}
|
||||||
))}
|
/>
|
||||||
</div>
|
))}
|
||||||
<div className="p-2.5 bg-primary rounded-2xl flex-col">
|
</div>
|
||||||
<div className="mb-5">Detector CPU Usage</div>
|
) : (
|
||||||
{detCpuSeries.map((series) => (
|
<Skeleton className="w-full aspect-video" />
|
||||||
<ThresholdBarGraph
|
)}
|
||||||
key={series.name}
|
{statsHistory.length != 0 ? (
|
||||||
graphId={`${series.name}-cpu`}
|
<div className="p-2.5 bg-primary rounded-2xl flex-col">
|
||||||
unit="%"
|
<div className="mb-5">Detector CPU Usage</div>
|
||||||
name={series.name}
|
{detCpuSeries.map((series) => (
|
||||||
threshold={DetectorCpuThreshold}
|
<ThresholdBarGraph
|
||||||
updateTimes={updateTimes}
|
key={series.name}
|
||||||
data={[series]}
|
graphId={`${series.name}-cpu`}
|
||||||
/>
|
unit="%"
|
||||||
))}
|
name={series.name}
|
||||||
</div>
|
threshold={DetectorCpuThreshold}
|
||||||
<div className="p-2.5 bg-primary rounded-2xl flex-col">
|
updateTimes={updateTimes}
|
||||||
<div className="mb-5">Detector Memory Usage</div>
|
data={[series]}
|
||||||
{detMemSeries.map((series) => (
|
/>
|
||||||
<ThresholdBarGraph
|
))}
|
||||||
key={series.name}
|
</div>
|
||||||
graphId={`${series.name}-mem`}
|
) : (
|
||||||
unit="%"
|
<Skeleton className="w-full aspect-video" />
|
||||||
name={series.name}
|
)}
|
||||||
threshold={DetectorMemThreshold}
|
{statsHistory.length != 0 ? (
|
||||||
updateTimes={updateTimes}
|
<div className="p-2.5 bg-primary rounded-2xl flex-col">
|
||||||
data={[series]}
|
<div className="mb-5">Detector Memory Usage</div>
|
||||||
/>
|
{detMemSeries.map((series) => (
|
||||||
))}
|
<ThresholdBarGraph
|
||||||
</div>
|
key={series.name}
|
||||||
|
graphId={`${series.name}-mem`}
|
||||||
|
unit="%"
|
||||||
|
name={series.name}
|
||||||
|
threshold={DetectorMemThreshold}
|
||||||
|
updateTimes={updateTimes}
|
||||||
|
data={[series]}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<Skeleton className="w-full aspect-video" />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{statsHistory.length > 0 && statsHistory[0].gpu_usages && (
|
{(statsHistory.length == 0 || statsHistory[0].gpu_usages) && (
|
||||||
<>
|
<>
|
||||||
<div className="mt-4 flex items-center justify-between">
|
<div className="mt-4 flex items-center justify-between">
|
||||||
<div className="text-muted-foreground text-sm font-medium">
|
<div className="text-muted-foreground text-sm font-medium">
|
||||||
GPUs
|
GPUs
|
||||||
</div>
|
</div>
|
||||||
{Object.keys(statsHistory[0].gpu_usages).filter(
|
{statsHistory.length > 0 &&
|
||||||
(key) =>
|
Object.keys(statsHistory[0].gpu_usages ?? {}).filter(
|
||||||
key == "amd-vaapi" ||
|
(key) =>
|
||||||
key == "intel-vaapi" ||
|
key == "amd-vaapi" ||
|
||||||
key == "intel-qsv",
|
key == "intel-vaapi" ||
|
||||||
).length > 0 && (
|
key == "intel-qsv",
|
||||||
<Button
|
).length > 0 && (
|
||||||
className="cursor-pointer"
|
<Button
|
||||||
variant="secondary"
|
className="cursor-pointer"
|
||||||
size="sm"
|
variant="secondary"
|
||||||
onClick={() => setShowVainfo(true)}
|
size="sm"
|
||||||
>
|
onClick={() => setShowVainfo(true)}
|
||||||
Hardware Info
|
>
|
||||||
</Button>
|
Hardware Info
|
||||||
)}
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className=" mt-4 grid grid-cols-1 sm:grid-cols-2 gap-2">
|
<div className=" mt-4 grid grid-cols-1 sm:grid-cols-2 gap-2">
|
||||||
<div className="p-2.5 bg-primary rounded-2xl flex-col">
|
{statsHistory.length != 0 ? (
|
||||||
<div className="mb-5">GPU Usage</div>
|
<div className="p-2.5 bg-primary rounded-2xl flex-col">
|
||||||
{gpuSeries.map((series) => (
|
<div className="mb-5">GPU Usage</div>
|
||||||
<ThresholdBarGraph
|
{gpuSeries.map((series) => (
|
||||||
key={series.name}
|
<ThresholdBarGraph
|
||||||
graphId={`${series.name}-gpu`}
|
key={series.name}
|
||||||
name={series.name}
|
graphId={`${series.name}-gpu`}
|
||||||
unit=""
|
name={series.name}
|
||||||
threshold={GPUUsageThreshold}
|
unit=""
|
||||||
updateTimes={updateTimes}
|
threshold={GPUUsageThreshold}
|
||||||
data={[series]}
|
updateTimes={updateTimes}
|
||||||
/>
|
data={[series]}
|
||||||
))}
|
/>
|
||||||
</div>
|
))}
|
||||||
<div className="p-2.5 bg-primary rounded-2xl flex-col">
|
</div>
|
||||||
<div className="mb-5">GPU Memory</div>
|
) : (
|
||||||
{gpuMemSeries.map((series) => (
|
<Skeleton className="w-full aspect-video" />
|
||||||
<ThresholdBarGraph
|
)}
|
||||||
key={series.name}
|
{statsHistory.length != 0 ? (
|
||||||
graphId={`${series.name}-mem`}
|
<div className="p-2.5 bg-primary rounded-2xl flex-col">
|
||||||
unit=""
|
<div className="mb-5">GPU Memory</div>
|
||||||
name={series.name}
|
{gpuMemSeries.map((series) => (
|
||||||
threshold={GPUMemThreshold}
|
<ThresholdBarGraph
|
||||||
updateTimes={updateTimes}
|
key={series.name}
|
||||||
data={[series]}
|
graphId={`${series.name}-mem`}
|
||||||
/>
|
unit=""
|
||||||
))}
|
name={series.name}
|
||||||
</div>
|
threshold={GPUMemThreshold}
|
||||||
|
updateTimes={updateTimes}
|
||||||
|
data={[series]}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<Skeleton className="w-full aspect-video" />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@ -380,34 +398,42 @@ export default function GeneralMetrics({
|
|||||||
Other Processes
|
Other Processes
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-4 grid grid-cols-1 sm:grid-cols-2 gap-2">
|
<div className="mt-4 grid grid-cols-1 sm:grid-cols-2 gap-2">
|
||||||
<div className="p-2.5 bg-primary rounded-2xl flex-col">
|
{statsHistory.length != 0 ? (
|
||||||
<div className="mb-5">Process CPU Usage</div>
|
<div className="p-2.5 bg-primary rounded-2xl flex-col">
|
||||||
{otherProcessCpuSeries.map((series) => (
|
<div className="mb-5">Process CPU Usage</div>
|
||||||
<ThresholdBarGraph
|
{otherProcessCpuSeries.map((series) => (
|
||||||
key={series.name}
|
<ThresholdBarGraph
|
||||||
graphId={`${series.name}-cpu`}
|
key={series.name}
|
||||||
name={series.name.replaceAll("_", " ")}
|
graphId={`${series.name}-cpu`}
|
||||||
unit="%"
|
name={series.name.replaceAll("_", " ")}
|
||||||
threshold={DetectorCpuThreshold}
|
unit="%"
|
||||||
updateTimes={updateTimes}
|
threshold={DetectorCpuThreshold}
|
||||||
data={[series]}
|
updateTimes={updateTimes}
|
||||||
/>
|
data={[series]}
|
||||||
))}
|
/>
|
||||||
</div>
|
))}
|
||||||
<div className="p-2.5 bg-primary rounded-2xl flex-col">
|
</div>
|
||||||
<div className="mb-5">Process Memory Usage</div>
|
) : (
|
||||||
{otherProcessMemSeries.map((series) => (
|
<Skeleton className="w-full aspect-tall" />
|
||||||
<ThresholdBarGraph
|
)}
|
||||||
key={series.name}
|
{statsHistory.length != 0 ? (
|
||||||
graphId={`${series.name}-mem`}
|
<div className="p-2.5 bg-primary rounded-2xl flex-col">
|
||||||
unit="%"
|
<div className="mb-5">Process Memory Usage</div>
|
||||||
name={series.name.replaceAll("_", " ")}
|
{otherProcessMemSeries.map((series) => (
|
||||||
threshold={DetectorMemThreshold}
|
<ThresholdBarGraph
|
||||||
updateTimes={updateTimes}
|
key={series.name}
|
||||||
data={[series]}
|
graphId={`${series.name}-mem`}
|
||||||
/>
|
unit="%"
|
||||||
))}
|
name={series.name.replaceAll("_", " ")}
|
||||||
</div>
|
threshold={DetectorMemThreshold}
|
||||||
|
updateTimes={updateTimes}
|
||||||
|
data={[series]}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<Skeleton className="w-full aspect-tall" />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user