Collector takes the 50 heaviest statements (CPU, last 24 h), fetches
statement plans as text (dm_exec_query_plan returns NULL for deeply
nested plans) and analyzes them in C#. Rules:
- SQLI-PLAN-001 implicit conversion preventing an index seek
- SQLI-PLAN-002 join without predicate (deliberate CROSS JOIN excluded)
- SQLI-PLAN-003 non-inlined scalar UDF in a heavy statement
- SQLI-PLAN-004 spills to tempdb, SQLI-PLAN-005 oversized memory grants
(2016 SP2+ / 2017 CU3+ columns, new capability)
Verified against real plans in SQL Server.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E3EExwndy8Z22EK2Qpt6BK
Collectors (SQL Server 2000+, version-specific SQL, least privilege):
server, configuration, trace flags, databases (settings, backups in UTC,
CHECKDB, VLFs, Query Store, files, tempdb), suspect pages, plan cache,
wait stats and file I/O as deltas with restart/clear detection,
performance counters, CPU from the scheduler monitor ring buffer,
blocking (sleeping head blockers with open transactions), and deadlocks
from system_health continuing from the last file offset.
Rules: configuration (memory, MAXDOP per Microsoft NUMA guidance, cost
threshold, ad hoc bloat, risky options, pending changes), databases
(state, settings, backups, log backups, CHECKDB, suspect pages, VLFs,
autogrowth, max size, Query Store, tempdb), waits (THREADPOOL, signal
waits, locks, I/O, WRITELOG, parallelism, PAGELATCH), I/O latency, CPU,
memory grants, blocking and deadlocks. Missing data makes a rule not
measurable with the collector's reason.
Integration tests run every collector as the least-privilege login and
reproduce real blocking and a real deadlock; green on 2017 and 2022.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E3EExwndy8Z22EK2Qpt6BK
- .NET 10 solution with Core, Connectivity, Rules, Contracts, Agent, Web and Hub
- Capability model gating collectors and rules by SQL Server version (2000 and later);
rules that cannot run are reported as not measurable, never as passed
- Connectivity via Microsoft.Data.SqlClient with ODBC fallback for legacy instances,
hardened monitoring session settings valid back to SQL Server 2000
- Support lifecycle rule (SQLI-VER-001) with lifecycle data shipped as a rule pack
- Version-aware least-privilege permissions script, verified by integration tests
against SQL Server in Docker (reads monitoring sources, cannot read customer data)
- Forgejo Actions CI, contributing guide, code of conduct, issue templates,
legacy version notes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E3EExwndy8Z22EK2Qpt6BK