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>
82 lines
4.2 KiB
Text
82 lines
4.2 KiB
Text
@page "/"
|
||
@inject InsightRepository Repository
|
||
@inject Display Display
|
||
|
||
<PageTitle>SQLInsight Pro</PageTitle>
|
||
|
||
<h1>Overblik</h1>
|
||
<p class="lead">Status for alle overvågede SQL Server-instanser.</p>
|
||
|
||
@if (_instances.Count == 0)
|
||
{
|
||
<div class="empty">
|
||
<p>Der er endnu ingen data. Tjek, at SQLInsight Agent kører og har instanser under <code>SQLInsight:Instances</code> i sin konfiguration.</p>
|
||
</div>
|
||
}
|
||
else
|
||
{
|
||
<PrivilegeAlert Findings="_active" ShowInstance="true" />
|
||
|
||
<div class="kpis">
|
||
<div class="kpi"><span class="kpi-icon"><Icon Name="servers" /></span><div><strong>@_instances.Count</strong><span>instanser</span></div></div>
|
||
<div class="kpi sev-critical"><span class="kpi-icon"><Icon Name="alert" /></span><div><strong>@_instances.Sum(i => i.Critical)</strong><span>kritiske fund</span></div></div>
|
||
<div class="kpi sev-high"><span class="kpi-icon"><Icon Name="alert" /></span><div><strong>@_instances.Sum(i => i.High)</strong><span>høje fund</span></div></div>
|
||
<div class="kpi sev-info"><span class="kpi-icon"><Icon Name="unplug" /></span><div><strong>@_instances.Count(i => i.IsFailing)</strong><span>kan ikke nås</span></div></div>
|
||
<div class="kpi sev-info"><span class="kpi-icon"><Icon Name="gauge" /></span><div><strong>@_instances.Sum(i => i.NotMeasurable)</strong><span>regler ikke målbare</span></div></div>
|
||
<div class="kpi sev-info"><span class="kpi-icon"><Icon Name="list" /></span><div><strong>@_instances.Sum(i => i.ManualChecks)</strong><span>skal tjekkes manuelt</span></div></div>
|
||
</div>
|
||
|
||
<section class="card">
|
||
<div class="card-head"><h2>Instanser</h2><span class="muted">sorteret efter alvor</span></div>
|
||
<table class="instances">
|
||
<thead>
|
||
<tr><th>Status</th><th>Instans</th><th>Version</th><th>Fund</th><th>Ikke målbar</th><th>Sidst set</th></tr>
|
||
</thead>
|
||
<tbody>
|
||
@foreach (var i in _instances.OrderByDescending(i => i.IsFailing).ThenByDescending(i => i.WorstSeverity ?? (Severity)(-1)).ThenBy(i => i.Name))
|
||
{
|
||
<tr>
|
||
<td>
|
||
@if (i.IsFailing)
|
||
{
|
||
<span class="badge sev-critical" title="@i.LastError">Fejler</span>
|
||
}
|
||
else
|
||
{
|
||
<SeverityBadge Severity="i.WorstSeverity" />
|
||
}
|
||
</td>
|
||
<td><a href="/instanser/@Uri.EscapeDataString(i.Name)"><strong>@i.Name</strong></a><div class="muted">@i.ServerName</div></td>
|
||
<td>@(i.ProductVersion is null ? "–" : Display.Release(i.ProductVersion, i.EngineEdition))<div class="muted">@i.ProductVersion @i.ProductLevel @i.ProductUpdateLevel</div></td>
|
||
<td><div class="counts">
|
||
@if (i.Critical > 0) { <SeverityBadge Severity="Severity.Critical" Count="i.Critical" /> }
|
||
@if (i.High > 0) { <SeverityBadge Severity="Severity.High" Count="i.High" /> }
|
||
@if (i.Medium > 0) { <SeverityBadge Severity="Severity.Medium" Count="i.Medium" /> }
|
||
@if (i.Low > 0) { <SeverityBadge Severity="Severity.Low" Count="i.Low" /> }
|
||
</div></td>
|
||
<td>@i.NotMeasurable</td>
|
||
<td title="@Display.Time(i.LastSeenAt)">@Display.Ago(i.LastSeenAt)</td>
|
||
</tr>
|
||
}
|
||
</tbody>
|
||
</table>
|
||
</section>
|
||
|
||
<section class="card">
|
||
<div class="card-head"><h2>Kritiske og høje fund</h2><a href="/fund">Se alle fund</a></div>
|
||
<FindingList Findings="_urgent" ShowInstance="true" Empty="Ingen kritiske eller høje fund." />
|
||
</section>
|
||
}
|
||
|
||
@code {
|
||
private IReadOnlyList<InstanceOverview> _instances = [];
|
||
private IReadOnlyList<StoredFinding> _active = [];
|
||
private IReadOnlyList<StoredFinding> _urgent = [];
|
||
|
||
protected override async Task OnInitializedAsync()
|
||
{
|
||
_instances = await Repository.GetInstancesAsync();
|
||
_active = await Repository.GetActiveFindingsAsync();
|
||
_urgent = _active.Where(f => f.Severity >= Severity.High).ToList();
|
||
}
|
||
}
|