FEAT: Remontée des logs agents — buffer + endpoint POST /api/agents/{id}/logs #50
Labels
No labels
bug
chore
design
dx:ci
dx:database
dx:dotnet
dx:infra
dx:security
dx:tests
dx:ui
etape-1
etape-2
etape-3
etape-4
etape-5
etape-6
etape-7
feature
priority-high
priority-low
priority-medium
security
spec
tech-debt
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
nonobis/Heimdall#50
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Contexte
Les agents Heimdall (FFmpeg/YOLO/RTSP) loguent aujourd'hui uniquement vers stdout/Docker (ILogger .NET standard) et vers Sentry/GlitchTip si DSN configuré. Aucun log n'est visible depuis l'interface d'admin centrale : quand un agent crashe, se reconnecte en boucle ou échoue une détection, l'admin ne voit rien sans SSH.
Référence spec
Pas de section dédiée dans
docs/MASTER_SPECIFICATION.md. Complète le pattern d'observabilité existant (AuditLog P0, §1.3) et la règle P1 « Secrets dans logs — sanitized : password, token, secret, snapshotUrl masqués » (ligne 510). S'inscrit dans l'étape 6 (ops/observabilité), comme les tickets #13 (health checks) et #14 (métriques).Décisions validées (08/2026)
agent.log.level, ex. Information/Warning/Error) avec override possible par agent — s'appuie sur le mécanismeAgentScopedSettingexistant (migrationAddAgentScopedSetting) +ConfigReceiverService(settings poussés à l'agent, patternheartbeat.interval.seconds)État actuel
src/Heimdall.Agent/Program.cs: logging Microsoft.Extensions.Logging par défaut, pas de Serilog, pas de bufferAgentRegistrationService: heartbeatPOST /api/agents/{id}/heartbeat(API Key) toutes les 30 s avec métriques — pas de logs dans le payloadAgentScopedSetting: table/settings par agent déjà en place (migrationAddAgentScopedSetting)À faire
LogBufferService(singleton) : ring buffer borné en mémoire (taille configurable, ex. 500 entrées), thread-safe ; niveau de capture effectif = override agent si défini (AgentScopedSetting), sinon niveau global (agent.log.level)ILoggerProviderbranché sur le pipeline de logging de l'agent pour capturer les entrées (timestamp, level, message, exception, composant) sans bloquer le thread appelantPOST /api/agents/{id}/logs(API Key) envoyant le batch :{ entries: [{ timestampUtc, level, message, exception?, source? }] }— ne pas alourdir le heartbeat (découplage volume/observabilité)DropWrite(pasDropOldest— règle agent existante) et retry/backoff si échec ; les logs restent non-bloquants (jamais d'await bloquant dans le chemin de logging)Critères d'acceptation
password=/token=/secret=sont masqués avant transmissiontests/Heimdall.Agent.TestsFichiers concernés
src/Heimdall.Agent/Services/LogBufferService.cs(nouveau)src/Heimdall.Agent/Logging/AgentLoggingProvider.cs(nouveau)src/Heimdall.Agent/Program.cs(enregistrement provider)src/Heimdall.Agent/AgentOptions.cs+appsettings.json(niveau, taille buffer, intervalle)src/Heimdall.Agent/Services/AgentRegistrationService.cs(tick d'envoi)AgentScopedSetting(override par agent) +SettingsController(paramètre global)Décision validée : niveau de capture = paramètre central (agent.log.level) avec override possible par agent via AgentScopedSetting. Rétention 7 j validée (cf. #53). Vue globale multi-agents : hors scope pour l'instant.
Clôturé par le commit
6c5d455(feat logs agents). Tests : 985 verts (Domain 131, Application 354, Infrastructure 163, Agent 120, Web 217).