feat(health): wire ISiteEventLogger.FailedWriteCount into SiteHealthReport (#30, M2.16)

Add SiteHealthReport.SiteEventLogWriteFailures (trailing optional long = 0,
additive-only), ISiteHealthCollector.SetSiteEventLogWriteFailures (default
no-op so existing fakes compile), and SiteEventLogFailureCountReporter
(hosted service in HealthMonitoring, Func<long> delegate to avoid the
HealthMonitoring → StoreAndForward → SiteEventLogging cycle).

Registration helper AddSiteEventLogHealthMetricsBridge added to
HealthMonitoring.ServiceCollectionExtensions; wired in
SiteServiceRegistration after AddSiteEventLogging.

Tests: SiteEventLogWriteFailuresMetricTests (4 collector tests) +
SiteEventLogFailureCountReporterTests (2 poller tests) in
HealthMonitoring.Tests. 79/79 HealthMonitoring.Tests green,
59/59 SiteEventLogging.Tests green, 0 warnings.
This commit is contained in:
Joseph Doherty
2026-06-16 07:14:54 -04:00
parent e1ee37e508
commit d81f747434
9 changed files with 394 additions and 6 deletions
@@ -111,6 +111,23 @@ public interface ISiteHealthCollector
/// <param name="count">The number of parked messages.</param>
void SetParkedMessageCount(int count);
/// <summary>
/// Site Event Logging (#12) M2.16 (#30) — replace the latest cumulative
/// site-event-log write-failure count (SQLite error, disk full,
/// bounded-queue overflow drop) used by the next <see cref="CollectReport"/>
/// call. Refreshed periodically by the <c>SiteEventLogFailureCountReporter</c>
/// hosted service. Point-in-time: the value is NOT reset on
/// <see cref="CollectReport"/>; it carries forward until the next poller
/// refresh. Default interface implementation is a no-op so existing test
/// fakes continue to compile without per-fake updates.
/// </summary>
/// <param name="count">The cumulative failed-write count from <c>ISiteEventLogger.FailedWriteCount</c>.</param>
void SetSiteEventLogWriteFailures(long count)
{
// Default no-op so test fakes do not need to be updated. The real
// SiteHealthCollector overrides this with the Interlocked.Exchange store.
}
/// <summary>
/// Sets the hostname of this node.
/// </summary>