Skip to content

Commit 4a42ac8

Browse files
committed
Resolution approach
1 parent fa5ca41 commit 4a42ac8

File tree

1 file changed

+178
-75
lines changed

1 file changed

+178
-75
lines changed

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

+178-75
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ const DeviceStatusPanel = ({ isInferenceRunning, setNotifications }: DeviceStatu
7373
memory: { warning: 85, error: 90, compare: "gt" as ComparisonOperator },
7474
disk: { warning: 90, error: 95, compare: "gt" as ComparisonOperator },
7575
performance: {
76+
latency_mean: { warning: 20.0, error: 30.0, compare: "gt" as ComparisonOperator },
7677
latency_p95: { warning: 1.35, error: 1.75, compare: "gt" as ComparisonOperator },
7778
fps_mean: { warning: 1.05, error: 1.1, compare: "gt" as ComparisonOperator },
7879
},
@@ -102,7 +103,7 @@ const DeviceStatusPanel = ({ isInferenceRunning, setNotifications }: DeviceStatu
102103
);
103104

104105
const addFlashMessage = useCallback(
105-
(id: string, content: string, type: FlashbarProps.Type) => {
106+
(id: string, content: string, type: FlashbarProps.Type, header?: string) => {
106107
// Check if a message with this ID already exists and update it if needed
107108
setNotifications((prev) => {
108109
const existingMessageIndex = prev.findIndex((message) => message.id === id);
@@ -114,6 +115,7 @@ const DeviceStatusPanel = ({ isInferenceRunning, setNotifications }: DeviceStatu
114115
type,
115116
dismissible: type !== "in-progress",
116117
onDismiss: type !== "in-progress" ? () => removeFlashMessage(id) : undefined,
118+
...(header && { header }),
117119
};
118120

119121
// If message already exists, update it
@@ -171,79 +173,146 @@ const DeviceStatusPanel = ({ isInferenceRunning, setNotifications }: DeviceStatu
171173

172174
const allAlerts = useMemo(
173175
() => ({
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",
176+
system: {
177+
"device-status-memory-usage": {
178+
metricValue: metrics.memoryUsage,
179+
status: checkStatus(metrics.memoryUsage, thresholds.memory),
180+
warningMessage: "Memory Usage is high",
181+
errorMessage: "Memory Usage is extremely high",
182+
},
183+
"device-status-disk-usage": {
184+
metricValue: metrics.diskUsage,
185+
status: checkStatus(metrics.diskUsage, thresholds.disk),
186+
warningMessage: "Disk Usage is high",
187+
errorMessage: "Disk Usage is extremely high",
188+
},
189+
"device-status-cpu-freq": {
190+
metricValue: (metrics.cpuFreq / metrics.cpuFreqMax) * 100.0,
191+
status: checkStatusWithInference(
192+
(metrics.cpuFreq / metrics.cpuFreqMax) * 100.0,
193+
thresholds.cpu.frequency,
194+
isInferenceRunning,
195+
2,
196+
"info"
197+
),
198+
warningMessage: "CPU Frequency is low",
199+
errorMessage: "CPU Frequency is critically low",
200+
updateDelay: 2,
201+
noInferenceStatus: "info" as "info" | "stopped" | "pending",
202+
},
179203
},
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",
204+
performance: {
205+
"device-status-cpu-temp": {
206+
metricValue: metrics.temperature,
207+
status: checkStatus(metrics.temperature, thresholds.cpu.temperature),
208+
warningMessage: "CPU Temperature is high",
209+
errorMessage: "CPU Temperature is extremely high",
210+
},
211+
"device-status-cpu-usage": {
212+
metricValue: metrics.cpuUsage,
213+
status: checkStatusWithInference(
214+
metrics.cpuUsage,
215+
thresholds.cpu.usage,
216+
isInferenceRunning,
217+
2,
218+
"info"
219+
),
220+
warningMessage: "CPU Usage is high",
221+
errorMessage: "CPU Usage is extremely high",
222+
updateDelay: 2,
223+
},
224+
"device-status-latency": {
225+
metricValue: metrics.latencyMean,
226+
status: checkStatusWithInference(
227+
metrics.latencyMean,
228+
thresholds.performance.latency_mean,
229+
isInferenceRunning,
230+
2,
231+
"stopped"
232+
),
233+
warningMessage: "Latency is high",
234+
errorMessage: "Latency is critically high",
235+
updateDelay: 2,
236+
noInferenceStatus: "stopped" as "info" | "stopped" | "pending",
237+
},
238+
"device-status-latency-p95": {
239+
metricValue: metrics.latencyP95 / metrics.latencyMean,
240+
status: checkStatusWithInference(
241+
metrics.latencyP95 / metrics.latencyMean,
242+
thresholds.performance.latency_p95,
243+
isInferenceRunning,
244+
2,
245+
"stopped"
246+
),
247+
warningMessage: "95% Latency is high",
248+
errorMessage: "95% Latency is critically high",
249+
updateDelay: 2,
250+
noInferenceStatus: "stopped" as "info" | "stopped" | "pending",
251+
},
252+
"device-status-fps-mean": {
253+
metricValue: 30.0 / metrics.fpsMean,
254+
status: checkStatusWithInference(
255+
30.0 / metrics.fpsMean,
256+
thresholds.performance.fps_mean,
257+
isInferenceRunning,
258+
2,
259+
"stopped"
260+
),
261+
warningMessage: "Frame Rate is low",
262+
errorMessage: "Frame Rate is critically low",
263+
updateDelay: 2,
264+
noInferenceStatus: "stopped" as "info" | "stopped" | "pending",
265+
},
239266
},
240267
}),
241268
[metrics, thresholds, checkStatus, checkStatusWithInference, isInferenceRunning]
242269
);
243270

271+
// Get combined performance metrics status and message
272+
const performanceMetricsAlert = useMemo(() => {
273+
const performanceAlerts = Object.values(allAlerts.performance);
274+
275+
// Get the worst status (error > warning > success/info/stopped/pending)
276+
const getStatusPriority = (status: string): number => {
277+
switch (status) {
278+
case "error":
279+
return 2;
280+
case "warning":
281+
return 1;
282+
default:
283+
return 0; // info, success, stopped, pending
284+
}
285+
};
286+
287+
const worstStatus = performanceAlerts
288+
.map((alert) => alert.status)
289+
.reduce(
290+
(worst, current) =>
291+
getStatusPriority(current) > getStatusPriority(worst) ? current : worst,
292+
"success" as string
293+
);
294+
295+
// Build a combined message including both warnings and errors
296+
const errorMessages = performanceAlerts
297+
.filter((alert) => alert.status === "error")
298+
.map((alert) => alert.errorMessage);
299+
300+
const warningMessages = performanceAlerts
301+
.filter((alert) => alert.status === "warning")
302+
.map((alert) => alert.warningMessage);
303+
304+
const messages = [...errorMessages, ...warningMessages];
305+
306+
return {
307+
status: worstStatus,
308+
message: messages.join(". ") + ".",
309+
hasIssue: worstStatus === "warning" || worstStatus === "error",
310+
};
311+
}, [allAlerts.performance]);
312+
244313
// Separate effects for handling warning and error messages based on metrics
245314
useEffect(() => {
246-
Object.entries(allAlerts).forEach(([alertId, data]) => {
315+
Object.entries(allAlerts.system).forEach(([alertId, data]) => {
247316
if (data.status === "error") {
248317
addFlashMessage(alertId, data.errorMessage, "error");
249318
} else if (data.status === "warning") {
@@ -252,7 +321,41 @@ const DeviceStatusPanel = ({ isInferenceRunning, setNotifications }: DeviceStatu
252321
removeFlashMessage(alertId);
253322
}
254323
});
255-
}, [addFlashMessage, removeFlashMessage, allAlerts]);
324+
}, [addFlashMessage, removeFlashMessage, allAlerts.system]);
325+
326+
useEffect(() => {
327+
// Handle combined performance metrics alert
328+
const performanceAlertId = "device-status-performance";
329+
if (performanceMetricsAlert.hasIssue) {
330+
addFlashMessage(
331+
performanceAlertId,
332+
performanceMetricsAlert.message,
333+
performanceMetricsAlert.status as FlashbarProps.Type,
334+
"Potential Performance Issue"
335+
);
336+
} else {
337+
// For performance messages, convert to info with last contents as reference
338+
setNotifications((prev) => {
339+
const existingMessageIndex = prev.findIndex((message) => message.id === performanceAlertId);
340+
if (existingMessageIndex >= 0) {
341+
const existingMessage = prev[existingMessageIndex];
342+
if (existingMessage.type === "info") {
343+
return prev; // If the status is already "info", do nothing
344+
}
345+
const lastContent = existingMessage.content;
346+
const updatedMessages = [...prev];
347+
updatedMessages[existingMessageIndex] = {
348+
...existingMessage,
349+
type: "info",
350+
content: `Last Error: ${lastContent}`,
351+
header: "Performance issue resolved",
352+
};
353+
return updatedMessages;
354+
}
355+
return prev;
356+
});
357+
}
358+
}, [addFlashMessage, removeFlashMessage, performanceMetricsAlert, setNotifications]);
256359

257360
// Count updates since inference started
258361
useEffect(() => {
@@ -306,17 +409,17 @@ const DeviceStatusPanel = ({ isInferenceRunning, setNotifications }: DeviceStatu
306409
<Box variant="h4">CPU</Box>
307410
<div style={{ display: "grid", gridTemplateColumns: "100px auto", rowGap: "6px" }}>
308411
<Box>Usage:</Box>
309-
<StatusIndicator type={allAlerts["device-status-cpu-usage"].status}>
412+
<StatusIndicator type={allAlerts.performance["device-status-cpu-usage"].status}>
310413
{metrics.cpuUsage}%
311414
</StatusIndicator>
312415

313416
<Box>Temperature:</Box>
314-
<StatusIndicator type={allAlerts["device-status-cpu-temp"].status}>
417+
<StatusIndicator type={allAlerts.performance["device-status-cpu-temp"].status}>
315418
{metrics.temperature}°C
316419
</StatusIndicator>
317420

318421
<Box>Frequency:</Box>
319-
<StatusIndicator type={allAlerts["device-status-cpu-freq"].status}>
422+
<StatusIndicator type={allAlerts.system["device-status-cpu-freq"].status}>
320423
{metrics.cpuFreq} MHz / {metrics.cpuFreqMax} MHz
321424
</StatusIndicator>
322425
</div>
@@ -327,12 +430,12 @@ const DeviceStatusPanel = ({ isInferenceRunning, setNotifications }: DeviceStatu
327430
<Box variant="h4">Memory Usage</Box>
328431
<div style={{ display: "grid", gridTemplateColumns: "100px auto", rowGap: "6px" }}>
329432
<Box>RAM:</Box>
330-
<StatusIndicator type={allAlerts["device-status-memory-usage"].status}>
433+
<StatusIndicator type={allAlerts.system["device-status-memory-usage"].status}>
331434
{metrics.memoryUsage}%
332435
</StatusIndicator>
333436

334437
<Box>Disk:</Box>
335-
<StatusIndicator type={allAlerts["device-status-disk-usage"].status}>
438+
<StatusIndicator type={allAlerts.system["device-status-disk-usage"].status}>
336439
{metrics.diskUsage}%
337440
</StatusIndicator>
338441
</div>
@@ -343,15 +446,15 @@ const DeviceStatusPanel = ({ isInferenceRunning, setNotifications }: DeviceStatu
343446
<Box variant="h4">Performance</Box>
344447
<div style={{ display: "grid", gridTemplateColumns: "100px auto", rowGap: "6px" }}>
345448
<Box>Mean Latency:</Box>
346-
<StatusIndicator type={isInferenceRunning ? "info" : "stopped"}>
449+
<StatusIndicator type={allAlerts.performance["device-status-latency"].status}>
347450
{metrics.latencyMean.toFixed(1)} ms
348451
</StatusIndicator>
349452
<Box>95% Latency:</Box>
350-
<StatusIndicator type={allAlerts["device-status-latency-p95"].status}>
453+
<StatusIndicator type={allAlerts.performance["device-status-latency-p95"].status}>
351454
{metrics.latencyP95.toFixed(1)} ms
352455
</StatusIndicator>
353456
<Box>Frame Rate:</Box>
354-
<StatusIndicator type={allAlerts["device-status-fps-mean"].status}>
457+
<StatusIndicator type={allAlerts.performance["device-status-fps-mean"].status}>
355458
{metrics.fpsMean.toFixed(1)} fps
356459
</StatusIndicator>
357460
</div>

0 commit comments

Comments
 (0)