5.7 KiB
Phase 5 — Diagnostic Center (architecture & décisions)
Outil SUPPORT uniquement (§13). PostgreSQL et OpenTelemetry ne sont jamais critiques pour Omika :
Mobile → DiagnosticOutbox → POST /api/diagnostics → RemoteDiagnosticIngestionStore (JSONL durable) → ACK mobilereste inchangé (§4). L'import PostgreSQL et l'export OTLP sont asynchrones et optionnels.
Architecture retenue
APPLICATIONS OMIKA (Mobile / Desktop / API / Worker)
│
▼
IOmikaTelemetry
│
▼
SafeTelemetrySink
│
▼
PriorityTelemetryQueue (P0-P4)
│
┌──────┴─────────┐
▼ ▼
JSONL / Outbox OpenTelemetry (OTLP HTTP, optional, kill-switch)
durable Omika │
│ ▼
│ OpenTelemetry Collector (Windows Service)
│ │
▼ ▼
Diagnostic Import Omika Telemetry Backend ← transport finalisé Phase serveur
│ │
└────────┬────────┘
▼
PostgreSQL (omika_diagnostics)
│
▼
Omika Diagnostic Center (ASP.NET Core Web)
Projets créés (§12)
| Projet | Rôle |
|---|---|
src/Omika.Diagnostics.Core |
Domain / models, abstractions repository, importer, whitelist sécurité |
src/Omika.Diagnostics.Data |
Persistance PostgreSQL (Npgsql direct), source JSONL, checkpoint |
src/Omika.Diagnostics.Worker |
Import asynchrone JSONL → PostgreSQL (BackgroundService, backoff) |
src/Omika.Diagnostics.Web |
Diagnostic Center Web (Razor Pages) + auth support/admin |
Choix d'accès données (§25)
Npgsql direct (pas d'ORM). Justification :
- Sous-système simple : 2 tables, peu de patrons de requêtes.
- Aucune « magie » (pas de mapping réflexif, pas d'EF Core) — SQL explicite et lisible.
- Pooling intégré de Npgsql (§24) : jamais une connexion par événement.
- Dapper réduirait le boilerplate mais ajoute une dépendance + réflexion inutile ici.
- EF Core est surdimensionné pour 2 tables.
Version : Npgsql 10.0.3 (aligné .NET 10, présent dans le cache local du poste).
Données interdites (§19) et whitelist (§18)
Réutilise DiagnosticForbiddenData (Phase 4) : password, token, authorization,
cookie, connectionstring, requestbody, responsebody, emailbody, smtp,
imei, macaddress, advertisingid, signature, secret.
Les métadonnées metadata_json (JSONB) ne sont pas un stockage libre :
DiagnosticMetadataPolicy n'autorise qu'une whitelist de clés low-cardinality
(method, routeTemplate, statusCode, exceptionType, retryCount, …) et rejette
toute clé/valeur interdite. Les champs d'identité métier (DeviceId, UserId,
ClientId, CollaborateurId, EntityId) ne sont pas persistés dans PostgreSQL
(confidentialité, §30/§31).
Importeur JSONL → PostgreSQL (§20-§23)
DiagnosticImporter.ImportOnceAsync() : lecture bornée (BatchSize, défaut 100) →
mapping (whitelist) → INSERT ... ON CONFLICT (event_id) DO NOTHING (batch) →
avancement du checkpoint uniquement après insertion réussie.
- at-least-once : le checkpoint n'avance qu'après succès → doublons possibles,
dédupliqués par
event_idunique en base (§16). - fail-open (§22) : toute erreur PostgreSQL → résultat
Retryable, JSONL intact, checkpoint non avancé, backoff exponentiel borné (aucune boucle CPU). - idempotent : relire un fichier déjà importé est sans effet (ON CONFLICT).
Checkpoint (§21)
import-checkpoint.json (curseur { fileName, lineIndex }), distinct du checkpoint
du forwarder OpenTelemetry. Reprise après restart / PostgreSQL down / reboot sans
réimporter tout l'historique. Les fichiers JSONL bruts ne sont jamais supprimés.
Rétention (§45)
Diagnostics:RetentionDays (défaut 60 jours), non hardcodé. La purge
(DELETE ... WHERE timestamp_utc < now() - interval '60 days') est documentée mais
non exécutée automatiquement (purge destructive → maintenance planifiée).
Métriques (§28-§31)
Table telemetry_metric_hourly : agrégats horaires (bucket_utc, metric_name,
component, value, count, min/max, tags_json). Low-cardinality obligatoire
(ExternalAttributePolicy) : jamais TraceId/SessionId/UserId/DeviceId/GUID
métier en dimension. Utilisateurs actifs/jour = agrégation respectueuse de la
confidentialité, jamais de surveillance individuelle (§31).
Traces (§32/§33/§39/§40)
X-Omika-TraceId reste l'identifiant applicatif de support (§33). La timeline
Mobile → API → Worker se reconstruit par trace_id (ORDER BY timestamp_utc ASC),
et par operation_id pour les synchronisations.
Configuration (générique, jamais de secret §26)
Observability:
External:
Enabled: false # kill-switch : aucun OTLP, aucun réseau, aucun crash
OtlpEndpoint: ""
Remote:
Directory: "" # JSONL durable (frontière d'ACK Phase 4)
Diagnostics:
ConnectionString: "" # configuration / variable d'environnement UNIQUEMENT
RetentionDays: 60
Import:
BatchSize: 100
CheckpointFileName: "import-checkpoint.json"
Déploiement (Phase serveur, PAS dans cette phase)
- Windows Server 2025 : PostgreSQL + OpenTelemetry Collector (Windows Service) +
Omika.Diagnostics.Worker+Omika.Diagnostics.Web. - Aucune dépendance Linux / Docker / ClickHouse / SigNoz / Kubernetes.
- Rien n'est à installer sur le serveur dans cette phase (§ « NE RIEN INSTALLER »).