Repository navigation
Plan analysis: per-rule disable and severity overrides from darling.json and Lite's settings (#4535) - #4602
Merged
Conversation
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.
…ng framework as legacy (#4566)
…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.
…5-analyzer-config
…5-analyzer-config
#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.
…Lite's settings (#4535)
…ins, and fix the Lite sample's trailing comma
The MCP host built its DarlingAnalysisService with no analyzerConfig argument, so get_analysis_facts, analyze_server and drill-down plan advisories silently fell back to AnalyzerConfig.Default while the scheduled worker pass and the web endpoints already honored a user's disabled or overridden rules from darling.json. Same fix as those two: pass the config instance the host already resolved for its own DI registration. A source census pins that every production construction site of DarlingAnalysisService carries an analyzer-config argument; it is RED against the pre-fix code at the MCP host's line and GREEN here.
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 #4535. #4585 is merged; this is now against dev. Part of #4511.
What changes
The per-rule analyzer configuration ported in #4585 (
AnalyzerConfig,PlanAnalyzer's disable/severity-override checks) now actually loads from each host's own settings file, so the config takes effect instead of always defaulting.PerformanceMonitor.PlanAnalysis/ConfigLoader.cs:Parse(json)andLoadFile(path), ported from erikdarlingdata/PerformanceStudio'sConfigLoader. A malformed or missing file/section returnsAnalyzerConfig.Defaultrather than throwing. No auto-discovery of~/.planview.json— each host resolves its own file path and hands the section text toParse."analyzer": { "rules": { "disabled": [...], "severity_overrides": {...} } }section indarling.json, bound ontoDarlingConfig.Analyzer. Threaded into both drill-down collectors, the MCP plan tools (DarlingMcpPlanTools, via a DI-registeredAnalyzerConfigsingleton — see the MCP-schema note below), andMcpPlanAnalysisFormatter.BuildAnalysisResult's new config-aware overload. Also threaded into the MCP host's ownDarlingAnalysisServiceconstruction (DarlingMcpHostService.cs) — that call was still passing no analyzer config, soget_analysis_facts/analyze_server/drill-down plan advisories over MCP silently usedAnalyzerConfig.Defaultwhile the scheduled worker pass and the web endpoints already honored a user's overrides on the same install. Now passes the sameconfig.Analyzer ?? AnalyzerConfig.Defaultinstance the host already resolved for its DI registration.darling.json(ViewerSettings.AnalyzerConfig) and setsPlanViewerControl.AnalyzerConfig, a new propertyLoadPlanpasses intoPlanAnalysisPipeline.Run."analyzer"key fromsettings.json(App.AnalyzerConfig) with the same JSON shape, and passes it to Lite's drill-down collector and MCP plan tools the same way.Lite/config/settings.sample.jsonandDarling/PerformanceMonitor.Darling.Service/darling.sample.json—"analyzer": { "rules": { "disabled": [20], "severity_overrides": { "5": "Low" } } }hides the Local Variables finding (rule 20) and downgrades rule 5's severity to Low.MCP schema check
DarlingMcpPlanTools' four tools takeAnalyzerConfig? analyzerConfig = nullas a method parameter, resolved from DI the same wayNpgsqlDataSourcealready is (no[Description]attribute).DarlingMcpPlanToolsSurfaceAndSqlTests.AdvertisedSchema_*builds the actualtools/listschema through the sameWithGeminiCompatibleToolspath Program wiring uses and asserts the required/optional parameter sets —analyzerConfigdoes not appear in any tool's schema, confirmed by those tests passing. Lite's tools read a staticApp.AnalyzerConfigdirectly rather than taking it as a parameter, so there's no schema exposure there either.Fixes found while wiring this up
DarlingMcpHostService.csregisteredAnalyzerConfigvia the untypedAddSingleton(instance)overload, whichMcpServiceParameterDiSeatCensusTestsrequires to be the typed-genericAddSingleton<T>form (the same census Store host visibility: a cross-platform host profile, a --check-settings verb, and a get_store_host read, so "is this store sized right" has an answer without shell access #4214's round-1 review added forPostgresConfig/StoreHostProfileCache). Switched toAddSingleton<AnalyzerConfig>and addedAnalyzerConfigto the census's pinned five-type list (now six).Lite/App.xaml.csinserted the newAnalyzerConfigproperty between an existing/// <summary>doc comment and its member (DefaultTimeRangeHours), stacking two doc blocks on one member — the classic failure the plan-sync guidance calls out. Reordered so each property keeps its own doc comment.DarlingMcpHostService.cs:526) passed no analyzer config, so MCP's plan advisories disagreed with the worker and web endpoints on the same install. Fixed by passingconfig.Analyzer ?? AnalyzerConfig.Default, same as the DI registration two lines above it.DrillDownCollector.Plans.cs,DuckDbFactCollector.QueryPerf.cs) reads the staticApp.AnalyzerConfigdirectly rather than taking a constructor/DI parameter, soAnalysisService's constructor sites (RecommendationsTab.xaml.cs:232,Mcp/McpHostService.cs:73,Services/CollectionBackgroundService.cs:663) have nothing to thread — Lite was never affected by this gap.Test plan
Built Release with
-p:EnableWindowsTargeting=true:Darling.Tests,Lite/PerformanceMonitorLite.csproj,Lite.Tests,PerformanceMonitor.Ui,Darling/PerformanceMonitor.Darling.Service, the Darling Viewer,deprecated/Dashboard.Tests— all 0 warnings / 0 errors.Ran in-process on macOS (
Darling.Tests.dll,Microsoft.WindowsDesktop.Appstripped from the runtimeconfig): the newPlanSync4535ConfigLoadingTests(12 pins:ConfigLoader.Parse/LoadFileround-trip and fallback, thedarling.json"analyzer" section binding, the end-to-end MCP formatter path with a disabled rule and a severity override, the viewer's helper seam reachingPlanAnalysisPipeline.Run), every otherPlanSync4535*class,BenefitScorerWiringTests, the plan-sync consumer classes, the census family (CommentFilterAdoptionTests,DocCommentHygieneTests,McpPayloadContractCensusTests,McpToolsListBudgetTests, every*Census*class) — 604 total, 0 failed, 3 skipped (live-Postgres gated, expected withoutDARLING_TEST_PG).RED confirmed against
6fb64ded2(theplan-sync/4535-analyzer-confighead, in a detached worktree): the new test file fails to compile there —ConfigLoaderdoesn't exist,DarlingConfig.Analyzerdoesn't exist, andBuildAnalysisResulthas no 6-argument overload. Compile-only RED, labelled.The MCP host fix added
PlanSync4602AnalysisServiceConfigCensusTests, a source census that asserts every productionnew DarlingAnalysisService(call carries an analyzer-config argument. Run against4dc30e743(this branch's own prior head, in a detached worktree) it failed at runtime with one message:Darling/PerformanceMonitor.Darling.Service/Mcp/DarlingMcpHostService.cs: 'new DarlingAnalysisService(postgres, planFetcher, _logger, _baselineCache)' has no analyzer-config argument — MCP's #4602 gap.GREEN after the fix, along with the updatedSharedBaselineCacheTestspin on the same construction line. Re-ran the full shared plan-sync test list plus the census family after merging dev (c650606fe) into the branch: 350 total, 0 failed, 1 skipped (live-Postgres gated).Darling.Tests/Lite.Testsbuilds both 0 warnings/0 errors.Plus one runtime mutation: forced
PlanAnalyzer.TryOverrideSeverity'soverrideSeveritylocal to always benull, ranBuildAnalysisResult_SeverityOverride_ChangesReportedSeverity— failed (Expected: "Info", Actual: "Warning") — then reverted; the class is back to its committed content (confirmed viagit diff, no residual change).Lite.Testsbuilds (0 errors) but does not run on macOS (discovery dies on WindowsBase); CI decides it. No live-Postgres pins were added by this branch beyond the three already-gated classes in the shared test list.CHANGELOG
SECTION: Added
ENTRY: - Per-rule plan analyzer overrides ([#4602]) -
darling.json's (Darling) andsettings.json's (Lite) new optionalanalyzersection can disable a specific plan-analysis rule or override its severity, e.g."analyzer": { "rules": { "disabled": [20] } }hides Local Variables findings. Applies to the MCP plan tools, the drill-down views, and the plan viewer window.REF: [#4602]: #4602