Skip to content

Commit fa5ca41

Browse files
committed
Refactoring
1 parent fe3bf57 commit fa5ca41

File tree

1 file changed

+160
-147
lines changed

1 file changed

+160
-147
lines changed

website/src/components/device-status-panel.tsx

+160-147
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { useEffect, useState, useCallback } from "react";
1+
import { useEffect, useState, useCallback, useMemo } from "react";
22
import {
33
Box,
44
SplitPanel,
@@ -22,7 +22,6 @@ interface DeviceMetrics {
2222
temperature: number;
2323
cpuFreq: number;
2424
cpuFreqMax: number;
25-
cpuFreqPct: number;
2625
latencyMean: number;
2726
latencyP95: number;
2827
fpsMean: number;
@@ -42,20 +41,44 @@ interface DeviceStatusResponse {
4241
}
4342

4443
const DeviceStatusPanel = ({ isInferenceRunning, setNotifications }: DeviceStatusProps) => {
45-
// Define thresholds for different metrics
46-
const [thresholds] = useState({
47-
cpu: {
48-
usage: { warning: 90, error: 99 },
49-
temperature: { warning: 75, error: 90 },
50-
frequency: { warning: 75, error: 50 }, // Note: For CPU frequency, higher is better
51-
},
52-
memory: { warning: 85, error: 95 },
53-
disk: { warning: 90, error: 95 },
54-
performance: {
55-
latency_p95: { warning: 1.25, error: 1.5 },
56-
fps_mean: { warning: 1.05, error: 1.1 },
57-
},
58-
});
44+
// Define comparison types
45+
type ComparisonOperator = "gt" | "lt" | "gte" | "lte" | "eq";
46+
47+
// Create a function that returns a comparator based on the operator string
48+
const getComparator = useCallback((op: ComparisonOperator) => {
49+
switch (op) {
50+
case "gt":
51+
return (a: number, b: number) => a > b;
52+
case "lt":
53+
return (a: number, b: number) => a < b;
54+
case "gte":
55+
return (a: number, b: number) => a >= b;
56+
case "lte":
57+
return (a: number, b: number) => a <= b;
58+
case "eq":
59+
return (a: number, b: number) => a === b;
60+
default:
61+
return (a: number, b: number) => a > b; // Default to greater than
62+
}
63+
}, []);
64+
65+
// Define thresholds for different metrics, wrapped in useMemo to maintain reference equality
66+
const thresholds = useMemo(
67+
() => ({
68+
cpu: {
69+
usage: { warning: 90, error: 99, compare: "gt" as ComparisonOperator },
70+
temperature: { warning: 75, error: 90, compare: "gt" as ComparisonOperator },
71+
frequency: { warning: 85, error: 75, compare: "lt" as ComparisonOperator }, // Note: For CPU frequency, higher is better
72+
},
73+
memory: { warning: 85, error: 90, compare: "gt" as ComparisonOperator },
74+
disk: { warning: 90, error: 95, compare: "gt" as ComparisonOperator },
75+
performance: {
76+
latency_p95: { warning: 1.35, error: 1.75, compare: "gt" as ComparisonOperator },
77+
fps_mean: { warning: 1.05, error: 1.1, compare: "gt" as ComparisonOperator },
78+
},
79+
}),
80+
[]
81+
); // Empty dependency array means this will only be calculated once
5982

6083
const [metrics, setMetrics] = useState<DeviceMetrics>({
6184
cpuUsage: 0,
@@ -64,7 +87,6 @@ const DeviceStatusPanel = ({ isInferenceRunning, setNotifications }: DeviceStatu
6487
temperature: 0,
6588
cpuFreq: 0,
6689
cpuFreqMax: 0,
67-
cpuFreqPct: 0,
6890
latencyMean: 0.0,
6991
latencyP95: 0.0,
7092
fpsMean: 0.0,
@@ -116,48 +138,121 @@ const DeviceStatusPanel = ({ isInferenceRunning, setNotifications }: DeviceStatu
116138
}
117139
}, [isInferenceRunning]);
118140

119-
// Separate effect for handling warning and error messages based on metrics
120-
useEffect(() => {
121-
// Check CPU usage
122-
const cpuUsageId = "device-status-cpu-usage";
123-
if (metrics.cpuUsage >= thresholds.cpu.usage.error) {
124-
addFlashMessage(cpuUsageId, "CPU Usage is extremely high", "error");
125-
} else if (metrics.cpuUsage >= thresholds.cpu.usage.warning) {
126-
addFlashMessage(cpuUsageId, "CPU Usage is getting high", "warning");
127-
} else {
128-
removeFlashMessage(cpuUsageId);
129-
}
141+
// Updated status check function using the dynamic comparator
142+
const checkStatus = useCallback(
143+
(
144+
value: number,
145+
thresholdConfig: { warning: number; error: number; compare: ComparisonOperator }
146+
): "success" | "warning" | "error" => {
147+
const { warning, error, compare } = thresholdConfig;
148+
const comparator = getComparator(compare);
149+
150+
if (!comparator(value, warning)) return "success";
151+
if (!comparator(value, error)) return "warning";
152+
return "error";
153+
},
154+
[getComparator]
155+
);
130156

131-
// Check CPU temperature
132-
const cpuTempId = "device-status-cpu-temp";
133-
if (metrics.temperature >= thresholds.cpu.temperature.error) {
134-
addFlashMessage(cpuTempId, "CPU Temperature is extremely high", "error");
135-
} else if (metrics.temperature >= thresholds.cpu.temperature.warning) {
136-
addFlashMessage(cpuTempId, "CPU Temperature is getting high", "warning");
137-
} else {
138-
removeFlashMessage(cpuTempId);
139-
}
157+
const checkStatusWithInference = useCallback(
158+
(
159+
value: number,
160+
thresholdConfig: { warning: number; error: number; compare: ComparisonOperator },
161+
isInferenceRunning: boolean,
162+
updatesSinceInferenceStartedDelay: number,
163+
noInferenceStatus: "info" | "stopped" | "pending" = "stopped"
164+
): "info" | "success" | "warning" | "error" | "stopped" | "pending" => {
165+
if (!isInferenceRunning) return noInferenceStatus;
166+
if (updatesSinceInferenceStarted <= updatesSinceInferenceStartedDelay) return "pending";
167+
return checkStatus(value, thresholdConfig);
168+
},
169+
[checkStatus, updatesSinceInferenceStarted]
170+
);
140171

141-
// Check memory usage
142-
const memoryUsageId = "device-status-memory-usage";
143-
if (metrics.memoryUsage >= thresholds.memory.error) {
144-
addFlashMessage(memoryUsageId, "Memory Usage is extremely high", "error");
145-
} else if (metrics.memoryUsage >= thresholds.memory.warning) {
146-
addFlashMessage(memoryUsageId, "Memory Usage is getting high", "warning");
147-
} else {
148-
removeFlashMessage(memoryUsageId);
149-
}
172+
const allAlerts = useMemo(
173+
() => ({
174+
"device-status-cpu-usage": {
175+
metricValue: metrics.cpuUsage,
176+
status: checkStatus(metrics.cpuUsage, thresholds.cpu.usage),
177+
warningMessage: "CPU Usage is high",
178+
errorMessage: "CPU Usage is extremely high",
179+
},
180+
"device-status-cpu-temp": {
181+
metricValue: metrics.temperature,
182+
status: checkStatus(metrics.temperature, thresholds.cpu.temperature),
183+
warningMessage: "CPU Temperature is high",
184+
errorMessage: "CPU Temperature is extremely high",
185+
},
186+
"device-status-memory-usage": {
187+
metricValue: metrics.memoryUsage,
188+
status: checkStatus(metrics.memoryUsage, thresholds.memory),
189+
warningMessage: "Memory Usage is high",
190+
errorMessage: "Memory Usage is extremely high",
191+
},
192+
"device-status-disk-usage": {
193+
metricValue: metrics.diskUsage,
194+
status: checkStatus(metrics.diskUsage, thresholds.disk),
195+
warningMessage: "Disk Usage is high",
196+
errorMessage: "Disk Usage is extremely high",
197+
},
198+
"device-status-cpu-freq": {
199+
metricValue: (metrics.cpuFreq / metrics.cpuFreqMax) * 100.0,
200+
status: checkStatusWithInference(
201+
(metrics.cpuFreq / metrics.cpuFreqMax) * 100.0,
202+
thresholds.cpu.frequency,
203+
isInferenceRunning,
204+
2,
205+
"info"
206+
),
207+
warningMessage: "CPU Frequency is low",
208+
errorMessage: "CPU Frequency is critically low",
209+
updateDelay: 2,
210+
noInferenceStatus: "info" as "info" | "stopped" | "pending",
211+
},
212+
"device-status-latency-p95": {
213+
metricValue: metrics.latencyP95 / metrics.latencyMean,
214+
status: checkStatusWithInference(
215+
metrics.latencyP95 / metrics.latencyMean,
216+
thresholds.performance.latency_p95,
217+
isInferenceRunning,
218+
2,
219+
"stopped"
220+
),
221+
warningMessage: "95% Latency is high",
222+
errorMessage: "95% Latency is critically high",
223+
updateDelay: 2,
224+
noInferenceStatus: "stopped" as "info" | "stopped" | "pending",
225+
},
226+
"device-status-fps-mean": {
227+
metricValue: 30.0 / metrics.fpsMean,
228+
status: checkStatusWithInference(
229+
30.0 / metrics.fpsMean,
230+
thresholds.performance.fps_mean,
231+
isInferenceRunning,
232+
2,
233+
"stopped"
234+
),
235+
warningMessage: "Frame Rate is low",
236+
errorMessage: "Frame Rate is critically low",
237+
updateDelay: 2,
238+
noInferenceStatus: "stopped" as "info" | "stopped" | "pending",
239+
},
240+
}),
241+
[metrics, thresholds, checkStatus, checkStatusWithInference, isInferenceRunning]
242+
);
150243

151-
// Check disk usage
152-
const diskUsageId = "device-status-disk-usage";
153-
if (metrics.diskUsage >= thresholds.disk.error) {
154-
addFlashMessage(diskUsageId, "Disk Usage is extremely high", "error");
155-
} else if (metrics.diskUsage >= thresholds.disk.warning) {
156-
addFlashMessage(diskUsageId, "Disk Usage is getting high", "warning");
157-
} else {
158-
removeFlashMessage(diskUsageId);
159-
}
160-
}, [metrics, addFlashMessage, removeFlashMessage, thresholds]);
244+
// Separate effects for handling warning and error messages based on metrics
245+
useEffect(() => {
246+
Object.entries(allAlerts).forEach(([alertId, data]) => {
247+
if (data.status === "error") {
248+
addFlashMessage(alertId, data.errorMessage, "error");
249+
} else if (data.status === "warning") {
250+
addFlashMessage(alertId, data.warningMessage, "warning");
251+
} else {
252+
removeFlashMessage(alertId);
253+
}
254+
});
255+
}, [addFlashMessage, removeFlashMessage, allAlerts]);
161256

162257
// Count updates since inference started
163258
useEffect(() => {
@@ -180,7 +275,6 @@ const DeviceStatusPanel = ({ isInferenceRunning, setNotifications }: DeviceStatu
180275
temperature: parseFloat(response.cpu_temp.toFixed(1)),
181276
cpuFreq: parseFloat(response.cpu_freq.toFixed(0)),
182277
cpuFreqMax: parseFloat(response.cpu_freq_max.toFixed(0)),
183-
cpuFreqPct: (response.cpu_freq / response.cpu_freq_max) * 100,
184278
latencyMean: parseFloat(response.latency_mean.toFixed(1)),
185279
latencyP95: parseFloat(response.latency_p95.toFixed(1)),
186280
fpsMean: parseFloat(response.fps_mean.toFixed(1)),
@@ -197,42 +291,6 @@ const DeviceStatusPanel = ({ isInferenceRunning, setNotifications }: DeviceStatu
197291
return () => clearInterval(intervalId);
198292
}, []); // Remove updatesSinceInferenceStarted from dependency array
199293

200-
const checkStatus = (
201-
value: number,
202-
thresholdPair: [number, number]
203-
): "success" | "warning" | "error" => {
204-
const [warning, error] = thresholdPair;
205-
if (value < warning) return "success";
206-
if (value < error) return "warning";
207-
return "error";
208-
};
209-
210-
const getCPUStatusType = (
211-
value: number,
212-
thresholdPair: [number, number],
213-
isInferenceRunning: boolean
214-
): "info" | "success" | "warning" | "error" => {
215-
if (!isInferenceRunning) return "info";
216-
const [warning, error] = thresholdPair;
217-
if (value > warning) return "success";
218-
if (value > error) return "warning";
219-
return "error";
220-
};
221-
222-
const checkPerformanceStatus = (
223-
value: number,
224-
referenceValue: number,
225-
thresholdPair: [number, number],
226-
isInferenceRunning: boolean
227-
): "success" | "warning" | "error" | "stopped" | "pending" => {
228-
if (!isInferenceRunning) return "stopped";
229-
if (updatesSinceInferenceStarted <= 3) return "pending";
230-
const [warning, error] = thresholdPair;
231-
if (value/referenceValue < warning) return "success";
232-
if (value/referenceValue < error) return "warning";
233-
return "error";
234-
};
235-
236294
return (
237295
<SplitPanel header={"Car Health"} hidePreferencesButton={true} closeBehavior="collapse">
238296
<SpaceBetween size="xs" direction="vertical">
@@ -248,33 +306,17 @@ const DeviceStatusPanel = ({ isInferenceRunning, setNotifications }: DeviceStatu
248306
<Box variant="h4">CPU</Box>
249307
<div style={{ display: "grid", gridTemplateColumns: "100px auto", rowGap: "6px" }}>
250308
<Box>Usage:</Box>
251-
<StatusIndicator
252-
type={checkStatus(metrics.cpuUsage, [
253-
thresholds.cpu.usage.warning,
254-
thresholds.cpu.usage.error,
255-
])}
256-
>
309+
<StatusIndicator type={allAlerts["device-status-cpu-usage"].status}>
257310
{metrics.cpuUsage}%
258311
</StatusIndicator>
259312

260313
<Box>Temperature:</Box>
261-
<StatusIndicator
262-
type={checkStatus(metrics.temperature, [
263-
thresholds.cpu.temperature.warning,
264-
thresholds.cpu.temperature.error,
265-
])}
266-
>
314+
<StatusIndicator type={allAlerts["device-status-cpu-temp"].status}>
267315
{metrics.temperature}°C
268316
</StatusIndicator>
269317

270318
<Box>Frequency:</Box>
271-
<StatusIndicator
272-
type={getCPUStatusType(
273-
metrics.cpuFreqPct,
274-
[thresholds.cpu.frequency.warning, thresholds.cpu.frequency.error],
275-
isInferenceRunning && updatesSinceInferenceStarted > 2
276-
)}
277-
>
319+
<StatusIndicator type={allAlerts["device-status-cpu-freq"].status}>
278320
{metrics.cpuFreq} MHz / {metrics.cpuFreqMax} MHz
279321
</StatusIndicator>
280322
</div>
@@ -285,22 +327,12 @@ const DeviceStatusPanel = ({ isInferenceRunning, setNotifications }: DeviceStatu
285327
<Box variant="h4">Memory Usage</Box>
286328
<div style={{ display: "grid", gridTemplateColumns: "100px auto", rowGap: "6px" }}>
287329
<Box>RAM:</Box>
288-
<StatusIndicator
289-
type={checkStatus(metrics.memoryUsage, [
290-
thresholds.memory.warning,
291-
thresholds.memory.error,
292-
])}
293-
>
330+
<StatusIndicator type={allAlerts["device-status-memory-usage"].status}>
294331
{metrics.memoryUsage}%
295332
</StatusIndicator>
296333

297334
<Box>Disk:</Box>
298-
<StatusIndicator
299-
type={checkStatus(metrics.diskUsage, [
300-
thresholds.disk.warning,
301-
thresholds.disk.error,
302-
])}
303-
>
335+
<StatusIndicator type={allAlerts["device-status-disk-usage"].status}>
304336
{metrics.diskUsage}%
305337
</StatusIndicator>
306338
</div>
@@ -311,38 +343,19 @@ const DeviceStatusPanel = ({ isInferenceRunning, setNotifications }: DeviceStatu
311343
<Box variant="h4">Performance</Box>
312344
<div style={{ display: "grid", gridTemplateColumns: "100px auto", rowGap: "6px" }}>
313345
<Box>Mean Latency:</Box>
314-
<StatusIndicator
315-
type={isInferenceRunning ? "info" : "stopped"}
316-
>
346+
<StatusIndicator type={isInferenceRunning ? "info" : "stopped"}>
317347
{metrics.latencyMean.toFixed(1)} ms
318-
</StatusIndicator>
348+
</StatusIndicator>
319349
<Box>95% Latency:</Box>
320-
<StatusIndicator
321-
type={checkPerformanceStatus(
322-
metrics.latencyP95,
323-
metrics.latencyMean,
324-
[thresholds.performance.latency_p95.warning, thresholds.performance.latency_p95.error],
325-
isInferenceRunning
326-
)}
327-
>
350+
<StatusIndicator type={allAlerts["device-status-latency-p95"].status}>
328351
{metrics.latencyP95.toFixed(1)} ms
329352
</StatusIndicator>
330353
<Box>Frame Rate:</Box>
331-
<StatusIndicator
332-
type={checkPerformanceStatus(
333-
30.0,
334-
metrics.fpsMean,
335-
[thresholds.performance.fps_mean.warning, thresholds.performance.fps_mean.error],
336-
isInferenceRunning
337-
)}
338-
>
354+
<StatusIndicator type={allAlerts["device-status-fps-mean"].status}>
339355
{metrics.fpsMean.toFixed(1)} fps
340356
</StatusIndicator>
341357
</div>
342358
</SpaceBetween>
343-
344-
{/* Empty grid cell for layout balance */}
345-
<div></div>
346359
</Grid>
347360
</SpaceBetween>
348361
</SplitPanel>

0 commit comments

Comments
 (0)