Skip to content

Plan analysis: the store readers fill ServerMetadata's cost threshold, max server memory and database settings (#4597) - #4607

Merged
erikdarlingdata merged 29 commits into
devfrom
plan-sync/4597-server-context-fields
Sep 28, 2026
Merged

erikdarlingdata merged 29 commits into
devfrom
plan-sync/4597-server-context-fields

Conversation

@erikdarlingdata

@erikdarlingdata erikdarlingdata commented Sep 28, 2026 •

Copy link
Copy Markdown
Owner

Refs #4597. #4601 is merged; this is now against dev. Part of #4511.

What changes

ServerMetadata gains PerformanceStudio's DatabaseMetadata (name, compatibility level, collation, RCSI, the auto-stats flags, forced parameterization) and ScopedConfigItem shapes, plus a Database property. Both store readers — DarlingServerMetadataReader (Postgres) and Lite's LocalDataService.GetServerMetadataForPlanAnalysisAsync (DuckDB) — now also read cost threshold for parallelism and max server memory (MB) from the config history, and, when a database name is given, the newest database_config/v_database_config row for that database. A missing or absent database row leaves Database null rather than failing the read, the same non-fatal contract the existing edition/MAXDOP read already has.

The viewer's plan-opening entry points (ProcedureHistoryWindow, QueryStatsHistoryWindow, QueryStoreHistoryWindow, WaitDrillDownWindow, ViewerActualPlanFlow, ViewerServerTab.Plans, ViewerDataService) and the drill-down/MCP paths (PgDrillDownCollector.Plans, DarlingMcpPlanTools) now pass the database name through to the reader wherever the call site already has it (a plan opened from a database-scoped history window or drill-down); sites with no database context at hand (a pasted plan, a plan looked up by hash alone) still call the reader with no database name, same as before, and get everything except Database.

PerformanceStudio parity

PM fills every DatabaseMetadata member PS's live fetch fills from sys.databases, sourced from PM's collected database_config/v_database_config row instead of a live connection (Darling has no live session at these call sites — same reasoning the existing edition/MAXDOP read already documents). ScopedConfigItem/NonDefaultScopedConfigs is added to the model to keep the shape aligned with PS, but nothing populates it yet in this change; no reader queries database_scoped_config here. That's the remaining PS surface with no PM data behind it yet.

