Technique
OpenTelemetry de bout en bout
Pour : ingénieurs et SRE · architectes · managers d’équipePrérequis : Avoir lu L'observabilité en 10 minutes ou savoir ce que sont une métrique, un log et une trace.
L’observabilité en 10 minutes a présenté les signaux sur un exemple : un paiement trop lent. Cette page montre comment ces signaux sont produits et transportés avec OpenTelemetry. On suit un seul span, celui de l’appel à la banque, de l’application jusqu’au stockage.
Ce qu’est OpenTelemetry
Section intitulée « Ce qu’est OpenTelemetry »OpenTelemetry (souvent abrégé OTel) est un projet open source de la CNCF, la fondation qui héberge aussi Kubernetes et Prometheus. Il est né de la fusion de deux projets antérieurs, OpenTracing et OpenCensus (présentation officielle).
OpenTelemetry n’est pas un outil de stockage ni de visualisation. Il produit et transporte la télémétrie. Le stockage reste au choix : Prometheus, Thanos, Mimir ou VictoriaMetrics pour les métriques, Tempo ou Jaeger pour les traces, Loki ou Elasticsearch pour les logs, ou une solution commerciale.
Le projet regroupe six briques :
| Brique | Rôle, en une phrase |
|---|---|
| Spécification | le texte qui dit comment tout doit fonctionner, langage par langage |
| API | les fonctions que le code appelle pour créer un span ou une métrique |
| SDK | la bibliothèque qui implémente l’API : elle échantillonne, regroupe et exporte |
| OTLP | le protocole de transport commun à tous les signaux |
| Collector | un programme autonome qui reçoit, transforme et réexpédie la télémétrie |
| Conventions sémantiques | la liste des noms d’attributs standard et de leur signification |
Le trajet d’un span
Section intitulée « Le trajet d’un span »Voici le chemin complet. Chaque étape est détaillée ensuite.
flowchart LR
A["Application<br/>service payment"] -->|"API"| S["SDK<br/>échantillonnage, lots"]
S -->|"OTLP"| R
subgraph COL["Collector"]
R["Receiver<br/>otlp"] --> P["Processors<br/>memory_limiter, batch"] --> E["Exporters"]
end
E -->|"OTLP"| B[("Stockage<br/>des traces")]
E --> D["debug<br/>console"]
1. L’instrumentation crée le span
Section intitulée « 1. L’instrumentation crée le span »Instrumenter, c’est ajouter au programme le code qui produit la télémétrie. Il existe deux façons de le faire.
L’instrumentation automatique (zero-code) ne demande aucune modification du code. Un agent ou un lanceur intercepte les bibliothèques connues : serveur web, client HTTP, pilote de base de données. Il crée les spans tout seul. C’est la meilleure façon de commencer.
L’instrumentation manuelle consiste à appeler l’API dans son propre code. Elle sert à ajouter ce que l’automatique ne peut pas deviner : une étape métier, un attribut comme le type de carte.
En pratique, on combine les deux. L’automatique donne le squelette de la trace. Le manuel ajoute le sens.
2. Le SDK prépare l’envoi
Section intitulée « 2. Le SDK prépare l’envoi »Le SDK reçoit les spans terminés. Il décide s’il les garde, c’est l’échantillonnage (sampling). Il les regroupe par lots pour limiter le nombre d’envois. Il ajoute les attributs de ressource. Puis il les confie à un exportateur.
3. OTLP transporte
Section intitulée « 3. OTLP transporte »OTLP (OpenTelemetry Protocol) est le format de transport. Il fonctionne sur gRPC (port 4317 par défaut) ou sur HTTP (port 4318) (configuration du Collector). Le même protocole transporte métriques, logs et traces.
4. Le Collector contrôle
Section intitulée « 4. Le Collector contrôle »Le Collector est un programme qui se place entre les applications et les stockages. Il a trois types de composants.
- Les receivers reçoivent les données. Le receiver
otlpécoute sur les ports 4317 et 4318. - Les processors transforment les données, dans l’ordre où ils sont listés.
memory_limiterrefuse des données quand la mémoire approche de sa limite, pour éviter que le Collector tombe.batchregroupe les données avant l’envoi. - Les exporters envoient les données vers un ou plusieurs stockages.
Un pipeline relie des receivers, des processors et des exporters pour un type de signal. On écrit un pipeline pour les traces, un autre pour les métriques.
Le Collector n’est pas obligatoire : un SDK peut exporter directement vers un stockage. Je recommande pourtant de l’utiliser dès le départ. C’est l’endroit unique où l’on protège, filtre et oriente les données, sans toucher aux applications.
5. Le stockage conserve et affiche
Section intitulée « 5. Le stockage conserve et affiche »Le stockage indexe les spans par identifiant de trace. L’interface reconstruit la cascade vue dans la page précédente. L’explorateur de traces montre à quoi ressemble ce résultat.
Un exemple minimal
Section intitulée « Un exemple minimal »L’exemple suivant instrumente un service Python et fait tourner un Collector qui affiche les données reçues dans sa console.
Instrumenter un service Python sans toucher au code
Section intitulée « Instrumenter un service Python sans toucher au code »Les commandes viennent de la documentation Python zero-code d’OpenTelemetry. app.py est votre application.
pip install opentelemetry-distro opentelemetry-exporter-otlpopentelemetry-bootstrap -a install
export OTEL_SERVICE_NAME=paymentexport OTEL_RESOURCE_ATTRIBUTES=service.version=1.4.2,deployment.environment.name=devexport OTEL_TRACES_EXPORTER=otlpexport OTEL_METRICS_EXPORTER=otlpexport OTEL_EXPORTER_OTLP_PROTOCOL=grpcexport OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
opentelemetry-instrument python app.pyopentelemetry-bootstrap détecte les bibliothèques installées et ajoute les instrumentations correspondantes. opentelemetry-instrument lance l’application avec ces instrumentations actives.
Ajouter un span métier à la main
Section intitulée « Ajouter un span métier à la main »Pour voir l’étape « autorisation » dans la trace, avec le type de carte, quelques lignes suffisent :
from opentelemetry import trace
tracer = trace.get_tracer("payment")
def authorize(order): with tracer.start_as_current_span("authorize_payment") as span: span.set_attribute("app.payment.card_type", order.card_type) return call_bank(order)Ce span devient l’enfant du span HTTP créé automatiquement. Le préfixe app. signale un attribut propre à l’application, hors conventions standard.
Configurer le Collector
Section intitulée « Configurer le Collector »receivers: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 http: endpoint: 0.0.0.0:4318
processors: memory_limiter: check_interval: 1s limit_percentage: 80 spike_limit_percentage: 20 batch: {}
exporters: debug: verbosity: detailed # Vers un stockage de traces qui accepte OTLP (Tempo, Jaeger, etc.). otlp_grpc/traces: endpoint: traces-backend:4317 tls: insecure: true # lab uniquement, jamais en production
service: pipelines: traces: receivers: [otlp] processors: [memory_limiter, batch] exporters: [debug, otlp_grpc/traces] metrics: receivers: [otlp] processors: [memory_limiter, batch] exporters: [debug]Trois remarques pour lire ce fichier.
memory_limitervient en premier : il doit refuser les données avant tout autre traitement.batchvient en dernier, après les processors qui filtrent ou transforment.- L’exportateur
debugaffiche chaque span dans la console du Collector. C’est le moyen le plus simple de vérifier que les données arrivent. - Les versions récentes du Collector nomment l’exportateur OTLP gRPC
otlp_grpcet l’exportateur OTLP HTTPotlp_http. Les anciens nomsotlpetotlphttprestent acceptés comme alias dépréciés : certaines configurations du site les emploient encore. Vérifiez le nom attendu par votre version.
L’adresse 0.0.0.0 écoute sur toutes les interfaces. La documentation du Collector l’utilise par commodité et recommande localhost quand tous les clients sont locaux.
Ressources et conventions sémantiques
Section intitulée « Ressources et conventions sémantiques »Deux notions reviennent partout. Elles sont simples, mais elles font toute la différence au moment de chercher.
La ressource décrit l’émetteur. Elle est attachée une fois pour toutes à tout ce que le service produit. Exemples : service.name="payment", service.version="1.4.2", deployment.environment.name="dev". Dans l’exemple, elle vient des variables OTEL_SERVICE_NAME et OTEL_RESOURCE_ATTRIBUTES. Sans service.name, impossible de savoir quel service a émis un span.
Les conventions sémantiques fixent le nom et le sens des attributs courants (conventions sémantiques). Une requête HTTP porte http.request.method et http.response.status_code. Une route porte http.route. Tout le monde utilise les mêmes noms, quel que soit le langage.
L’intérêt est concret. Si un service Java et un service Python suivent les conventions, une seule requête retrouve toutes les erreurs HTTP 500 des deux. Si chacun invente ses noms (status, httpCode, code_retour), il faut une requête par équipe.
Les conventions évoluent encore. Certains noms ont changé ces dernières années. Je recommande de fixer la version suivie et de la réviser à chaque montée de version des SDK.
Pour aller plus loin
Section intitulée « Pour aller plus loin »- Pipeline du Collector animé : activer et désactiver les processors pour voir leur effet.
- Échantillonnage en queue : garder toutes les traces en erreur sans tout stocker.
- Coût du Collector : estimer ce que chaque traitement fait gagner en volume.
- Architecture cliquable : une pile complète, brique par brique.
- SLO et alerting : transformer ces signaux en objectifs et en alertes utiles.
- Le glossaire définit Collector, span, trace et convention sémantique.
- OpenTelemetry, What is OpenTelemetry? : origine du projet, briques et indépendance vis-à-vis des stockages.
- OpenTelemetry, Python zero-code instrumentation : commandes d’installation et de lancement.
- OpenTelemetry, Collector configuration : receivers, processors, exporters, pipelines, ports 4317 et 4318.
- OpenTelemetry, Semantic conventions : noms standard des attributs.