
OpenTelemetry (OTel) est le standard open source qui vous permet d’instrumenter vos applications une seule fois et d’envoyer les données de télémétrie — traces, métriques et logs — vers n’importe quel backend sans modifier votre code. Projet CNCF Graduated au même niveau que Kubernetes, OpenTelemetry fait partie des projets les plus actifs de la fondation (souvent cité comme #2 en velocity derrière Kubernetes). Si vous ne voulez retenir qu’une chose : OpenTelemetry sépare l’instrumentation (comment on collecte) du stockage (où on envoie), et c’est cette séparation qui élimine le vendor lock-in.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Le problème avant OTel : vendor lock-in, agents multiples, formats incompatibles
- Les composants clés : API, SDK, Collector, OTLP — qui fait quoi
- Les signaux OTel : traces, métriques, logs (et profiles) — état de maturité de chacun
- Le Collector : pipeline receivers → processors → exporters et patterns de déploiement
- L’instrumentation : auto-instrumentation (zero-code) vs instrumentation manuelle
- Les exporters : OTLP et les passerelles vers vos backends existants
- L’adoption pragmatique : par où commencer dans un système existant
Le problème : avant OpenTelemetry
Section intitulée « Le problème : avant OpenTelemetry »Avant OpenTelemetry, instrumenter une application pour l’observabilité impliquait des choix lourds et coûteux :
Vendor lock-in : chaque plateforme d’observabilité fournissait son propre agent et son propre SDK. Instrumenter pour Datadog signifiait utiliser le SDK Datadog, ses conventions, son format de données. Migrer vers New Relic ou Grafana Cloud nécessitait de ré-instrumenter tout le code.
Agents multiples : un serveur pouvait héberger simultanément un agent Datadog pour les métriques, un agent Jaeger pour les traces, et Fluentd pour les logs. Trois agents, trois configurations, trois consommations de ressources.
Formats incompatibles : les traces Zipkin utilisaient le format B3, Jaeger son propre format, et les métriques passaient par StatsD, Prometheus ou InfluxDB — chacun avec sa sérialisation. Corréler entre ces formats était un cauchemar.
Deux projets concurrents : en 2019, la communauté avait deux projets d’instrumentation ouverte — OpenTracing (tracing API) et OpenCensus (tracing + métriques, initié par Google). Les deux faisaient presque la même chose, fragmentant l’écosystème et les contributions.
La fusion : naissance d’OpenTelemetry
Section intitulée « La fusion : naissance d’OpenTelemetry »En mai 2019, OpenTracing et OpenCensus ont fusionné pour créer OpenTelemetry, sous l’égide de la CNCF (Cloud Native Computing Foundation). L’objectif : un standard unique d’instrumentation, neutre vis-à-vis des vendors, couvrant tous les signaux.
Les composants clés : API, SDK, Collector, OTLP
Section intitulée « Les composants clés : API, SDK, Collector, OTLP »OpenTelemetry n’est pas un outil unique — c’est un écosystème de composants qui se combinent. Chaque composant a un rôle précis :
L’API : le contrat stable
Section intitulée « L’API : le contrat stable »L’API OpenTelemetry est un ensemble d’interfaces (pas d’implémentation) qui définissent comment créer des spans, enregistrer des métriques, émettre des logs. Elle est conçue pour être stable et rétrocompatible : votre code applicatif dépend de l’API, jamais directement du SDK.
Pourquoi cette séparation ? Les bibliothèques partagées (frameworks HTTP, clients de base de données, ORMs) peuvent s’instrumenter avec l’API OpenTelemetry sans imposer de dépendance lourde à leurs utilisateurs. Si l’application n’a pas configuré de SDK, les appels à l’API sont des no-ops (pas d’impact sur les performances).
Le SDK : l’implémentation par langage
Section intitulée « Le SDK : l’implémentation par langage »Le SDK est l’implémentation concrète de l’API, spécifique à chaque langage (Java, Python, Go, .NET, JavaScript, Rust…). C’est le SDK qui :
- Crée réellement les spans et les points de données
- Gère le sampling (head-based, probability-based)
- Configure les exporters (où envoyer les données)
- Gère le batching et le buffering avant export
- Injecte le contexte dans les logs (bridge logging)
Le SDK est configuré au démarrage de l’application (pas dans le code métier). Vous pouvez changer d’exporter ou de sampling sans modifier une seule ligne de code applicatif.
OTLP : le protocole de transport
Section intitulée « OTLP : le protocole de transport »OTLP (OpenTelemetry Protocol) est le protocole natif pour transporter les données de télémétrie. Il supporte les trois signaux (traces, métriques, logs) dans un format unique, avec deux modes de transport :
| Mode | Port conventionnel | Usage |
|---|---|---|
| gRPC | 4317 | Haute performance, streaming, production |
| HTTP/protobuf | 4318 | Compatibilité large, traverse les proxies HTTP |
Ces ports sont une convention largement adoptée, pas une obligation protocolaire — adaptez-les selon votre réseau ou votre service mesh.
OTLP est le format recommandé pour la communication SDK → Collector et Collector → backend. La plupart des backends modernes le supportent nativement (Tempo, Jaeger, Prometheus remote write, Elastic APM, Datadog, New Relic).
Le Collector : le pipeline central
Section intitulée « Le Collector : le pipeline central »Le Collector est un composant autonome, écrit en Go, qui reçoit, traite et exporte les données de télémétrie. C’est le routeur de votre infrastructure d’observabilité.
Le Collector sera détaillé dans la section suivante — c’est le composant le plus important à comprendre pour le déploiement.
Les signaux OTel : état de maturité
Section intitulée « Les signaux OTel : état de maturité »OpenTelemetry couvre aujourd’hui quatre signaux. Leur niveau de maturité détermine ce que vous pouvez utiliser en production en toute confiance :
| Signal | Maturité | Détail |
|---|---|---|
| Traces | Stable (GA depuis 2021) | Signal le plus mature — API, SDK, Collector, OTLP : tout est stable dans les langages majeurs |
| Métriques | Stable (GA depuis 2023) | API et SDK stables dans la plupart des langages — support OTLP, histogrammes exponentiels, exemplars |
| Logs | Stable (GA depuis 2023) | Le Logs Bridge API permet d’injecter le contexte OTel dans vos frameworks de logging existants — le niveau de stabilité varie encore selon le langage/SDK |
| Profiles | En développement | 4ᵉ signal (profiling continu — CPU, mémoire, allocations). Spécification en cours, pas encore prêt pour la production |
Le Collector : pipeline receive → process → export
Section intitulée « Le Collector : pipeline receive → process → export »Le Collector est le composant qui découple vos applications de vos backends. Il se configure via un fichier YAML organisé en quatre sections :
Architecture du pipeline
Section intitulée « Architecture du pipeline »- Receivers : points d’entrée — comment les données arrivent au Collector (OTLP, scrape Prometheus, fichiers de logs, protocoles legacy)
- Processors : transformations en vol — batching, limitation mémoire, filtrage, enrichissement d’attributs, sampling
- Exporters : points de sortie — vers quels backends envoyer les données
Une quatrième section, Extensions, gère les fonctionnalités transverses (health check, pprof, zpages pour le debug).
Exemple minimal de configuration
Section intitulée « Exemple minimal de configuration »receivers: otlp: protocols: grpc: endpoint: "0.0.0.0:4317" http: endpoint: "0.0.0.0:4318"
processors: batch: send_batch_size: 1024 timeout: 5s memory_limiter: check_interval: 1s limit_mib: 2048 spike_limit_mib: 512
exporters: otlp/tempo: endpoint: "tempo:4317" tls: insecure: true prometheus: endpoint: "0.0.0.0:8889" loki: endpoint: "http://loki:3100/loki/api/v1/push"
service: pipelines: traces: receivers: [otlp] processors: [memory_limiter, batch] exporters: [otlp/tempo] metrics: receivers: [otlp] processors: [memory_limiter, batch] exporters: [prometheus] logs: receivers: [otlp] processors: [memory_limiter, batch] exporters: [loki]Ce fichier déclare trois pipelines — un par signal — qui reçoivent les données via OTLP (gRPC et HTTP), appliquent un memory limiter et du batching, puis exportent vers Tempo (traces), Prometheus (métriques) et Loki (logs).
Patterns de déploiement
Section intitulée « Patterns de déploiement »Le Collector peut être déployé de trois façons, selon vos besoins :
| Pattern | Description | Cas d’usage |
|---|---|---|
| Sidecar | Un Collector par pod/conteneur, colocalisé avec l’application | Isolation forte, faible latence d’export, overhead par pod |
| Agent (DaemonSet) | Un Collector par nœud du cluster | Bon compromis performance/ressources, collecte des logs système |
| Gateway | Un pool centralisé de Collectors en aval des agents | Tail-based sampling, enrichissement centralisé, routage multi-backend |
En pratique, les architectures combinent souvent agent + gateway : un agent DaemonSet collecte et pré-traite localement, puis envoie au gateway qui applique le sampling intelligent et route vers les backends.
Instrumentation : zero-code vs manuelle
Section intitulée « Instrumentation : zero-code vs manuelle »OpenTelemetry propose deux approches complémentaires pour instrumenter vos applications :
Auto-instrumentation (zero-code)
Section intitulée « Auto-instrumentation (zero-code) »L’auto-instrumentation intercepte automatiquement les appels aux bibliothèques connues (clients HTTP, clients de base de données, frameworks web) et crée des spans sans que vous modifiiez votre code applicatif.
Selon le langage, le mécanisme est différent :
| Langage | Mécanisme | Comment l’activer |
|---|---|---|
| Java | Agent Java (javaagent JAR) | -javaagent:opentelemetry-javaagent.jar au démarrage de la JVM |
| Python | Monkey-patching via opentelemetry-instrument | opentelemetry-instrument python app.py |
| .NET | Agent .NET ou variables d’environnement | Variables OTEL_DOTNET_AUTO_* |
| Node.js | Module loader (--require) | node --require @opentelemetry/auto-instrumentations-node app.js |
| Go | Pas d’agent classique (pas de VM) | Instrumentation manuelle le plus souvent ; des approches eBPF / OBI (OpenTelemetry eBPF Instrumentation) émergent pour certains scénarios |
Avantages : déploiement rapide, pas de modification du code source, couvre les frameworks les plus courants.
Limites : ne capture que les opérations des bibliothèques connues — pas le contexte métier (ID commande, montant, utilisateur). Les spans créés sont génériques.
Instrumentation manuelle
Section intitulée « Instrumentation manuelle »L’instrumentation manuelle utilise l’API OpenTelemetry pour créer des spans et des attributs spécifiques à votre logique métier :
from opentelemetry import trace
tracer = trace.get_tracer("payment-service")
def process_payment(order_id: str, amount: float): with tracer.start_as_current_span("process_payment") as span: span.set_attribute("order.id", order_id) span.set_attribute("order.amount", amount) # ... logique de paiementAvantages : contrôle total sur les spans, attributs métier riches, nommage significatif.
Limites : nécessite de modifier le code source, maintenance à prévoir.
La bonne pratique : combiner les deux
Section intitulée « La bonne pratique : combiner les deux »-
Commencez par l’auto-instrumentation
Activez l’auto-instrumentation pour obtenir immédiatement les spans des appels HTTP, des requêtes SQL, des appels gRPC — sans modifier le code.
-
Ajoutez l’instrumentation manuelle où ça compte
Sur les opérations métier critiques (paiement, création de commande, authentification), ajoutez des spans manuels avec des attributs métier pertinents pour le diagnostic.
-
Ne sur-instrumentez pas
Chaque span a un coût (CPU, mémoire, réseau). Instrumentez les opérations qui aident au diagnostic — pas chaque fonction interne.
Les exporters : OTLP et les passerelles
Section intitulée « Les exporters : OTLP et les passerelles »Le SDK et le Collector peuvent exporter les données vers de nombreux backends. OTLP est le format natif, mais des exporters spécifiques existent pour les systèmes qui ne supportent pas (encore) OTLP :
| Backend | Protocole | Traces | Métriques | Logs |
|---|---|---|---|---|
| Tempo | OTLP (natif) | Oui | — | — |
| Jaeger | OTLP (natif) | Oui | — | — |
| Prometheus | Remote Write / Scrape | — | Oui | — |
| Loki | Push API | — | — | Oui |
| Elasticsearch | API Elasticsearch | Oui | Oui | Oui |
| Datadog | API Datadog | Oui | Oui | Oui |
| New Relic | OTLP (natif) | Oui | Oui | Oui |
| Grafana Cloud | OTLP (natif) | Oui | Oui | Oui |
Adoption pragmatique : par où commencer
Section intitulée « Adoption pragmatique : par où commencer »Adopter OpenTelemetry dans un système existant ne se fait pas en un jour. Voici une stratégie progressive qui minimise les risques :
-
Commencez par les traces
C’est le signal le plus mature et celui qui apporte le plus de valeur immédiate dans une architecture distribuée. Activez l’auto-instrumentation sur un ou deux services critiques, déployez un Collector en mode agent, et envoyez vers Tempo ou Jaeger.
-
Ajoutez la corrélation logs ↔ traces
Configurez le Logs Bridge pour injecter le
trace_iddans vos logs existants. Vous obtenez la navigation log → trace sans changer de logger. -
Migrez les métriques progressivement
Si vous utilisez déjà Prometheus, continuez à le scraper directement. Le Collector peut aussi scraper vos targets Prometheus (receiver
prometheus) et ajouter des exemplars OTLP. La migration peut être graduelle. -
Déployez un gateway pour le sampling intelligent
Quand le volume de traces devient coûteux, ajoutez un Collector en mode gateway avec du tail-based sampling pour capturer 100 % des erreurs et échantillonner le trafic normal.
Pièges courants
Section intitulée « Pièges courants »| Piège | Pourquoi c’est un problème | Solution |
|---|---|---|
| Dépendre directement du SDK dans le code métier | Couplage fort, migration difficile | Dépendre uniquement de l’API dans le code applicatif ; configurer le SDK au démarrage |
| Envoyer directement au backend sans Collector | Pas de batching, pas de retry, pas de buffer en cas de panne backend | Toujours interposer un Collector entre l’application et le backend |
| Utiliser la distribution Core en production | Il manque les exporters vers vos backends spécifiques | Utiliser la distribution Contrib ou construire un Collector custom avec ocb |
Oublier le memory_limiter dans le Collector | Le Collector consomme de la mémoire sans limite → OOM kill | Toujours configurer memory_limiter comme premier processor de chaque pipeline |
| Sur-instrumenter | Trop de spans = coût élevé + bruit dans les traces | Instrumenter les opérations utiles au diagnostic, pas chaque ligne de code |
| Confondre auto-instrumentation et visibilité complète | L’auto-instrumentation ne capture pas le contexte métier | Compléter avec de l’instrumentation manuelle sur les opérations critiques |
À retenir
Section intitulée « À retenir »-
OpenTelemetry sépare l’instrumentation du stockage — vous instrumentez une fois avec l’API/SDK, et vous routez vers n’importe quel backend via le Collector
-
Les quatre composants : API (contrat stable), SDK (implémentation par langage), OTLP (protocole de transport), Collector (pipeline receive → process → export)
-
Les trois signaux sont largement stables : traces (GA 2021), métriques (GA 2023), logs (GA 2023) — mais la maturité varie selon le langage/SDK. Les profiles arrivent en 4ᵉ signal
-
Le Collector est le routeur central — receivers pour les entrées, processors pour les transformations, exporters pour les sorties. Configuration YAML, déploiement en agent, sidecar ou gateway
-
Auto-instrumentation + instrumentation manuelle se combinent : zero-code pour la couverture de base, manuelle pour le contexte métier
-
Adoptez progressivement : traces d’abord sur 1-2 services, puis corrélation logs, puis métriques — ne pas tout instrumenter d’un coup
- OpenTelemetry Documentation : opentelemetry.io/docs — documentation officielle du projet
- OpenTelemetry Collector : opentelemetry.io/docs/collector — architecture et configuration
- OpenTelemetry Specification : opentelemetry.io/docs/specs/otel — spécifications techniques (API, SDK, OTLP)
- CNCF OpenTelemetry : cncf.io/projects/opentelemetry — statut du projet dans la CNCF
- Statut par langage : opentelemetry.io/status — maturité de chaque signal par SDK