Fix live metrics change view and splits plots#469
Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates the LiveMetricsChart React component to reduce unnecessary recalculation during renders and to allow the metrics WebSocket to connect to a configurable backend base URL (via REACT_APP_API_URL).
Changes:
- Memoizes metric filtering and chart data preparation with
useMemoto avoid recomputing on unrelated renders. - Refactors WebSocket URL construction to derive the WS base from
REACT_APP_API_URLinstead ofwindow.location.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const apiUrl = process.env.REACT_APP_API_URL || ""; | ||
| const wsBase = apiUrl.replace(/^http/, "ws"); | ||
| const ws = new WebSocket(`${wsBase}/v1/metrics/ws/${run.id}`); | ||
|
|
There was a problem hiding this comment.
apiUrl falls back to an empty string, which makes new WebSocket(${wsBase}/v1/...) throw at runtime because the URL resolves to an http(s) URL (or just a path) instead of a ws:///wss:// URL. This means the component can break entirely when REACT_APP_API_URL is unset or set to a relative value.
Consider building the WS URL from the same base used by the REST client (e.g. api.defaults.baseURL) and, if no base is configured, derive it from window.location.origin (including the /api prefix used elsewhere) and explicitly convert the scheme to ws/wss using new URL(...) to avoid malformed URLs and double slashes.
| const apiUrl = process.env.REACT_APP_API_URL || ""; | |
| const wsBase = apiUrl.replace(/^http/, "ws"); | |
| const ws = new WebSocket(`${wsBase}/v1/metrics/ws/${run.id}`); | |
| const apiUrl = | |
| process.env.REACT_APP_API_URL || `${window.location.origin}/api`; | |
| let wsUrl; | |
| try { | |
| wsUrl = new URL(`/v1/metrics/ws/${run.id}`, apiUrl); | |
| } catch (e) { | |
| console.error("Invalid WebSocket base URL:", apiUrl, e); | |
| return; | |
| } | |
| if (wsUrl.protocol === "http:") { | |
| wsUrl.protocol = "ws:"; | |
| } else if (wsUrl.protocol === "https:") { | |
| wsUrl.protocol = "wss:"; | |
| } | |
| const ws = new WebSocket(wsUrl.toString()); |
| const m = data[split]?.[level] ?? {}; | ||
| const a = availableMetrics[split] ?? []; | ||
| return Object.fromEntries( | ||
| Object.entries(m).filter(([name]) => a.includes(name)), |
There was a problem hiding this comment.
Inside the useMemo for filteredMetrics, the temporary variables m and a are quite cryptic compared to the rest of the file’s naming style. Using clearer names (e.g. metrics / allowedMetrics) would make the intent easier to follow when revisiting this logic.
| const m = data[split]?.[level] ?? {}; | |
| const a = availableMetrics[split] ?? []; | |
| return Object.fromEntries( | |
| Object.entries(m).filter(([name]) => a.includes(name)), | |
| const metrics = data[split]?.[level] ?? {}; | |
| const allowedMetrics = availableMetrics[split] ?? []; | |
| return Object.fromEntries( | |
| Object.entries(metrics).filter(([name]) => allowedMetrics.includes(name)), |
This pull request optimizes the
LiveMetricsChartcomponent by improving how metric data is filtered and prepared for charting, and by making the WebSocket connection more configurable. The main changes involve usinguseMemofor performance, and updating the WebSocket URL construction to support custom API endpoints.Performance improvements:
useMemo, ensuring these operations are only recalculated when their dependencies change, which improves rendering efficiency. [1] [2] [3]Configuration and maintainability:
REACT_APP_API_URLenvironment variable, allowing the frontend to connect to a custom backend endpoint instead of always using the current window location.