Repository navigation
Web charts: show the queries, blocking or deadlocks at the clicked time (#5230) - #5286
Merged
Merged
Conversation
…er, so the range picker shows the new range (#5230) Review finding 1 on PR #5286. The item set the custom range and then redrew only the panel grid. The range picker lives in the page head, which only a full render rebuilds, so on the tab already open the picker kept the old preset and the Custom form stayed hidden. From another tab, the panel redraw started a whole batch of reads under the new range, and the hashchange render that followed aborted that batch. applyCustomRange takes { redraw: false } for a caller that rebuilds the page itself. goToTime passes it, then always renders through the router: it sets the hash, or raises hashchange itself when the hash already holds the target (setting a hash to its current value fires none). The harness stands in window.dispatchEvent and records the redraw option the item passes. The new case pins redraw false for all three items, no raised event on a move to another tab, and exactly one on the tab already open.
…drawn point, the one the hover tooltip names (#5230) Review finding 2 on PR #5286. The menu mapped the raw pointer x to a time, but the hover tooltip and the desktop's chart drill-down both snap to the nearest drawn point. On a 7-day chart one pixel is about 19 minutes, so a right-click a couple of pixels beside a one-bucket deadlock spike opened an hour about 40 minutes away that did not hold it, and the Deadlocks grid came up empty. The tooltip's nearest-point loop moves into one helper, nearestPointIdx, which the tooltip and the menu's timeAt now both call, so there is a single loop and the two cannot disagree. A click past either edge snaps to the first or last point, the same clamp values as before. A plot with no point gives no time, so no items. The new case draws two points, at 00:00 and 00:10, and right-clicks near each (expecting that point's time, where the raw pointer time would be 00:05.85 at the right one) and at the exact middle (either point, never 00:05).
…ide the plot, not on the legend, status line, button or menu (#5230) Review finding 3 on PR #5286. The contextmenu listener sits on the whole chart box, which also holds the legend, the annotation legend, the status line, the source box, the menu button and the open menu. timeAt mapped the pointer x of any of them through the plot's x scale and clamped it, so a right-click on the legend under a 24-hour chart offered "Show Active Queries at This Time" for a point on the axis the user never pointed at, and Shift+F10 on the focused button did the same with the right-edge time. The handler now names a time only when the event target is inside the plot's SVG (root.contains(e.target)). Anywhere else, and from the keyboard, the menu holds just Copy Image, Save Image As and Export Data to CSV. The harness gives FakeNode a contains method and lets a right-click name its target (the plot's SVG unless a case says otherwise). The new case right-clicks the legend, the status line, the button and an item of the open menu, and expects only the three usual items each time.
…s it, as the desktop does (#5230) A right-click on a server-tab line chart used to offer all three items. The desktop's chart drill-downs give each chart one: Show Blocking at This Time on the blocking charts, Show Deadlocks at This Time on the deadlock charts, and Show Active Queries at This Time on the rest. atTime now carries an item, and line() and fanout() read it from atTimeItem (Blocking Events, Lock Waits and Blocking Severity name "blocking"; Deadlocks and Deadlock Severity name "deadlocks").
… Show Deadlocks reaches the Deadlocks grid (#5230) The desktop's Deadlocks item opens its Deadlocks sub-tab. On the web both the Blocking and the Deadlocks item opened the top of the Blocking tab, with the Deadlocks grid below the fold. Each item now names the panel it brings into view (Active Queries, Blocking, Deadlocks), and once the router has built the tab a once-only hashchange listener scrolls the last panel with that title to the top: the Deadlocks chart and the Deadlocks grid share a title, and the grid is the later one. The listener is added after the range is taken, so a refused range leaves none behind.
…ostgreSQL opt-out, is removed (#5230) Most server-tab charts reach the chart menu through line() and fanout(), and the one PostgreSQL line chart opts out with atTime: false, but the scan counted only the nine direct zoomableLineChart calls. Deleting any of the three left every case passing. Two cases now pin the two hand-offs (server and item) and the opt-out of every PostgreSQL line().
erikdarlingdata
marked this pull request as ready for review
October 5, 2026 22:53
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #5230.
Why
The desktop viewer's Performance Trends charts have a right-click item. It jumps from a point on a chart to what was running then. The item is "Show Active Queries at This Time" on most charts, "Show Blocking at This Time" on the blocking charts and "Show Deadlocks at This Time" on the deadlock chart.
The web viewer's chart menu had Copy Image, Save Image As, Reset zoom, Export Data to CSV and Show Data Source. It had nothing that goes from a spike to the queries, blocking or deadlocks around it.
What changes
Each chart gets one item, as on the desktop. A right-click on the plot of a server-tab line chart adds the "at This Time" item that matches what the chart plots, after the usual items:
renderLineCharttakesatTime: { server, item }.line()andfanout()inpages/server-tabs.jshand the server over and read the item fromatTimeItem.panels.jspassesatTimethrough to the line chart. The nine charts that callzoomableLineChartdirectly pass the server and take the Active Queries default.The item uses the time of the drawn point nearest the click. A click a pixel beside a one-bucket spike on a 7-day chart therefore still opens the hour that holds the spike. The hover tooltip names the same point, because both now use one
nearestPointIdx. A click past either edge of the plot snaps to the first or last point.The item sets a custom range of one hour: the clicked time plus or minus 30 minutes. This is the shortest range that the range picker allows. A range cannot end in the future. Near now, the item therefore shifts the hour back to end at the current time. The hour still holds the clicked time. The chart's status line shows a range that the page refuses, and the tab does not change.
The page rebuilds through the router.
applyCustomRangegains{ redraw: false }. The item applies the range without a panel redraw. Then it sets the hash (#/server/<name>/queriesor/blocking, with the server name URL-encoded), or raiseshashchangeitself when that tab is already open. A full render makes the range picker in the page head show the new range. A panel redraw does not.The item's own grid scrolls into view. Once the router builds the tab, a once-only
hashchangelistener runs. It scrolls the last panel with the item's title (Active Queries, Blocking or Deadlocks) to the top of the view. The Blocking tab has a Deadlocks chart and, below it, a Deadlocks grid. Show Deadlocks at This Time lands on the grid. The item adds the listener only after the page takes the range, so a refused range leaves none behind.The item appears only on a right-click on the plot. A menu opened any other way has no clicked time and offers no item. The other ways include the chart menu button, Shift+F10, and a right-click on the legend, the status line or the open menu. A menu held open across the 60-second page refresh keeps its clicked time.
Some charts get no item. The PostgreSQL Aurora CPU chart passes
atTime: false, because the PostgreSQL page has no Queries or Blocking tab. The FinOps and Custom Views charts are unchanged.WebChartAtTimeBehaviourTestsand its Node harnessweb-chart-at-time-harness.mjsare new.This change touches web JavaScript and tests only. It has no server code, read or MCP tool changes.
Test plan
WebChartAtTimeBehaviourTests: 26 cases, 0 failed. The cases run the shippedcharts.jsunder Node. The harness copies every module underjs/andjs/pages/, so a new page module needs no list edit. The cases also scanserver-tabs.js,panels.jsandcharts.jsfor the hand-offs. They cover:atTime, from the chart menu button, or from the legend, status line, button or open menu. A held-open menu keeps its time.line()andfanout()hand-offs (server and item).line()opting out.once, or is added before the range check.line()hand-off, thefanout()hand-off or the Aurora opt-out is removed. Before these cases, removing any of these three failed nothing.BaselineDiscontinuityRenderCensusTests(Lite, scansserver-tabs.js): 24 cases, 0 failed.Darling.TestsandLite.Testsbuild with 0 warnings after mergingdev.