Premiere commit - Omika
This commit is contained in:
@@ -0,0 +1,135 @@
|
||||
# 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 mobile` reste inchangé (§4).
|
||||
> L'import PostgreSQL et l'export OTLP sont **asynchrones et optionnels**.
|
||||
|
||||
## Architecture retenue
|
||||
|
||||
```text
|
||||
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_id` unique 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)
|
||||
|
||||
```yaml
|
||||
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 »).
|
||||
Reference in New Issue
Block a user