feat(health): SiteAuditBacklog metric (count + age + bytes) (#23 M6)
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
using ScadaLink.Commons.Types;
|
||||
|
||||
namespace ScadaLink.HealthMonitoring.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// Bundle E (M6-T6) regression coverage. The site-side audit-log SQLite writer
|
||||
/// exposes a backlog snapshot (<c>SiteAuditBacklogSnapshot</c>) via the
|
||||
/// <c>ISiteAuditQueue.GetBacklogStatsAsync</c> surface. A periodic
|
||||
/// <c>SiteAuditBacklogReporter</c> hosted service polls that snapshot and
|
||||
/// pushes it into the collector via <see cref="ISiteHealthCollector.UpdateSiteAuditBacklog"/>
|
||||
/// so the next <see cref="ISiteHealthCollector.CollectReport"/> includes it in
|
||||
/// the report payload as <c>SiteAuditBacklog</c>. Unlike the
|
||||
/// SiteAuditWriteFailures / AuditRedactionFailure interval counters, the
|
||||
/// backlog snapshot is not reset on collect — the field carries forward
|
||||
/// whatever the most recent refresh pushed in.
|
||||
/// </summary>
|
||||
public class SiteAuditBacklogMetricTests
|
||||
{
|
||||
private readonly SiteHealthCollector _collector = new();
|
||||
|
||||
[Fact]
|
||||
public void Update_Then_CollectReport_IncludesBacklog()
|
||||
{
|
||||
var snapshot = new SiteAuditBacklogSnapshot(
|
||||
PendingCount: 42,
|
||||
OldestPendingUtc: new DateTime(2026, 5, 20, 10, 0, 0, DateTimeKind.Utc),
|
||||
OnDiskBytes: 1234567);
|
||||
|
||||
_collector.UpdateSiteAuditBacklog(snapshot);
|
||||
|
||||
var report = _collector.CollectReport("site-1");
|
||||
|
||||
Assert.Equal(snapshot, report.SiteAuditBacklog);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Report_Payload_Includes_SiteAuditBacklog_AsNullByDefault()
|
||||
{
|
||||
// No refresh has been pushed yet — the report carries null so the
|
||||
// central UI can distinguish "no data yet" from "queue empty".
|
||||
var report = _collector.CollectReport("site-1");
|
||||
|
||||
Assert.Null(report.SiteAuditBacklog);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CollectReport_DoesNotReset_SiteAuditBacklog()
|
||||
{
|
||||
// Backlog snapshot is a point-in-time reading, not a per-interval
|
||||
// counter — successive CollectReport calls before the next
|
||||
// SiteAuditBacklogReporter tick MUST keep returning the same snapshot
|
||||
// so a slow refresh cadence doesn't blank the central dashboard.
|
||||
var snapshot = new SiteAuditBacklogSnapshot(
|
||||
PendingCount: 7,
|
||||
OldestPendingUtc: null,
|
||||
OnDiskBytes: 8192);
|
||||
|
||||
_collector.UpdateSiteAuditBacklog(snapshot);
|
||||
|
||||
var first = _collector.CollectReport("site-1");
|
||||
var second = _collector.CollectReport("site-1");
|
||||
|
||||
Assert.Equal(snapshot, first.SiteAuditBacklog);
|
||||
Assert.Equal(snapshot, second.SiteAuditBacklog);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Update_With_Null_Throws_ArgumentNullException()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>(
|
||||
() => _collector.UpdateSiteAuditBacklog(null!));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user