Feature: Single Sandbox Resource Metrics#246
Conversation
- Removed redundant wrapper in SandboxDetailsHeader for SandboxDetailsTitle. - Updated DashboardLayoutHeader to ensure consistent rendering of ThemeSwitcher. - Refactored logs handling in VirtualizedLogsBody to utilize state for scroll container, enhancing performance and readability. - Adjusted event listeners for scroll handling to improve responsiveness.
|
|
||
| chart.group = SANDBOX_MONITORING_CHART_GROUP | ||
| echarts.connect(SANDBOX_MONITORING_CHART_GROUP) | ||
| }, [isMobile]) |
There was a problem hiding this comment.
Brush config set once, never updates on resize
Low Severity
handleChartReady dispatches the brush action based on isMobile, but onChartReady is only invoked once by echarts-for-react on mount. Although isMobile is in the dependency array of useCallback, the new callback reference won't be called again when isMobile changes. The key prop is resolvedTheme, not isMobile, so a viewport change from desktop to mobile (or vice versa) leaves the brush configuration stale — brush/zoom stays enabled on mobile or stays disabled on desktop.
| const end = urlParams.end ?? now | ||
|
|
||
| return { start, end } | ||
| }, [urlParams.start, urlParams.end, activePresetId, lifecycleBounds]) |
There was a problem hiding this comment.
Sandbox context derives lifecycle but never updates polling on preset changes
Medium Severity
The timeframe memo depends on urlParams.start, urlParams.end, activePresetId, and lifecycleBounds. When a preset is active and lifecycleBounds changes (e.g., sandbox goes from running to killed), preset.getValue() is called which returns a new timeframe. However, the setPreset callback on line 145 writes both preset and start/end to URL params, so on the next render the timeframe memo will see non-null urlParams.start/urlParams.end and a non-null activePresetId — the preset branch wins, which is correct. But the isPolling check on line 92 uses timeframe.end compared to Date.now(), meaning if the preset produces a stale end value (e.g. lifecycle settled), polling may incorrectly continue or stop.
| isPolling, | ||
| lifecycleBounds, | ||
| setUrlParams, | ||
| ]) |
There was a problem hiding this comment.
Live polling fetches data but never advances visible timeframe
Medium Severity
When a user zooms into a chart (which sets activePresetId to null via setCustomTimeframe), the live polling tick effect exits early on line 162 (!activePresetId), so the URL timeframe stops advancing. However, isPolling on line 87-90 can still be true (it doesn't depend on activePresetId), so the React Query refetchInterval on line 228 keeps re-fetching data for the same frozen fetchTimeframe. This means the chart appears stuck while unnecessary network requests continue in the background. Either isPolling needs to account for the absence of an active preset, or the tick effect needs to handle custom timeframes as well.
Additional Locations (1)
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
| !isLifecycleSettled && | ||
| (lifecycleBounds?.isRunning ?? false) && | ||
| timeframe.end + SANDBOX_MONITORING_OVERFETCH_MIN_MS >= Date.now() | ||
|
|
There was a problem hiding this comment.
Live polling condition may keep polling indefinitely for non-killed ended sandboxes
Medium Severity
The isPolling flag relies on isLifecycleSettled which requires hasKilledEvent to be true when the state is killed. But lifecycleBounds?.isRunning must also be true for polling to occur. For a sandbox that's killed but awaiting the killed event, isRunning would be false (since getSandboxLifecycleBounds likely returns isRunning: false for killed state), so isPolling would be false anyway, making the isLifecycleSettled check partially redundant for the metrics polling path. The sandbox context polling (lines 94-104 in context.tsx) separately handles this case, but the metrics controller polling may not fire when the killed event is still pending.


Note
Medium Risk
Moderate risk: introduces a new monitoring route with substantial client-side charting/URL-state logic and changes sandbox details polling behavior, which could affect dashboard performance and data freshness if mis-tuned.
Overview
Adds a new single-sandbox Monitoring view under
/dashboard/.../sandboxes/[sandboxId]/monitoringthat charts CPU/RAM/Disk utilization over a selectable timeframe (presets + custom range), supports brush-zoom with reset, and overlays lifecycle event markers plus paused-interval line breaks.Updates sandbox details state management to derive and expose a
sandboxLifecyclemodel (created/paused/ended + events), switches sandbox details polling to an aligned interval that continues briefly after kill until the killed event is observed, and adjusts header/logs timestamps to use the lifecycle-derived fields. Removes the configurable refresh/polling cookie + API route and replaces header “usage” widgets with static CPU/memory/disk spec items.Adds extensive unit tests for timeframe parsing/normalization, lifecycle derivation, chart-model generation (including paused gaps and markers), and a dev-only E2B stress test to generate lifecycle events; bumps
e2bto^2.14.0(lockfile updates included).Written by Cursor Bugbot for commit 12baba7. This will update automatically on new commits. Configure here.