Skip to content

Plan viewer: add a Parameters card to the Plan Insights strip - #4604

Merged
erikdarlingdata merged 3 commits into
devfrom
viewer/4598-parameters-card
Sep 28, 2026
Merged

erikdarlingdata merged 3 commits into
devfrom
viewer/4598-parameters-card

Conversation

@erikdarlingdata

@erikdarlingdata erikdarlingdata commented Sep 28, 2026 •

Copy link
Copy Markdown
Owner

Fixes #4598. Builds on #4599 (merge it first). Part of #4511.

Why

PerformanceStudio desktop's Plan Insights strip has a Parameters card (erikdarlingdata/PerformanceStudio@85492a1, src/PlanViewer.App/Controls/PlanViewerControl.Parameters.cs) that lists a plan statement's parameters with their compiled and runtime values, and flags a runtime value that looks sniffed. PM's viewer had no equivalent; PM's PlanStatement.Parameters already carried the data (name, data type, compiled value, runtime value), so nothing needed to change in the parser.

What changes

  • New pure PerformanceMonitor.PlanAnalysis.ParameterCard: header text, which value columns to show (Compiled/Runtime are dropped when no parameter carries them, matching PerformanceStudio's grid), one parameter's row text and its sniffed flag, the annotation lines (OPTIMIZE FOR UNKNOWN vs. OPTION(RECOMPILE) when every compiled value is null, unresolved local variables), and the unresolved-variable scan (excludes extracted parameters and table-variable names read from the plan tree).
  • PlanAnalyzer.MaskCommentsAndLiterals (Rules that read the query text count hints and keywords inside comments and string literals #4524) is now public so the card's OPTIMIZE FOR UNKNOWN check can read the masked statement text — a hint spelled inside a comment or string literal doesn't count, per [BUG] OPTIMIZE FOR UNKNOWN rule 27 treats string literals and comments as query hints PerformanceStudio#579.
  • PlanViewerControl.Properties.cs: new ShowParameters, wired into RenderStatement alongside the existing insight cards. It only builds the grid and calls the pure helper for every decision.
  • PlanViewerControl.xaml: new fourth insight-strip column for the card, placed between Missing Indexes and Wait Stats (PerformanceStudio's order: Runtime Summary, Missing Indexes, Parameters, Wait Stats — PM has no Server Context card yet, so that slot is simply absent).
  • New InsightParamsBrush theme token (green, matching PerformanceStudio's #7BCF7B/#2E7D32) in all three themes, for both the Darling Viewer and Lite (shared control).

Lite: gets this too (shared control, same XAML/code-behind).

Not ported

  • PerformanceStudio's Server Context card, which sits first in its strip: Plan viewer: PerformanceStudio's Server Context insight card #4597.
  • PerformanceStudio's grid falls back to a bare "Value" column when neither Compiled nor Runtime is present. PM's ParameterCard.Columns keeps that branch's flags for parity, but it can't actually arise from PM's model today (a statement with zero parameters is the separate "no parameters" empty state, not a parameter list where every column is null); noted in the helper's doc comment.

Test plan

  • New pure helper PerformanceMonitor.PlanAnalysis.ParameterCard, pinned by Darling/Darling.Tests/Viewer4598Tests.cs (20 facts): header text, column-drop flags (both present / runtime absent / compiled-all-null "Value" fallback), sniffed flag (present+differ / present+match / either missing), compiled-text "?" vs. "" distinction, annotations (none / local variables / OPTIMIZE FOR UNKNOWN via masked text / OPTIMIZE FOR UNKNOWN mentioned only inside a masked comment falling through to OPTION(RECOMPILE) / unresolved variables appended after), and FindUnresolvedVariables (extracted-parameter and table-variable exclusion, de-duplication, empty input, and a pin for the inherited @\w+-regex quirk where a @@ system variable is captured as @ROWCOUNT rather than skipped — this matches PerformanceStudio's own behaviour, not an idealised one).
  • RED: git worktree add --detach at pre-fix sha 898db2ba2, copied the new test file in — compile failure (ParameterCard doesn't exist), confirming the RED is real.
  • Mutation: flipped the Sniffed comparison from != to == in ParameterCard.Row; Row_FlagsSniffed_WhenRuntimeDiffersFromCompiled and Row_DoesNotFlagSniffed_WhenRuntimeMatchesCompiled both failed. Reverted; rebuilt; all 20 facts pass.
  • Ran on this rig (in-process, Darling.Tests.dll, Microsoft.WindowsDesktop.App stripped from the runtimeconfig): Viewer4598Tests, Viewer4573Tests, every *Census* class, CommentFilterAdoptionTests, DocCommentHygieneTests, McpToolsListBudgetTests, and the viewer regression classes (ShowPlanParserCondAndMultiplePlanTests, ActualPlanRequestTests, ActualPlanDispatchTests, ActualPlanResultParseTests, QueryModificationDetectorTests, ActualPlanCaptureLoopTests, ActualPlanGatingTests, ReproScriptBuilderHardeningTests, DarlingAnalysisPipelineTests, DarlingMcpPlanToolsSurfaceAndSqlTests, DarlingMcpPlanToolsLivePostgresTests, McpPlanAnalysisEnvelopeTests, SerialLoopStoreSizeSourceTests, TsqlConventionGuardTests). Total across both runs: 605 passed, 0 failed, 3 skipped (live-Postgres tests that need a Postgres test server).
  • Builds clean (0 warnings, 0 errors) for Darling.Tests, PerformanceMonitor.PlanAnalysis, PerformanceMonitor.Ui, Lite/PerformanceMonitorLite.csproj, and Darling/PerformanceMonitor.Darling.Viewer, all with -p:EnableWindowsTargeting=true.
  • Lite.Tests: no change here; no Lite.Tests class asserts this card, and CI builds it.
  • Screenshot plan: open a captured plan with parameters (e.g. any actual plan with a parameterized statement) in both the Darling Viewer and Lite. In the Plan Insights strip, between "Missing Index Suggestions" and "Wait Stats", a new "Parameters" card should show: header "Parameters (N)"; a grid with Parameter/Data Type columns always, and Compiled/Runtime columns only when at least one parameter carries that value; any runtime value that differs from its compiled value shown in the warning (amber/gold) colour with a tooltip; the card's 3px left accent edge and header text in the new green InsightParamsBrush tone when non-empty, dimmed/muted when there are no parameters and no local variables to report ("No parameters"). For a statement with OPTION(RECOMPILE) or OPTIMIZE FOR UNKNOWN and no parameters, the card should stay non-quiet and show the matching italic annotation line instead of "No parameters".

CHANGELOG

SECTION: Added
ENTRY: - Plan viewer: a Parameters card ([#4604]) - The Plan Insights strip now includes a Parameters card, listing each statement parameter's data type, compiled value and runtime value, and flagging a runtime value that differs from its compiled value as possible parameter sniffing.
REF: [#4604]: #4604

Ports PerformanceStudio dev's insights-strip card system
(erikdarlingdata/PerformanceStudio@87bad14) to the shared plan viewer used by
both the Darling Viewer and Lite. All three cards (Runtime Summary, Missing
Indexes, Wait Stats) now sit on the same neutral BackgroundLightBrush surface
with a 3px per-card accent edge (InsightIndexBrush, InsightWaitsBrush) instead
of a full-bleed tinted background. Runtime Summary keeps a blank edge as the
neutral centre.

A card with nothing to report now goes quiet: its header drops to the muted
foreground and its accent edge dims to 0.35, via a shared SetInsightQuiet
helper whose quiet/non-quiet values live in the new pure
PerformanceMonitor.PlanAnalysis.InsightCardStyle so they are testable outside
WPF.

No inline hex is left in the insight-card markup or code.
Ports PerformanceStudio dev's Parameters insight card
(erikdarlingdata/PerformanceStudio@85492a1) to the shared plan viewer used
by both the Darling Viewer and Lite. The card lists each parameter's name,
data type, compiled value and runtime value, tints a runtime value amber
when it differs from its compiled value (possible parameter sniffing),
and annotates the card when every compiled value is missing (OPTIMIZE FOR
UNKNOWN vs. OPTION(RECOMPILE), read from the masked statement text so a
hint spelled inside a comment or string literal doesn't count) or when
the statement text references a local variable with no matching
parameter.

The row/column/annotation logic lives in a new pure
PerformanceMonitor.PlanAnalysis.ParameterCard, pinned by
Darling.Tests/Viewer4598Tests.cs; the WPF code-behind (ShowParameters in
PlanViewerControl.Properties.cs) only builds and lays out the grid.

Adds InsightParamsBrush to all three themes for the card's accent edge
and header, matching PerformanceStudio's green tone.
…-card

# Conflicts:
#	Darling/PerformanceMonitor.Darling.Viewer/Themes/CoolBreezeTheme.xaml
#	Darling/PerformanceMonitor.Darling.Viewer/Themes/DarkTheme.xaml
#	Darling/PerformanceMonitor.Darling.Viewer/Themes/LightTheme.xaml
#	Lite/Themes/CoolBreezeTheme.xaml
#	Lite/Themes/DarkTheme.xaml
#	Lite/Themes/LightTheme.xaml
#	PerformanceMonitor.Ui/PlanViewerControl.Properties.cs
#	PerformanceMonitor.Ui/PlanViewerControl.Rendering.cs
#	PerformanceMonitor.Ui/PlanViewerControl.xaml
#	PerformanceMonitor.Ui/PlanViewerControl.xaml.cs
@erikdarlingdata
erikdarlingdata marked this pull request as ready for review September 28, 2026 16:38
@erikdarlingdata
erikdarlingdata merged commit 5aea3af into dev Sep 28, 2026
15 of 16 checks passed
@erikdarlingdata
erikdarlingdata deleted the viewer/4598-parameters-card branch September 28, 2026 16:38
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