23c0fd417e
Bundle C task M5-T7 — surface DefaultAuditPayloadFilter redactor
over-redactions as a Site Health metric so a misconfigured /
catastrophic regex shows up on /monitoring/health rather than
disappearing into a NoOp sink.
- SiteHealthReport: new 'AuditRedactionFailure' int field
(defaulted to 0 for back-compat with existing producers/tests).
- ISiteHealthCollector / SiteHealthCollector:
new IncrementAuditRedactionFailure() — per-interval atomic
counter with Interlocked, reset on CollectReport, mirroring
the M2 Bundle G SiteAuditWriteFailures pattern.
- HealthMetricsAuditRedactionFailureCounter: new bridge in
ScadaLink.AuditLog.Site that forwards IAuditRedactionFailureCounter
increments to ISiteHealthCollector — mirrors
HealthMetricsAuditWriteFailureCounter one-for-one.
- AddAuditLogHealthMetricsBridge: now ALSO Replaces the
NoOpAuditRedactionFailureCounter binding with the health-metrics
bridge, so a single AddAuditLogHealthMetricsBridge() call wires
both the M2 Bundle G write-failure counter and the M5 Bundle C
redaction-failure counter into the health report.
Site-side only for M5 — the filter also runs on CentralAuditWriter
and AuditLogIngestActor (where it just keeps the NoOp default), but
a central-side health-metric surface for AuditRedactionFailure is
deferred to M6 alongside the rest of the central health collector
work.
Tests:
- AuditRedactionFailureMetricTests (HealthMonitoring) covers the
SiteHealthCollector increment/report/reset shape (3 tests).
- HealthMetricsAuditRedactionFailureCounterTests (AuditLog) covers
the AuditLog → HealthMonitoring bridge (3 tests).
- Existing CountCapturingHealthCollector stub in
DeploymentManagerRedeployTests extended with the new no-op
interface method.
Verified: dotnet build clean, all 24 test projects green
(the only Failed at first ScadaLink.SiteRuntime.Tests run was the
known-flaky InstanceActorChildAttributeRaceTests; passes on re-run
in isolation and full suite, unrelated to these changes).
49 lines
2.1 KiB
C#
49 lines
2.1 KiB
C#
using ScadaLink.AuditLog.Payload;
|
|
using ScadaLink.HealthMonitoring;
|
|
|
|
namespace ScadaLink.AuditLog.Site;
|
|
|
|
/// <summary>
|
|
/// Audit Log (#23) M5 Bundle C — bridges
|
|
/// <see cref="IAuditRedactionFailureCounter"/> (incremented by
|
|
/// <see cref="DefaultAuditPayloadFilter"/> every time a header / body / SQL
|
|
/// parameter redactor stage throws and the filter has to over-redact the
|
|
/// offending field) into <see cref="ISiteHealthCollector"/> so the count
|
|
/// surfaces in the site health report payload as
|
|
/// <c>SiteHealthReport.AuditRedactionFailure</c>.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// Registered by <see cref="ServiceCollectionExtensions.AddAuditLogHealthMetricsBridge"/>;
|
|
/// callers must register <c>AddHealthMonitoring()</c> first so
|
|
/// <see cref="ISiteHealthCollector"/> resolves. The default <see cref="ServiceCollectionExtensions.AddAuditLog"/>
|
|
/// registration keeps <see cref="NoOpAuditRedactionFailureCounter"/> for nodes
|
|
/// where Site Health Monitoring is not wired (the silent-sink contract —
|
|
/// redaction failures must NEVER abort the user-facing action, alog.md §7).
|
|
/// </para>
|
|
/// <para>
|
|
/// Mirrors the M2 Bundle G <see cref="HealthMetricsAuditWriteFailureCounter"/>
|
|
/// shape one-for-one so the two health-metric bridges age together.
|
|
/// </para>
|
|
/// <para>
|
|
/// Site-side only for M5: the redaction filter also runs on the central
|
|
/// writers (CentralAuditWriter + AuditLogIngestActor), but the central
|
|
/// health-metric surface that would expose <c>AuditRedactionFailure</c>
|
|
/// alongside the existing central counters ships in M6. Until then, the
|
|
/// central composition root keeps the NoOp default — the redactions still
|
|
/// happen, they just don't get counted into a health report.
|
|
/// </para>
|
|
/// </remarks>
|
|
public sealed class HealthMetricsAuditRedactionFailureCounter : IAuditRedactionFailureCounter
|
|
{
|
|
private readonly ISiteHealthCollector _collector;
|
|
|
|
public HealthMetricsAuditRedactionFailureCounter(ISiteHealthCollector collector)
|
|
{
|
|
_collector = collector ?? throw new ArgumentNullException(nameof(collector));
|
|
}
|
|
|
|
/// <inheritdoc/>
|
|
public void Increment() => _collector.IncrementAuditRedactionFailure();
|
|
}
|