Skip to content

Keep Viewer charts and grids readable at 1366x768 (#6652) - #6674

Merged
erikdarlingdata merged 3 commits into
devfrom
fix/6652-viewer-small-screen
Oct 23, 2026
Merged

erikdarlingdata merged 3 commits into
devfrom
fix/6652-viewer-small-screen

Conversation

@erikdarlingdata

@erikdarlingdata erikdarlingdata commented Oct 23, 2026 •

Copy link
Copy Markdown
Owner

Claude posting for Erik Darling.

Closes #6652.

Why

At 1366x768 the Viewer's stacked charts got a plot a few pixels tall (only a "0" tick), long left-axis titles were cut at both ends so the unit was lost, and two wide grids (Query Store Regressions, Collection Health) showed fixed-width columns squeezed to slivers.

Diagnosis on the grids: every column already had a fixed Width, but WPF's DataGrid takes width away from fixed columns (down to their default MinWidth of about 20 px) to satisfy a star column's minimum when the total does not fit. Regressions had a star Query Text column with MinWidth=300; Collection Health has two star columns. That is the "10 px each" the issue shows.

What changes

  • Charts, minimum height and scrolling. Blocking Trends, tempdb, File I/O Latency, Queries Performance Trends and the Overview lanes: each chart row has MinHeight from one shared constant (ChartLayout.MinPlotHeight, 150), and the chart grid sits in a vertical ScrollViewer. The grid height is bound to the viewport, so on a tall window the charts still stretch to fill it, and on a short one the tab scrolls. The mouse wheel over a plot stays that plot's zoom (ChartLayout.KeepWheelOnPlot); the scroll bar and the margins scroll the tab.
  • Axis titles, once, in ChartStyle (shared with Lite, so Lite gains it too). ChartAxisTitle.Fit shrinks the font (12 down to 9) and then trims the name keeping a short unit last; it runs before every render for charts that use ApplyThemeToChart, so all ~50 titles are covered. Also shortened the named ones at their call sites: "Lock wait ms/s", "Blocking events", "tempdb latency ms", "Duration ms/s" (Deadlocks and Read/Write Latency (ms) were already short enough).
  • At least two y ticks. MinimumTickGenerator wraps the automatic numeric ticks and adds the low and high end of the axis when fewer than two labelled ticks fall in range (all-zero data is 0..1 plus padding). Applied by ApplyThemeToChart and ApplyMinimalChartTheme unless a caller already set its own y tick generator.
  • Regressions grid. Query Text is Width=320 (not star, MinWidth=200), every fixed column has MinWidth equal to its width (so nothing can be taken away), headers wrap (DockPanel + TextWrapping), horizontal scroll was already Auto.
  • Collection Health. Same MinWidth on every column (the two star columns get MinWidth=160) and wrapping headers.
  • One pin in ViewerBlockingSourceLabelTests that spelled the old "Blocking Incidents" call site was updated to the new title.

Proof

  • Unit tests on the pure helpers, plus a run of the Viewer on a seeded throwaway store at 1366x768 and a larger window (next section).
  • Unit tests (ViewerShortPlotTests): every long title fits the minimum row and keeps its unit; short titles are untouched; all-zero axis and only-"0" axis get two ticks; enough ticks are returned untouched; the min-height constant is in range.

Seen at 1366x768 and 1920x1080

I ran the Viewer (Release build of this branch) against a throwaway PostgreSQL store seeded by tools/ui-smoke/run-ui-smoke.ps1 -SeedOnly, with DARLING_CONFIG set to that store's config in the Viewer's own process only (its server list showed the seed's ui-sql and ui-pg). I sized the window and captured it (PrintWindow) at each view. The PNGs are in the lane scratchpad wave-312\shots-6674\ and are not committed. The laptop panel is 3840x2400 at 250 percent, so I sized the windows in device-independent pixels (1366x768 DIPs = 3415x1920 physical): the layout is the one a 100 percent 1366x768 screen gets. Windows would not make a window bigger than the panel, so the large size is 1549x925 DIPs (3872x2312 physical), not a true 1920x1080. The layout is bound to the viewport, so it shows the same behaviour with more room. The 1366x768 window is the whole outer window (title bar included), a little taller than the usable area of a screen with a taskbar.

At 1366x768, before any change:

  • Overview lanes: every lane has a visible plot with y labels; the lane grid scrolls (vertical bar only, no horizontal bar).
  • Blocking Trends: three charts with visible plots and at least two y labels; the titles "Lock wait ms/s", "Blocking events (blocked-process-report)" and "Deadlocks" are whole and unclipped (the long one shrinks); the page scrolls to the last chart and its legend.
  • tempdb, File I/O Latency: all charts fit at or above 150 DIPs; no scroll bar needed; axes labelled.
  • Queries Performance Trends: the 2x2 grid fits; the "No Data" charts keep their frame; titles whole.
  • Regressions and Collection Health: a defect. Headers broke mid-word because the column was narrower than its longest header word: "Severit / y" (Regressions), "Succes / s" and "Abando / ned" (Collection Health).
  • Scroll check: the scroll area reaches the bottom (1366x768-blocking-trends-scrolled-to-bottom.png). The mouse wheel over a plot zooms that plot (its x range shrank and y rescaled) and does not scroll the page (the scroll position stayed at 0 percent); the scroll bar and the margins scroll the page.
  • No layout loop: the window did not resize or flicker across tab changes.

Fix (commit 75f4eeb, ViewerServerTab.xaml, 3 lines): Regressions Severity 80 to 100; Collection Health Success 80 to 105 and Abandoned 90 to 120 (both Width and MinWidth). After: 1366x768-regressions-after.png and 1366x768-collection-health-after.png (plus ...-scrolled-right.png) show every header whole, wrapping only at spaces.

At 1549x925 (taken before the fix, so Regressions and Collection Health there still show the old widths): Blocking Trends fills the window with no scroll bar and no empty space; tempdb, File I/O Latency and Queries Performance Trends fill; the Overview lanes still scroll (six lanes at the 150 DIP minimum need more than 925 DIPs), which is the intended minimum height, not a defect. Toolbar fix in this PR: the four label-and-box pairs (Query tag, Compare, Auto-refresh interval, Times) now wrap together, so a label no longer ends one row while its box starts the next.

Not seen: the Regressions columns right of "Base Execs" (the seed has no regressions, so the grid shows its empty text and cannot scroll). Their widest header words ("Baseline", "Timeouts", "Timeouts/hr") are no wider than "Severity", which fits in 100.

Tests rerun after the fix: ViewerShortPlotTests, ViewerBlockingSourceLabelTests, *Census*, *Ratchet*, *Xaml* in Darling.Tests: 536 run, 0 failed, 1 skipped.

Test plan

  • Darling.Tests build, 0 errors; Lite.Tests build, 0 errors, 0 warnings
  • Darling: new class, the 8 Viewer classes naming the touched controls, *Ratchet*, *Census*, *Xaml*: 734 run, 0 failed, 1 skipped
  • Lite: *ChartStyle*, *ChartClickIsolateTests*, *Ratchet*, *Census*: 49 run, 0 failed
  • git merge-tree of this branch with the Make the Viewer match the web on dropped databases, labels, job history, wording and strip gaps (#6651) #6667 branch (fix/6651-viewer-parity) reports no conflicts
  • Visual check at 1366x768 of Blocking Trends, tempdb, File I/O Latency, Overview, Queries Performance Trends, Regressions, Collection Health (see "Seen at 1366x768 and 1920x1080"; Regressions columns past "Base Execs" not seen)
  • Not revert-proved: the helpers are new, so the tests cannot fail on the old code (they do not exist there). No full suite or pre-push.sh (CI decides).

Considered, not added

  • Wrapping a rotated title onto two lines: ScottPlot labels are single-line; shrink-then-trim covers the case.
  • Lite XAML (its charts live in a different layout); only the shared ChartStyle part reaches Lite.
  • A wheel-vs-scroll test: ScottPlot needs native Skia, which a plain test host cannot create; the handler is one line after ScottPlot's own.

CHANGELOG entry

SECTION: Fixed
ENTRY:

Toolbar label wrap (commit 503910a)

Each label and its box in the server tab toolbar is now one item in the WrapPanel, so the WrapPanel can no longer break the line between them. At 1549 px a label ended one row while its box started the next ("Compare:" and its "None" box).

What changed (one file, Darling/PerformanceMonitor.Darling.Viewer/ViewerServerTab.xaml): the four label-and-box pairs (Query tag, Compare, Auto-refresh with its interval, Times) are each wrapped in <StackPanel Orientation="Horizontal">. Attributes, names, handlers and comments are unchanged. git diff -w shows exactly 8 added lines (the four StackPanel open and close pairs). The rest of the diff re-indents the 33 wrapped lines (--numstat: 41 insertions, 33 deletions).

Test plan (this part)

  • dotnet build Darling/Darling.Tests/Darling.Tests.csproj -c Debug -m:1 -p:UseSharedCompilation=false: 0 errors, 8 warnings. The warnings are C# analyzer warnings (CA1870, CA2016, xUnit2031) in three files this XAML-only diff does not touch: ChangeWatchDetectionLiveTests.cs, DarlingMcpAlertTools.cs and MonitoringGrantScript.cs.
  • dotnet build Darling/PerformanceMonitor.Darling.Viewer/PerformanceMonitor.Darling.Viewer.csproj -c Debug -m:1 -p:UseSharedCompilation=false: 0 warnings, 0 errors, so the edited XAML compiles.
  • Darling.Tests.exe, one run with -class for ViewerShortPlotTests, ViewerBlockingSourceLabelTests, ServerTabToolbarAndTooltipsTests, *Xaml*, *Census* and *Ratchet*: Total 558, Errors 0, Failed 0, Skipped 1. The skip is WebExceptionTextCensusLiveTests.RealToolCaughtStatementTimeout_OnTheRig_Returns503_NoExceptionText_OneLogLine, a live test that needs the rig. *Ratchet* matched no class in Darling.Tests.
  • ServerTabToolbarAndTooltipsTests alone: 22 tests, 0 failed, 0 skipped.
  • The XAML is well-formed XML.
  • No test pins the server tab WrapPanel's children. The only WrapPanel references in Darling.Tests are in ViewerFleetRollupTests, which reads MainWindow.xaml. No test was changed.
  • Not run: the full suite and pre-push.sh (laptop run; CI decides), and the live tests (no rig started).
  • Not checked: the rendered toolbar at 1366x768 or 1920x1080.

For the coordinator

  • Visual check. The label TextBlocks keep VerticalAlignment="Center", which now centres each label within its pair's StackPanel. I did not check on screen whether that moves any label. A 1920x1080 look at the toolbar would settle it.
  • CHANGELOG. No buffer entry was written. The brief does not fill <CHANGELOG_BUFFER_DIR>, and CHANGELOG.md is not to be edited. The entry for Darling Viewer at 1366x768: stacked charts collapse to a sliver and the Query Store Regressions grid is unreadable #6652 is the coordinator's.
  • Lite. Lite/Controls/ServerTab.xaml has the same four labels (around lines 186-260), but its only WrapPanels are at lines 1519 and 1564, so its toolbar does not share this WrapPanel. I did not check its layout further, because the brief limits the edit to the Viewer file.
  • Considered, not added. Nothing beyond the four pairs. No code, test or hardening change.
  • Issues filed: none. The PR stays a draft.

Each label and its box (Query tag, Compare, Auto-refresh interval, Times) is now one horizontal StackPanel item in the server tab toolbar WrapPanel, so the WrapPanel can no longer break the line between a label and its box. Element attributes, names, handlers and comments are unchanged; the other diff lines are re-indentation of the wrapped pairs.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant