From d9e3b4ee6d8139c37fce849328a3e2fb3e26ccbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Eggert=20Lundsteen=20Olsen?= Date: Fri, 2 Oct 2026 11:38:34 +0200 Subject: [PATCH] Review 1.2: read only the default trace's current file between rollovers With ALTER TRACE the error log collector read every default trace file (up to 5 x 20 MB) every 5 minutes. While the current file is the one read last time, everything since then is in it, so only that file is read; after a rollover (and the first time) all files are read once as before. Co-Authored-By: Claude Opus 5.5 (1M context) --- .../Instance/ErrorLogCollector.cs | 19 +++++++++++++------ src/SQLInsight.Core/Data/ErrorLog.cs | 3 +++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/SQLInsight.Collectors/Instance/ErrorLogCollector.cs b/src/SQLInsight.Collectors/Instance/ErrorLogCollector.cs index 410448a..a00e3e5 100644 --- a/src/SQLInsight.Collectors/Instance/ErrorLogCollector.cs +++ b/src/SQLInsight.Collectors/Instance/ErrorLogCollector.cs @@ -69,13 +69,14 @@ public sealed class ErrorLogCollector(int loginFailureBurst = 20) : Collector entries; ErrorLogSource source; string? coverage = null; + string? traceFile = null; if (errorLog && await ReadErrorLogAsync(connection, since, now, offset, ct).ConfigureAwait(false) is { } fromLog) { (entries, source) = (fromLog, ErrorLogSource.ErrorLog); } - else if (await ReadDefaultTraceAsync(connection, since, offset, ct).ConfigureAwait(false) is { } fromTrace) + else if (await ReadDefaultTraceAsync(connection, since, offset, previous?.TraceFile, ct).ConfigureAwait(false) is { } fromTrace) { - (entries, source, coverage) = (fromTrace, ErrorLogSource.DefaultTrace, DefaultTraceCoverage); + (entries, source, coverage, traceFile) = (fromTrace.Entries, ErrorLogSource.DefaultTrace, DefaultTraceCoverage, fromTrace.File); } else { @@ -103,6 +104,7 @@ public sealed class ErrorLogCollector(int loginFailureBurst = 20) : CollectorErrorLog (22) and Audit Login Failed (20) events from the default trace, or null without ALTER TRACE. - private static async Task?> ReadDefaultTraceAsync(DbConnection connection, DateTimeOffset since, TimeSpan offset, - CancellationToken cancellationToken) + private static async Task<(List Entries, string File)?> ReadDefaultTraceAsync(DbConnection connection, DateTimeOffset since, TimeSpan offset, + string? previousFile, CancellationToken cancellationToken) { try { @@ -138,9 +140,14 @@ public sealed class ErrorLogCollector(int loginFailureBurst = 20) : Collector '{Local(since, offset)}' """; var rows = await Db.QueryAsync(connection, sql, r => (At: Utc(r.DateTime(0)) - offset, Class: r.Int(1), Error: r.NullableInt(2), Severity: r.NullableInt(3), @@ -164,7 +171,7 @@ public sealed class ErrorLogCollector(int loginFailureBurst = 20) : Collector e.At > since)]; + return ([.. entries.Where(e => e.At > since)], path); } catch (DbException) { diff --git a/src/SQLInsight.Core/Data/ErrorLog.cs b/src/SQLInsight.Core/Data/ErrorLog.cs index d0454fb..f5bd75e 100644 --- a/src/SQLInsight.Core/Data/ErrorLog.cs +++ b/src/SQLInsight.Core/Data/ErrorLog.cs @@ -54,6 +54,9 @@ public sealed record ErrorLogSnapshot /// The newest entry read; the next collection continues after it. public required DateTimeOffset ReadUntil { get; init; } + /// The default trace's current file when it was read; while it stays the same, only that file is read next time. + public string? TraceFile { get; init; } + /// What was found since the previous collection, grouped. public IReadOnlyList Groups { get; init; } = [];