feat(ui): Audit KPI tiles on Health dashboard (#23 M7)
Adds three KPI tiles to the central Health dashboard for the Audit channel: volume (rows in the last hour), error rate (Failed/Parked/Discarded over total), and backlog (sum of SiteAuditBacklog.PendingCount across all sites). Repo + service: - IAuditLogRepository.GetKpiSnapshotAsync(window, nowUtc) — single aggregate SELECT over the trailing window returning total + error counts; nowUtc is optional for production callers and pinned by integration tests against the shared MSSQL fixture so the global counts are deterministic. - AuditLogQueryService.GetKpiSnapshotAsync() — composes the repo aggregate with a sum of SiteAuditBacklog.PendingCount read from ICentralHealthAggregator. - AuditLogKpiSnapshot record in Commons/Types/. UI: - New AuditKpiTiles Blazor component (Components/Health/) — three Bootstrap card-tiles, click navigates to /audit/log with the matching pre-filter. - Health.razor wires the tiles in alongside the existing Notification Outbox KPIs; LoadAuditKpis() runs on every 10s refresh tick and degrades to em dashes + inline error if the query fails. - AuditLogPage extended to parse ?status= so the error-rate tile drill-in (?status=Failed) auto-loads the grid. Tests: - AuditLogRepositoryTests: GetKpiSnapshotAsync mixed-status + empty-window cases against the MSSQL migration fixture. - AuditLogQueryServiceTests: forwarding + backlog composition; sites with null SiteAuditBacklog contribute zero. - AuditKpiTilesTests: 9 bUnit tests covering tile render, error-rate maths with safe zero-events handling, em-dash unavailable path, click-through navigation, and warning/danger border thresholds. - HealthPageTests: new Renders_AuditKpiTiles_WithValues plus IAuditLogQueryService stub registration in the constructor so existing outbox tests still pass. - AuditLogPageScaffoldTests: ?status=Failed auto-load + unknown status drop.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
using ScadaLink.Commons.Entities.Audit;
|
||||
using ScadaLink.Commons.Types;
|
||||
using ScadaLink.Commons.Types.Audit;
|
||||
|
||||
namespace ScadaLink.CentralUI.Services;
|
||||
@@ -27,4 +28,26 @@ public interface IAuditLogQueryService
|
||||
|
||||
/// <summary>Default page size when callers don't specify one.</summary>
|
||||
int DefaultPageSize { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Audit Log (#23) M7 Bundle E (T13) — returns the point-in-time KPI snapshot
|
||||
/// the Health dashboard's Audit tiles render. Composes:
|
||||
/// <list type="bullet">
|
||||
/// <item><c>TotalEventsLastHour</c> + <c>ErrorEventsLastHour</c> from
|
||||
/// <see cref="ScadaLink.Commons.Interfaces.Repositories.IAuditLogRepository.GetKpiSnapshotAsync"/>
|
||||
/// (1-hour trailing window).</item>
|
||||
/// <item><c>BacklogTotal</c> from the sum of every site's
|
||||
/// <c>SiteHealthReport.SiteAuditBacklog.PendingCount</c> via
|
||||
/// <see cref="ScadaLink.HealthMonitoring.ICentralHealthAggregator"/>.</item>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Repository + aggregator are read independently; if either source has no
|
||||
/// data the corresponding field is zero (a real signal — "no events" vs
|
||||
/// "no backlog" — rather than an error). The service does NOT swallow
|
||||
/// exceptions; the page wraps the call in a try/catch so a transient DB
|
||||
/// outage degrades the tile group to "unavailable" rather than killing the
|
||||
/// dashboard.
|
||||
/// </remarks>
|
||||
Task<AuditLogKpiSnapshot> GetKpiSnapshotAsync(CancellationToken ct = default);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user