Status Dashboard — Technische Architectuur
Het Status Dashboard toont real-time gezondheid per module (IAM, UserTypes, Workflows) in het Management Portal. De implementatie is gebaseerd op een SignalR streaming architectuur die Seq parallel bevraagt en resultaten naar de portal pusht zodra ze beschikbaar zijn. Hierdoor kan het eerste kaartje al renderen terwijl de overige modules nog worden opgevraagd.
Architectuuroverzicht
Betrokken bestanden
Component | Locatie |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
Blazor componenten |
|
Domeinmodellen
IsDetailLoaded = false geeft aan dat een ModuleStatusSummary afkomstig is van GetModuleStatusQuickAsync — de detailvelden (RecentErrors, audit events, signals) zijn dan leeg.
Per-module query strategie
SeqStatusService.GetModuleStatusAsync voert vier categorie queries parallel uit voor elke module. Alle queries raken GET /api/events op Seq met fromDateUtc/toDateUtc en shortCircuitAfter=N.
Module-naar-log mapping
Dashboard module | Seq |
|---|---|
|
|
|
|
|
|
Query 1 — errors
Serilog error events voor foutdetectie. Retourneert maximaal 20 events.
Zodra er errors zijn (errors.Count > 0) wordt de module status Error; anders Ok.
Query 2 — activity
Meest recente audit event voor de LastActivityAt timestamp. Retourneert count=1.
Query 3 — actions
Module-specifieke query voor het laatste zichtbare actiebericht in de kaartkopregel:
Module | Filter | Count |
|---|---|---|
IAM |
| 10 |
UserTypes |
| 1 |
Workflows |
| 1 |
Query 4 — signals
Per module worden de signals parallel bevraagd (zie het Signal systeem hieronder). Elke signal heeft zijn eigen Seq filter; de caller voegt and TenantId = '{tenantId}' toe.
Quick variant
GetModuleStatusQuickAsync voert slechts twee queries uit (count=1, shortCircuitAfter=1) — genoeg om Ok versus Error vast te stellen en LastActivityAt te vullen. Dit is bedoeld voor snelle initiële rendering. IsDetailLoaded is altijd false.
Signal systeem
Wat is een signal?
Een DashboardSignalDefinition is een named, zelfstandig Seq filter met een weergavenaam en een maximaal aantal te retourneren events:
Signals beantwoorden specifieke operationele vragen onafhankelijk van de module-brede foutdetectie: "Heeft de sync gedraaid?", "Zijn er accounts via het formulier gewijzigd?", "Heeft AutoLeave accounts uitgeschakeld?"
Gedefinieerde signals per module
IAM signals:
Signal ( |
| Seq filter | Vraag |
|---|---|---|---|
| IAM Sync |
| Heeft de sync gedraaid? |
| Employee Management |
| Zijn medewerkers via het formulier gewijzigd? |
| Auto Leave |
| Heeft AutoLeave accounts uitgeschakeld? |
UserTypes signals:
Signal ( |
| Seq filter |
|---|---|---|
| Org Model |
|
| Personas |
|
Workflows signals:
Signal ( |
| Seq filter |
|---|---|---|
| Definitions |
|
| Executions |
|
Signal gezondheid
BuildSignalSummary bepaalt de status van een signal op basis van de ontvangen events:
Conditie | Status |
|---|---|
Errors aanwezig |
|
Events aanwezig, geen errors |
|
Geen events |
|
EventKind = 'Audit' strategie — immuun voor library-ruis
Het probleem
Serilog library loggers (MSAL token acquisitie, HttpClient, EF Core etc.) worden uitgevoerd in dezelfde job context als de business code. Ze erven daardoor properties zoals Module en TenantId uit de ambient log context. Een query als Module = 'IAM' and @Level = 'Information' zou daardoor MSAL token logs kunnen teruggeven die niets te maken hebben met IAM business activiteit.
De oplossing
SeqAuditLogSink stampt op elk audit event de property EventKind = 'Audit'. Library loggers schrijven nooit deze property — zij schrijven standaard Serilog events zonder EventKind.
Alle signals filteren altijd op EventKind = 'Audit'. Hierdoor:
Retourneren signals uitsluitend business audit records
Library-ruis (token logs, HTTP logs) verschijnt nooit in signal resultaten
De
Processproperty onderscheidt de trigger bron:Process = 'IamSync'— geschreven tijdens een IAM sync Hangfire jobProcess = 'AutoLeave'— geschreven tijdens de AutoLeave check jobProcess is null— getriggerd door een mens via het AutoMate formulier of de API
Praktisch voorbeeld
MSAL logt tijdens een IAM sync:
Een IAM Sync audit event:
De signal filter EventKind = 'Audit' and Process = 'IamSync' geeft alleen het tweede event terug.
SignalR streaming — progressief laden
Hub: StatusHub
Locatie: API/Src/AutoMate.API/Features/Common/Status/Hubs/StatusHub.cs Hub URL: /hubs/status Authenticatie: [Authorize] attribuut
De server-streaming methode StreamModuleStatuses werkt als volgt:
Volgorde van renderen: De drie modules worden parallel bevraagd. De snelste module verschijnt als eerste in de portal — er is geen vaste volgorde. De frontend rendert elk kaartje zodra het ModuleStatusSummary object binnenkomt via de stream.
Channel keuze: Een UnboundedChannel zorgt ervoor dat geen van de drie producers op de andere hoeft te wachten om te schrijven. De consumer leest in volgorde van aankomst.
Cancellation: De Seq HTTP aanroepen binnen SeqStatusService gebruiken CancellationToken.None — niet de caller token. Dit voorkomt dat portaalnavigatie een lopende Seq query afbreekt voordat het resultaat gecached kan worden.
Portal verbinding: StatusHubConnectionFactory
Locatie: Portals/ManagementPortal/Src/ManagementPortal.Website/Services/StatusHubConnectionFactory.cs
De factory haalt de API base URL op uit services:api:https:0 of services:api:https in de configuratie. De bearer token wordt per request opgehaald via IUserTokenManager (Duende Access Token Management). WithAutomaticReconnect() herstelt de verbinding automatisch bij tijdelijke netwerkstoringen.
Caching
Cache sleutel
Voorbeeld: status:module:IAM:550e8400-e29b-41d4-a716-446655440000:1440
Cache gedrag
TTL: 60 seconden per module/tenant combinatie
Alleen gecached als
Status != Unknown— bij Seq-uitval wordt geen staleUnknowngecachedDe REST endpoints (
GET /api/status/system,GET /api/status/modules/{module}) gebruiken dezelfde cache sleutel als de SignalR hub, zodat herhaalde loads near-instant zijn
Tenant autorisatie
ValidateTenantAccessAsync in StatusHub kent twee toegangspaden:
Directe match: De tenantid claim in het JWT token komt overeen met de opgevraagde tenant ID.
MSP cross-tenant: Vereist:
Gebruikerstenant heeft
TenantType = "MSP"Gebruiker heeft de rol
Automate365.Customers.ReadWriteDe opgevraagde tenant is een directe klant van de MSP (
requestedTenant.Partner.Id == userTenantId) — dit voorkomt dat een MSP toegang krijgt tot tenants van andere MSPs viaSystemTenantHasAccessconstructies
REST fallback
Naast SignalR biedt IStatusService een REST interface via de auto-gegenereerde Kiota API client:
Methode | Endpoint | Beschrijving |
|---|---|---|
|
| Alle modules in één antwoord |
|
| Één module opvragen |
De REST interface levert dezelfde data als de SignalR stream maar in één gebundeld antwoord. Geschikt als fallback of voor polling-gebaseerde integraties.
Nieuwe signal toevoegen — stap voor stap
1. Voeg een constante toe in LoggingConstants
Signalnamen zijn constanten genest onder het betreffende module-blok in LoggingConstants.DashboardModules:
2. Registreer de DashboardSignalDefinition in StatusSignals
Voeg de definitie toe aan de juiste signals lijst in API/AutoMate.API.Plugins.AuditLog/Status/StatusSignals.cs:
Vuistregels voor de Seq filter:
Begin altijd met
EventKind = 'Audit'voor audit-gebaseerde signals — nooit weglatenGebruik
Process = 'NaamVanJob'als het signal een Hangfire-job vertegenwoordigtGebruik
Process is nullals het signal handmatige portaalacties vertegenwoordigtGebruik
Module = '...'ofFeature = '...'om verder te scopenVoeg
TenantIdniet toe — de caller doet dat automatisch
3. Verifieer in Seq
Test de filter voordat je deployt:
Vervang <jouw-tenant-id> door een bekende tenant GUID. Zie de sectie Seq filter voorbeelden hieronder voor meer debugging queries.
4. Geen verdere wijzigingen nodig
SeqStatusService.GetModuleStatusAsync laadt signals dynamisch via StatusSignals.ForModule(dashboardModule). De portal rendert signal sub-rijen automatisch op basis van de Signals property van ModuleStatusSummary.
Seq query parameters — referentie
SeqStatusService bouwt elke query als volgt op:
Parameter | Beschrijving |
|---|---|
| Tijdvenster (niet |
| Maximum aantal te retourneren events |
| Stop scannen zodra N matches gevonden — zeer effectief voor |
| Seq rendert berichten server-side (template tokens worden ingevuld) |
| API key via request header |
Seq filter voorbeelden voor debugging
Vervang <tenant-id> door de betreffende tenant GUID.
Controleer of IAM sync heeft gedraaid in de afgelopen 24 uur:
Bekijk handmatige IAM-wijzigingen van vandaag:
AutoLeave activiteit:
Alle errors voor een module (zoals het dashboard ze ziet):
Workflow definitie wijzigingen:
OrgModel audit events:
Controleer of library-ruis door signals heen lekt (verwacht: nul resultaten):