Skip to content

Scheduler issues read the utilization fields the event carries, flagged the way sp_HealthParser flags them (#4452) - #4456

Merged
erikdarlingdata merged 6 commits into
devfrom
fix/4452-scheduler-monitor-mirrors-sp-healthparser
Sep 27, 2026
Merged

erikdarlingdata merged 6 commits into
devfrom
fix/4452-scheduler-monitor-mirrors-sp-healthparser

Conversation

@erikdarlingdata

@erikdarlingdata erikdarlingdata commented Sep 27, 2026 •

Copy link
Copy Markdown
Owner

Refs #4452.

Why

The get_health_parser_scheduler_issues tool (Darling and Lite) read scheduler_monitor_system_health_ring_buffer_recorded events by the wrong column set: scheduler/CPU IDs and online/runnable/running state, none of which the event actually carries. sp_HealthParser flags this event by SQL CPU percent, other-process CPU percent, idle percent, memory utilization percent, page faults, and working-set delta — the tool never surfaced any of that, and its significance gate matched nothing real.

What changes

  • PerformanceMonitor.Common/SystemHealthModels.cs: SchedulerIssueRecord now carries EventTime, SqlCpuUtilization, OtherProcessCpu, SystemIdle, MemoryUtilization, PageFaults, WorkingSetDeltaMb.
  • PerformanceMonitor.Common/SystemHealthParser.cs: ParseSchedulerIssue reads process_utilization / system_idle / memory_utilization / page_faults / working_set_delta off the event's own data[@name]/value elements. Working-set bytes convert to MB the same way the stored procedure does (divide by 1,048,576, round to 2 places, away from zero).
  • PerformanceMonitor.Common/SystemHealthSignificance.cs: IsSignificant mirrors sp_HealthParser's own warning predicate — SQL CPU at or above 90, other-process CPU at or above 50, or memory utilization at or below 50. Null comparisons are false.
  • Darling DarlingMcpHealthParserTools.GetSchedulerIssues: description, served columns, and empty-result message updated to the new fields. Its tools/list budget line and McpToolGuideHeads.HealthParser gate text updated to match, with the total-bytes ceiling raised by the measured amount (never guessed).
  • Lite McpHealthParserTools.GetSchedulerIssues and LocalDataService.SystemEvents.cs: same field set; the description and gate text now match Darling's, keeping both SKUs byte-identical on the served head (checked by McpToolGuideTests).
  • ViewerDataService.SystemEvents.cs / ViewerServerTab.xaml (Darling) and the Lite twin: grid columns and the no-data message follow the new fields.
  • The deprecated/Dashboard project has its own scheduler-issue model and never calls the shared SystemHealthParser; confirmed by grep and left untouched.
  • Fixtures: real captured scheduler_monitor_high_sql_cpu.xml (SQL CPU 94, over the significant threshold) and scheduler_monitor_normal.xml (all three arms comfortably under threshold) replace the old hand-written fixture, call_stack removed. scheduler_monitor_other_process_cpu.xml and scheduler_monitor_low_memory.xml are derived from the normal capture with only the relevant value changed, because no real capture crossed those two thresholds; each file's comment states which and why.
  • All UTC handling is unchanged: the event timestamp continues to be parsed and stored as UTC, converted to local time only at render, same as the rest of the system_health family.

Fixtures table

Fixture Source Notes
scheduler_monitor_high_sql_cpu.xml Real capture SQL CPU 94 ≥ 90 → significant
scheduler_monitor_normal.xml Real capture All arms under threshold → not significant
scheduler_monitor_other_process_cpu.xml Derived from normal Other-process CPU raised past 50; no real capture crossed this arm
scheduler_monitor_low_memory.xml Derived from normal Memory utilization lowered to 50 or below; no real capture crossed this arm

Test plan

  • dotnet build for both Darling.Tests and Lite.Tests with -p:EnableWindowsTargeting=true: 0 errors on both.
  • In-process on macOS (xunit v3 runner against the built Darling.Tests.dll): McpToolsListBudgetTests, McpToolGuideTests, McpToolGuideHeadsHealthParserTests, SystemHealthParserTests, DarlingMcpHealthParserToolsSurfaceAndSqlTests, ViewerSystemEventsTests, DocCommentHygieneTests, ViewerServerTabCapabilityPinTests — all green (209 total, 0 failed).
  • Live product-path pin (DarlingMcpHealthParserToolsLivePostgresTests.HealthParserTools_ReadPlantedEvents_AgainstDevPostgres), against a local Postgres/TimescaleDB container, plants the real high-CPU fixture through system_health_events and calls DarlingMcpHealthParserTools.GetSchedulerIssues directly (the tool's own call path, not a manual parse): passed, asserting the served JSON text carries sql_cpu_utilization:94, other_process_cpu:4, system_idle:2, memory_utilization:100.
  • RED on origin/dev @ 89831e931cb5b38e0ee1a7c58ffaa90c85aa3ff3 at runtime: Darling.Tests Total: 1, Errors: 0, Failed: 1, Skipped: 0, Not Run: 0; System.Collections.Generic.KeyNotFoundException : The given key was not present in the dictionary at JsonElement.GetProperty("server") inside the envelope assertion helper — because dev's significance check still keys off the old Status == "WARNING" text field, the high-CPU fixture (which carries no status) never qualifies as significant, so GetSchedulerIssues answers the healthy-empty envelope instead of the issues envelope and the test never reaches the sql_cpu_utilization assertion. The live fact was cut down to just the DarlingMcpHealthParserToolsLivePostgresTests class and its one changed fixture (scheduler_monitor_high_sql_cpu.xml); the sibling DarlingMcpHealthParserToolsSurfaceAndSqlTests class and its SchedulerIssueRecord-typed-property assertions were left out because those members don't exist on dev at all and porting them isn't in scope for this pin.
  • Mutation: swapped process_utilization for system_idle in ParseSchedulerIssue, rebuilt, and re-ran SystemHealthParserTests. Four tests failed, e.g. SchedulerIssue_ShredsEveryColumn_HighSqlCpu: Assert.Equal() Failure: Expected: 94, Actual: 2. Reverted, rebuilt, re-ran: all 39 tests in that class green again.
  • Total lines from the tests actually run: 209 (McpToolsListBudgetTests + McpToolGuideTests + McpToolGuideHeadsHealthParserTests + SystemHealthParserTests + DarlingMcpHealthParserToolsSurfaceAndSqlTests + ViewerSystemEventsTests + DocCommentHygieneTests + ViewerServerTabCapabilityPinTests), 0 failed; plus the live product-path test (1 total, 0 failed) run separately against the Postgres rig.
  • Lite.Tests build only (0 errors); it can't run in-process on macOS — CI decides it.

CHANGELOG entry

SECTION: Changed
ENTRY:

@erikdarlingdata
erikdarlingdata marked this pull request as ready for review September 27, 2026 01:11
@erikdarlingdata
erikdarlingdata merged commit 6bbc18b into dev Sep 27, 2026
15 of 16 checks passed
@erikdarlingdata
erikdarlingdata deleted the fix/4452-scheduler-monitor-mirrors-sp-healthparser branch September 27, 2026 01:11
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