# Observabilité externe Omika — Phase 5 Centralisation externe **optionnelle** de l'observabilité : ```text OpenTelemetry (adapter Omika) → OpenTelemetry Collector → SigNoz → ClickHouse ``` > **Règle absolue** : *Les logs servent Omika. Omika ne dépend jamais des logs.* > OpenTelemetry, Collector, SigNoz et ClickHouse apportent visibilité, recherche, > diagnostic et corrélation. Ils n'apportent **aucune** dépendance au fonctionnement > métier. En cas de doute : **GARANTIR OMIKA**. ## Sommaire | Document | Contenu | |---|---| | [configuration.md](configuration.md) | Options `Observability:External`, kill switch, endpoints | | [deployment.md](deployment.md) | VM, ressources, ports, installation, démarrage, rétention, sauvegarde | | [support-guide.md](support-guide.md) | Retrouver un problème dans SigNoz depuis un TraceId | | [unplug.md](unplug.md) | Supprimer entièrement la pile externe sans casser Omika | | [data-whitelist.md](data-whitelist.md) | Inventaire des données exportées (liste blanche officielle) | ## Architecture finale ```text ┌── LocalFileTelemetryExporter (JSONL local) │ IOmikaTelemetry ├── DiagnosticOutboxExporter (omika-diagnostics.db) ↓ │ SafeTelemetrySink ──┤ ↓ │ PriorityQueue └── OpenTelemetryExporterAdapter ←─ RemoteDiagnosticForwarder ↓ │ ↑ TelemetryWorker OTLP HTTP/protobuf │ ↓ (relit le JSONL serveur) OTel Collector RemoteDiagnosticIngestionStore ↓ ↑ SigNoz POST /api/diagnostics ↓ ↑ ClickHouse Mobile ``` **Points clés :** 1. **OpenTelemetry est UN exporter optionnel**, derrière l'architecture Omika (`IOmikaTelemetry → SafeTelemetrySink → PriorityTelemetryQueue → TelemetryWorker → exporters`). Jamais devant, jamais référencé par le métier. 2. **Le mobile ne parle jamais OTLP directement.** Flux mobile : `Mobile → POST /api/diagnostics → RemoteDiagnosticIngestionStore (JSONL serveur) → ACK`. Le forwarding vers l'externe (`RemoteDiagnosticForwarder`) est asynchrone et best-effort, **après** l'ACK. 3. **`POST /api/diagnostics` ne dépend jamais du Collector.** L'ACK signifie uniquement « le serveur Omika a persisté localement le diagnostic ». 4. **Kill switch** `Observability:External:Enabled=false` (défaut) : désactive l'adaptateur OTel et le forwarder externe, sans toucher au local. 5. **Fail-open** : arrêter Collector/SigNoz/ClickHouse, bloquer le port OTLP, éteindre la VM, DNS/TLS invalide → **Omika fonctionne normalement** (seule conséquence : absence temporaire de centralisation). ## Choix du protocole OTLP (§11) | Critère | gRPC | HTTP/protobuf | |---|---|---| | Dépendance native | `Grpc.Net.Client` (HTTP/2, ALPN) | `HttpClient` pur | | Simplicité Windows | moyenne (TLS/HTTP2) | **haute** | | Firewall | un port (4317) | un port (4318) | | Debug/curl | non | **oui** (POST clair) | **Choix : OTLP HTTP/protobuf** (port 4318) — un seul protocole, `HttpClient` pur, simple à déployer entre l'API Windows et le Collector. Le gRPC reste configuré côté Collector pour interopérabilité mais n'est pas utilisé par Omika. ## Versions (réellement installées, §10) | Package / service | Version | Notes | |---|---|---| | `OpenTelemetry` (SDK .NET) | **1.13.0** | stable, compatible .NET 10 | | `OpenTelemetry.Exporter.OpenTelemetryProtocol` | **1.13.0** | train 1.13 aligné | | OpenTelemetry Collector | 0.128.x | distribution contrib | | SigNoz | 0.72.x (à épingler au stable officiel) | via installateur officiel | Les packages OpenTelemetry sont localisés **uniquement** dans le projet `src/Omika.Observability.External`. Aucun package OpenTelemetry dans `Omika.Core`, ni dans `Omika.App`/`Omika.App.Local`/`Omika.Data` (garanti par un test d'architecture). ## Identifiants — ne pas confondre (§33/§34) | Identifiant | Format | Rôle | Où | |---|---|---|---| | **Omika TraceId** | GUID (`X-Omika-TraceId`) | corrélation applicative **principale** | header HTTP, attribut `omika.trace_id` | | **OpenTelemetry TraceId** | 128 bits | trace native OTel | dérivé déterministiquement du GUID Omika | | **OpenTelemetry SpanId** | 64 bits | span OTel | généré par le SDK (logé en `omika.span_id`) | | **SessionId** | GUID | une exécution d'app | attribut `omika.session_id` | | **OperationId** | GUID | une opération métier/technique | attribut `omika.operation_id` | | **EventId** | GUID | un événement unique (dédup/doublons) | attribut + identifiant du log | | **BatchId** | GUID | un lot de transport mobile | Phase 4 | Le contrat `X-Omika-TraceId` reste **inchangé** : c'est l'identifiant visible par Omika/support. L'OTel TraceId est un mapping déterministe (GUID = 16 octets = 128 bits), jamais un remplacement silencieux du contrat.