Review 1.2: say correctly what each error log source shows

The error log page called the default trace "the whole error log" and
said it has every line, and the ring buffer source told SQLI-LOG-002/005
to grant ALTER TRACE, which does not make 833 or stack dumps visible
(they are only in the error log itself). The rules now say that it takes
securityadmin, why SQLInsight does not grant it, and the exact statement.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Søren Eggert Lundsteen Olsen 2026-10-02 11:31:53 +02:00
parent 70934e7562
commit a256e4c8cc
4 changed files with 10 additions and 6 deletions

View file

@ -9,7 +9,7 @@ public enum ErrorLogSource
/// <summary>The error log itself (xp_readerrorlog): everything. Needs securityadmin, which the agent normally does not have.</summary>
ErrorLog,
/// <summary>The default trace's ErrorLog and Audit Login Failed events: every error log line. Needs ALTER TRACE (optional).</summary>
/// <summary>The default trace's ErrorLog and Audit Login Failed events: severe errors with text and failed logins, not 833 or stack dumps. Needs ALTER TRACE (optional).</summary>
DefaultTrace,
/// <summary>The exception ring buffer: error numbers and severity, no text. Needs only VIEW SERVER STATE.</summary>

View file

@ -31,7 +31,8 @@ public abstract class ErrorLogRule(ErrorLogCategory category, bool needsText) :
var snapshot = context.Data.Get<ErrorLogSnapshot>();
if (needsText && snapshot.Source != ErrorLogSource.ErrorLog)
{
throw new DataUnavailableException(snapshot.Coverage ?? ErrorLogCollectorText.Coverage);
// Not the snapshot's coverage text: that recommends ALTER TRACE, which does not make 833 or stack dumps visible.
throw new DataUnavailableException(ErrorLogCollectorText.NeedsErrorLog);
}
return Result(Relevant(snapshot).Select(g => CreateFinding(
@ -56,7 +57,10 @@ public abstract class ErrorLogRule(ErrorLogCategory category, bool needsText) :
internal static class ErrorLogCollectorText
{
public const string Coverage = "Fejlloggen kan ikke læses fuldt ud med agentens rettigheder. Giv agenten ALTER TRACE (valgfrit i grant-least-privilege.sql).";
public const string NeedsErrorLog =
"Langsom I/O (833) og stack dumps står kun i selve fejlloggen (xp_readerrorlog), som kræver serverrollen securityadmin; ALTER TRACE er ikke nok. "
+ "SQLInsight giver ikke agenten securityadmin som standard, fordi rollen kan tildele rettigheder. Ønskes det alligevel: "
+ "ALTER SERVER ROLE securityadmin ADD MEMBER [agentens login]; (SQL Server 2005-2008 R2: EXEC sp_addsrvrolemember N'agentens login', N'securityadmin';)";
}
public sealed class CorruptionErrorRule() : ErrorLogRule(ErrorLogCategory.Corruption, needsText: false)

View file

@ -59,7 +59,7 @@ else
<section class="card">
<details>
<summary>Hvad betyder det?</summary>
<p>SQL Servers fejllog er instansens dagbog. SQLInsight Pro læser den uden at have adgang til selve filen: med rettigheden ALTER TRACE (valgfri i grant-least-privilege.sql) via default trace, som har hver linje, og ellers kun fejlnumre fra SQL Servers exception ring buffer. Beskadigede sider (823/824/825) og I/O over 15 sekunder (833) peger næsten altid på storage og skal undersøges med det samme.</p>
<p>SQL Servers fejllog er instansens dagbog. SQLInsight Pro bruger den bedste kilde, agentens rettigheder giver: selve fejlloggen kun med serverrollen securityadmin (gives ikke som standard), med rettigheden ALTER TRACE (valgfri i grant-least-privilege.sql) default trace med alvorlige fejl og mislykkede logins, og ellers kun fejlnumre fra SQL Servers exception ring buffer. Langsom I/O (833) og stack dumps ses kun i selve fejlloggen. Beskadigede sider (823/824/825) og I/O over 15 sekunder (833) peger næsten altid på storage og skal undersøges med det samme.</p>
</details>
</section>
@ -88,7 +88,7 @@ else
public static string SourceText(ErrorLogSource source) => source switch
{
ErrorLogSource.ErrorLog => "fejlloggen",
ErrorLogSource.DefaultTrace => "default trace (hele fejlloggen)",
ErrorLogSource.DefaultTrace => "default trace (alvorlige fejl og mislykkede logins)",
_ => "exception ring buffer (kun fejlnumre)",
};

View file

@ -36,7 +36,7 @@ public class ErrorLogRuleTests
var result = Run(new SlowIoErrorRule(), With(Log(ErrorLogSource.RingBuffer)));
Assert.Equal(RuleOutcome.NotMeasurable, result.Outcome);
Assert.Contains("ALTER TRACE", result.Reason, StringComparison.Ordinal);
Assert.Contains("securityadmin ADD MEMBER", result.Reason, StringComparison.Ordinal);
Assert.Equal(RuleOutcome.NotMeasurable, Run(new SlowIoErrorRule(), With(Log(ErrorLogSource.DefaultTrace))).Outcome);
Assert.Equal(RuleOutcome.Findings, Run(new SlowIoErrorRule(), With(Log(ErrorLogSource.ErrorLog, G(ErrorLogCategory.SlowIo, 833, 10)))).Outcome);
Assert.Equal(RuleOutcome.NotMeasurable, Run(new StackDumpRule(), With(Log(ErrorLogSource.RingBuffer))).Outcome);