Test plan

  • dotnet build Darling/Darling.Tests/Darling.Tests.csproj -c Release -p:EnableWindowsTargeting=true: 0 warnings, 0 errors.
  • Live (own rig, TimescaleDB Postgres container): PlanSync4597ServerContextFieldsLiveTests, PlanSync4530ReaderLiveTests, PlanSync4530DrillDownLiveTests → 4/4/… all green, Total: 20 across those plus StorageCommandTimeoutTests, 0 failed.
  • Census family + StorageCommandTimeoutTests + LivePostgresCollectionHygieneTests + LiveCleanupConversionRatchetTests + DocCommentHygieneTests + CommentFilterAdoptionTests + McpPayloadContractCensusTests + McpToolsListBudgetTests: Total 204, Failed: 1 — LivePostgresCollectionHygieneTests.EveryClassUsingTheSharedStore_IsSerializedOrDocumentsWhyNot fails on this Mac only, with Could not load file or assembly 'PresentationFramework'; that's a WPF type load unavailable on macOS, not a regression (confirmed unrelated to this change by running it before and after).
  • RED: changed the new database_config predicate to database_name = 'red-mutation', rebuilt, reran PlanSync4597ServerContextFieldsLiveTests → Assert.NotNull() Failure: Value is null at the seeded-database assertion. Reverted, rebuilt, reran → green again (Total: 20, 0 failed).
  • StorageCommandTimeoutTests initially caught one real gap: the new database_config read's NpgsqlCommand had no explicit deadline. Fixed by setting CommandTimeout = StorageCommandDeadlines.McpReadSeconds (this reader serves the MCP plan tools and drill-downs, the same regime as the file's other MCP-facing reads).
  • Lite: dotnet build Lite/PerformanceMonitorLite.csproj, Lite.Tests/Lite.Tests.csproj, Darling/PerformanceMonitor.Darling.Viewer, Darling/PerformanceMonitor.Darling.Service (all -p:EnableWindowsTargeting=true) → 0 warnings, 0 errors on all four.
    • Added a source census in PlanSync4597ServerContextFieldsLiveTests confirming Lite's PlanServerMetadataSql names the same v_database_config columns Darling's database_config schema does.
    • Added Lite.Tests/PlanServerMetadataDatabaseArgTests.cs (a new file, not the sibling PlanServerMetadataReaderTests.cs, which Plan analysis: rule 38 reads the server's edition and MAXDOP at every entry point (#4530) #4601 also edits) with three build-only pins for the database argument, copying that file's SharedDuckDbFixture setup pattern and filling every NOT NULL column of server_properties and database_config. Can't run on macOS (Lite.Tests discovery dies on WindowsBase); CI decides them.
    • No ProjectReference or lock-file changes in this branch, so no dotnet restore --force-evaluate was needed.

CHANGELOG

SECTION: None
ENTRY: None: the fields feed the Server Context card (#4597), a separate PR

erikdarlingdata and others added 29 commits September 28, 2026 09:15
Ports PerformanceStudio's AnalyzerConfig/RulesConfig (disabled rules,
severity overrides) and the top-level ServerMetadata fields into
PerformanceMonitor.PlanAnalysis, adds PlanWarning.RuleNumber, and adds
Analyze/Run overloads that take (config, serverMetadata, cancellationToken)
and thread both down to the statement and node walks. The existing
overloads still forward to AnalyzerConfig.Default and a null metadata, and
no rule reads either new parameter yet, so analyzer output is unchanged.
…ing (#4535)

Ports erikdarlingdata/PerformanceStudio's severity-override pass: overrides now find a warning's rule via PlanWarning.RuleNumber instead of matching WarningType against a rule-to-name table, and the engine's own warnings (Source == SqlServer) are always skipped. Also ports PlanStatements.EnumerateAllWithContainer, with EnumerateAll delegating to it so the plain and container-carrying walks stay one walk.
#4535, #4566)

The plumbing step's RuleNumber_DefaultsToNull_UntilLaterStepsStampIt pinned the
state partway through the per-rule configuration rollout (only rule 3 stamped).
Every step that stamps a rule has landed on this branch, so that pin is wrong
by design now.

Replaces it with PlanSync4535RuleNumberCensusTests: a code census over every
new PlanWarning construction in PlanAnalyzer.cs (each must set RuleNumber,
except a SqlServer-sourced initializer), a runtime census over the existing
plan fixtures (every analyzer finding carries a non-null RuleNumber), and a
cross-step check that disabling every stamped rule number leaves zero analyzer
findings.
Adds three tests the earlier #4530 steps skipped:

- a live Postgres pin that seeds collect.server_properties and
  collect.server_config on a migrated store and asserts
  DarlingServerMetadataReader.ReadAsync returns the edition and MAXDOP,
  then runs the same plan XML through the analysis formatter and
  confirms rule 38 (Standard Edition DOP 2 limitation) gives its
  Warning, plus a no-rows case that stays on the Info branch;
- a drill-down pin: a PLAN_WARNING finding's drill-down surfaces the
  rule-38 Warning when PgDrillDownCollector runs against a seeded
  Standard Edition / MAXDOP 8 server;
- a Lite.Tests pin (build-only on macOS) for
  LocalDataService.GetServerMetadataForPlanAnalysisAsync against a
  seeded DuckDB fixture, plus a Darling.Tests source-census pin that
  the Lite reader's SQL names the same view and columns Darling's
  migrated schema and reader use.

Ported the reader's column-name RED by temporarily renaming the
FROM clause, confirming the new live pin fails, then reverting.
…and seed every required server_properties column in the Lite metadata test
…oints

# Conflicts:
#	PerformanceMonitor.Ui/PlanViewerControl.xaml.cs
…o plan-sync/4597-server-context-fields

# Conflicts:
#	Darling/PerformanceMonitor.Darling.Storage/DarlingServerMetadataReader.cs
@erikdarlingdata
erikdarlingdata marked this pull request as ready for review September 28, 2026 17:19
@erikdarlingdata
erikdarlingdata merged commit a4813da into dev Sep 28, 2026
17 of 18 checks passed
@erikdarlingdata
erikdarlingdata deleted the plan-sync/4597-server-context-fields branch September 28, 2026 17:19
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