Commit graph

8 commits

Author SHA1 Message Date
a01ec374a4 Review 1.2: keep SQL Server's error message out of the replication reason
When the distribution database could not be read, SQL Server's message
(which names the agent's login) was appended to Unavailable. That text is
the rules' "not measurable" reason and is returned unredacted by
/rule-states and /replication. It is now UnavailableDetail: shown on the
local instance page and [udeladt] in the API unless
ApiIncludesSensitiveEvidence. The agent list is also capped (TOP 500).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 11:33:25 +02:00
6cc65e3c75 Index usage over time and never-updated statistics (8g, F)
The index collector now sums index reads and writes between collections
across restarts of SQL Server (and of the agent, by seeding from the
stored snapshot) and keeps them per day in insight.IndexUsageDaily
(migration 0015, HourlyDays). SQLI-IDX-002 judges an index once it has
been followed for 7 days instead of needing 7 days of uptime.
GET /api/v1/instances/{name}/index-usage lists usage per index.

SQLI-STAT-001 also reports statistics that were never updated on tables
with rows; statistic rows now come from the table's heap or clustered
index, as a never-updated statistic has no row count of its own.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 10:55:22 +02:00
473a7d0be3 Replication from the distributor (8f)
On a distributor, a 15-minute collector reads each distribution agent's
latest run (status, latency, message) and replication errors the last
day from the distribution database. That needs SELECT on
MSdistribution_agents, MSdistribution_history and MSrepl_errors, which
the agent does not have by default (never the replicated commands);
without it SQLI-REPL-001 (agent failed/retrying, High) and SQLI-REPL-002
(latency > 5 min, Medium) are "not measurable" with the exact grant, and
"not relevant" elsewhere. Shown on the instance page and in
GET /api/v1/instances/{name}/replication. Tested against a real
distributor set up in the SQL 2022 container.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 10:48:46 +02:00
4d18d20ab0 tempdb and version store (8c)
A five-minute collector reads tempdb space (free, version store, user and
internal objects, whether files can grow), the 'Version Store Size (KB)'
counter, the sessions using most tempdb, the oldest snapshot transaction
and, only when the version store is large, the databases generating
versions. Trend and heavy sessions survive restarts; used space and the
version store become metrics with explanation and assessment.

Rules SQLI-TEMP-001 (version store > 1 GB or steadily growing),
SQLI-TEMP-002 (nearly full and cannot grow) and SQLI-TEMP-003 (session
above 1 GB for 15 minutes), configurable under SQLInsight:Tempdb.
"tempdb lige nu" on the instance page; GET /api/v1/instances/{name}/tempdb.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 10:42:38 +02:00
6f7839d011 Long and large transactions and long-running statements (8b, 8d)
A one-minute collector reads open user transactions (age, log bytes used
and reserved, database, session, login, program, statement) and user
requests running longer than the threshold, leaving out the agent's own
and system sessions, BACKUP/RESTORE/DBCC (long operations) and requests
waiting on purpose. Transactions open a minute or holding 100 MB are kept
in insight.LongTransactions (migration 0014, RawDays).

Rules SQLI-TRAN-001 (open > 10 min, High at 6x), SQLI-TRAN-002 (> 1 GB
log) and SQLI-REQ-001 (statement > 15 min), configurable under
SQLInsight:Activity. Shown "right now" on the instance page and in the
time window analysis and PDF; GET /api/v1/instances/{name}/activity and
the analysis JSON leave logins and statements out.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 10:36:41 +02:00
e6840e40d7 SQL Server error log without elevated rights (8a)
A five-minute collector reads important error log entries from the best
source the agent's rights allow: the error log itself (xp_readerrorlog,
only with securityadmin), the default trace's ErrorLog and Audit Login
Failed events (optional ALTER TRACE), or the exception and connectivity
ring buffers (VIEW SERVER STATE: numbers and severity, failed logins).
Repetitions are summed per error; the watermark is the newest entry
read, because the default trace is buffered. Stored in
insight.ErrorLogEvents (migration 0013, EventDays), resumed after restart.

Rules SQLI-LOG-001..006: corruption 823/824/825, I/O over 15 s (833),
severe errors (17+), login failure bursts (configurable), stack dumps and
AG errors; rules needing the log text are "not measurable" with the
right to grant. Page /instanser/{navn}/fejllog (menu Overvågning) and
GET /api/v1/instances/{name}/error-log with messages redacted.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 10:30:41 +02:00
0dc7866808 Separate "check by hand" from "not relevant" for version-gated rules
A rule whose topic applies but whose way of measuring needs a newer
version or patch now gives the new outcome ManualCheck with concrete
Danish guidance, instead of NotApplicable. It is marked explicitly per
rule (IRule.ManualCheck) and only used when every missing capability is
a measurement capability (InstanceCapabilities.IsMeasurement): CHECKDB
status (SQLI-DB-009), VLFs (SQLI-DB-011), spills and memory grants
(SQLI-PLAN-004/005) and deadlocks on 2005 (SQLI-DLK-001). Query Store,
AG and Azure-managed topics stay "not relevant".

Shown in a visible "Skal tjekkes manuelt" section on the instance page,
a KPI on the overview, a "Tjek manuelt" column in the management
report's controls, manualChecks in /api/v1/instances and manualCheck in
rule-states; not counted as not measurable.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 09:59:50 +02:00
30d89acbd7 API v1: findings, rules, reports and page data as JSON, with OpenAPI
- /api/v1/findings gains status (active/resolved/all), from/to, database,
  ruleId, category, sort and paging (limit + X-Continuation header; the
  response stays an array). /findings/{id} with fix script and history.
- /rules (built-in, community, local) and /instances/{name}/rule-states.
- /reports and /reports/{driftsrapport|analyse|rettigheder} as JSON or PDF,
  built from the same models as the pages and PDFs.
- Page data: analysis, top-sql, disks, configuration, privileges (one or
  all instances) and wait types. Statement texts, logins, names and
  service accounts are "[udeladt]" unless ApiIncludesSensitiveEvidence.
- OpenAPI at /api/v1/openapi.json; a test fails when an endpoint is
  missing from it.
- API tokens get scopes ("read", "support:write"); the old form is read
  only, and new-api-token takes --scope. Token names show as token:<name>.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 09:27:10 +02:00