
L’OpenTelemetry Collector est un intermédiaire entre vos applications et vos backends d’observabilité. Au lieu d’envoyer directement vos traces à Jaeger, vos métriques à Prometheus et vos logs à Loki, vos applications envoient tout au Collector — et lui se charge de distribuer les données aux bons endroits.
Ce guide vous explique pourquoi l’utiliser, comment l’installer, et surtout comment connecter vos applications.
À quoi sert le Collector ?
Section intitulée « À quoi sert le Collector ? »Le problème sans Collector
Section intitulée « Le problème sans Collector »Imaginez une application Python qui doit envoyer :
- Des traces à Jaeger
- Des métriques à Prometheus
- Des logs à Loki
Sans Collector, votre code ressemble à ça :
# Chaque backend a son SDK, son format, sa configfrom jaeger_client import Config as JaegerConfigfrom prometheus_client import start_http_serverimport logging_loki
# 3 connexions différentes, 3 formats différentsjaeger_tracer = JaegerConfig(...).initialize_tracer()start_http_server(8000) # Endpoint Prometheusloki_handler = logging_loki.LokiHandler(url="http://loki:3100/...")Problèmes :
- Si vous changez de backend traces (Jaeger → Tempo), vous modifiez le code
- Chaque service a sa propre config de connexion
- Pas de filtrage, pas de transformation des données
La solution : le Collector comme intermédiaire
Section intitulée « La solution : le Collector comme intermédiaire »Avec l’OpenTelemetry Collector, vos applications envoient tout au même endroit :
Avantages :
- Code simplifié : votre app ne connaît qu’OTLP, pas les backends
- Changement de backend : modifiez la config du Collector, pas le code
- Transformation : filtrez, enrichissez, samplez les données avant envoi
- Résilience : le Collector bufferise si un backend est temporairement indisponible
Comprendre l’architecture
Section intitulée « Comprendre l’architecture »Le Collector fonctionne comme un pipeline avec trois étapes :
1. Receivers : recevoir les données
Section intitulée « 1. Receivers : recevoir les données »Les receivers écoutent sur des ports et ingèrent les données entrantes.
| Receiver | Ce qu’il reçoit | Port par défaut |
|---|---|---|
otlp | Traces, métriques, logs au format OpenTelemetry | 4317 (gRPC), 4318 (HTTP) |
jaeger | Traces au format Jaeger | 14268 |
prometheus | Métriques scrapées depuis des endpoints | - |
filelog | Logs depuis des fichiers | - |
En pratique : utilisez otlp pour vos nouvelles applications. Les autres receivers servent à intégrer des outils existants.
2. Processors : transformer les données
Section intitulée « 2. Processors : transformer les données »Les processors modifient les données entre réception et envoi.
| Processor | Ce qu’il fait | Quand l’utiliser |
|---|---|---|
batch | Regroupe les données (réduit le trafic réseau) | Toujours |
memory_limiter | Évite les OOM en limitant la mémoire | Toujours |
filter | Supprime les données inutiles | Réduire les coûts |
attributes | Ajoute/supprime des métadonnées | Enrichir ou masquer des données sensibles |
k8sattributes | Ajoute les métadonnées Kubernetes (pod, namespace…) | Sur Kubernetes |
3. Exporters : envoyer aux backends
Section intitulée « 3. Exporters : envoyer aux backends »Les exporters transmettent les données aux backends finaux.
| Exporter | Destination | Quand l’utiliser |
|---|---|---|
otlp | Tout backend compatible OTLP (Tempo, Jaeger, Honeycomb…) | Traces et métriques |
prometheusremotewrite | Prometheus, Mimir, Cortex | Métriques |
loki | Loki | Logs |
debug | Console (stdout) | Dépannage |
Installer le Collector
Section intitulée « Installer le Collector »-
Créez un fichier de configuration
config.yaml receivers:otlp:protocols:grpc:endpoint: 0.0.0.0:4317http:endpoint: 0.0.0.0:4318processors:memory_limiter:check_interval: 1slimit_mib: 512spike_limit_mib: 128batch:timeout: 5sexporters:debug:verbosity: detailedextensions:health_check:endpoint: 0.0.0.0:13133zpages:endpoint: 0.0.0.0:55679service:extensions: [health_check, zpages]pipelines:traces:receivers: [otlp]processors: [memory_limiter, batch]exporters: [debug]Cette config minimale :
- Écoute OTLP sur les ports 4317 (gRPC) et 4318 (HTTP)
- Limite la mémoire (
memory_limiter) pour éviter les OOM - Regroupe les données par batch de 5 secondes
- Active
health_check(port 13133) etzpages(port 55679) pour le diagnostic - Affiche les traces dans la console (pour vérifier que ça marche)
-
Lancez le Collector
Fenêtre de terminal docker run -d \--name otel-collector \-p 127.0.0.1:4317:4317 \-p 127.0.0.1:4318:4318 \-p 127.0.0.1:13133:13133 \-v $(pwd)/config.yaml:/etc/otelcol-contrib/config.yaml:ro \otel/opentelemetry-collector-contrib:0.145.0 -
Vérifiez qu’il fonctionne
Fenêtre de terminal # Vérifier les logsdocker logs otel-collector# Vérifier le health checkcurl http://localhost:13133/Ce que vous devez voir :
2026-02-09T10:00:00.000Z info service@v0.145.0/service.go:140 Starting otelcol-contrib...2026-02-09T10:00:00.100Z info service@v0.145.0/service.go:267 Everything is ready. Begin running and processing data.Le health check retourne :
{"status":"Server available"}Si vous voyez
Everything is readyet le health check passe, le Collector est opérationnel.
-
Ajoutez le repo Helm
Fenêtre de terminal helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-chartshelm repo update -
Créez un fichier values.yaml
values.yaml mode: deployment # ou daemonset pour collecter par nodeconfig:receivers:otlp:protocols:grpc:endpoint: 0.0.0.0:4317http:endpoint: 0.0.0.0:4318processors:batch:timeout: 5smemory_limiter:check_interval: 1slimit_mib: 512exporters:debug:verbosity: detailedservice:pipelines:traces:receivers: [otlp]processors: [memory_limiter, batch]exporters: [debug] -
Installez
Fenêtre de terminal helm install otel-collector open-telemetry/opentelemetry-collector \--namespace observability \--create-namespace \-f values.yaml -
Vérifiez
Fenêtre de terminal kubectl get pods -n observability -l app.kubernetes.io/name=opentelemetry-collectorLe pod doit être en
Running.
-
Téléchargez
Fenêtre de terminal # Dernière version stable (février 2026)VERSION="0.145.0"curl -LO "https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v${VERSION}/otelcol-contrib_${VERSION}_linux_amd64.tar.gz"tar -xzf otelcol-contrib_${VERSION}_linux_amd64.tar.gz -
Créez la config (même contenu que pour Docker)
Fenêtre de terminal cat > config.yaml << 'EOF'receivers:otlp:protocols:grpc:endpoint: 0.0.0.0:4317http:endpoint: 0.0.0.0:4318processors:batch:timeout: 5sexporters:debug:verbosity: detailedservice:pipelines:traces:receivers: [otlp]processors: [batch]exporters: [debug]EOF -
Lancez
Fenêtre de terminal ./otelcol-contrib --config config.yaml -
Validez la configuration (optionnel mais recommandé)
Fenêtre de terminal ./otelcol-contrib validate --config config.yaml
Votre premier pipeline : traces vers Jaeger
Section intitulée « Votre premier pipeline : traces vers Jaeger »Maintenant que le Collector tourne, configurons un pipeline réaliste qui envoie les traces vers Jaeger.
Prérequis
Section intitulée « Prérequis »Vous avez besoin de Jaeger. Créez un réseau Docker pour éviter les conflits de ports :
# Créer un réseau partagédocker network create observability
# Lancer Jaeger (uniquement l'UI exposée)docker run -d --name jaeger \ --network observability \ -p 16686:16686 \ jaegertracing/all-in-one:1.64L’interface Jaeger est sur http://localhost:16686
Configuration
Section intitulée « Configuration »Modifiez votre config.yaml :
receivers: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 http: endpoint: 0.0.0.0:4318
processors: memory_limiter: check_interval: 1s limit_mib: 512 spike_limit_mib: 128 batch: timeout: 5s send_batch_size: 1000
exporters: # Exporter vers Jaeger via OTLP otlp/jaeger: endpoint: jaeger:4317 tls: insecure: true
# Garder le debug pour voir ce qui passe debug: verbosity: basic
extensions: health_check: endpoint: 0.0.0.0:13133 zpages: endpoint: 0.0.0.0:55679
service: extensions: [health_check, zpages] pipelines: traces: receivers: [otlp] processors: [memory_limiter, batch] exporters: [otlp/jaeger, debug]Ce qui se passe :
- Les applications envoient des traces OTLP au Collector (port 4317 ou 4318)
- Le Collector limite la mémoire (
memory_limiter) pour éviter les OOM - Les traces sont regroupées par batch de 1000 ou toutes les 5 secondes
- Les traces sont envoyées à Jaeger ET affichées dans les logs (debug)
Redémarrez le Collector
Section intitulée « Redémarrez le Collector »# Arrêter l'ancien collectordocker stop otel-collector && docker rm otel-collector
# Relancer avec le réseau et la nouvelle configdocker run -d \ --name otel-collector \ --network observability \ -p 127.0.0.1:4317:4317 \ -p 127.0.0.1:4318:4318 \ -p 127.0.0.1:13133:13133 \ -v $(pwd)/config.yaml:/etc/otelcol-contrib/config.yaml:ro \ otel/opentelemetry-collector-contrib:0.145.0Connecter vos applications au Collector
Section intitulée « Connecter vos applications au Collector »C’est la partie la plus importante : comment vos applications envoient-elles des données au Collector ?
Option 1 : SDK OpenTelemetry (recommandé)
Section intitulée « Option 1 : SDK OpenTelemetry (recommandé) »Installez le SDK OpenTelemetry dans votre application et configurez l’endpoint.
pip install opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlpfrom opentelemetry import tracefrom opentelemetry.sdk.trace import TracerProviderfrom opentelemetry.sdk.trace.export import BatchSpanProcessorfrom opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
# Configurer l'exporter OTLP vers le Collectorotlp_exporter = OTLPSpanExporter( endpoint="http://localhost:4317", # Adresse du Collector insecure=True)
# Configurer le tracerprovider = TracerProvider()provider.add_span_processor(BatchSpanProcessor(otlp_exporter))trace.set_tracer_provider(provider)
# Utilisertracer = trace.get_tracer(__name__)
with tracer.start_as_current_span("mon-operation"): # Votre code ici print("Cette opération est tracée !")npm install @opentelemetry/api @opentelemetry/sdk-node @opentelemetry/exporter-trace-otlp-grpcconst { NodeSDK } = require('@opentelemetry/sdk-node');const { OTLPTraceExporter } = require('@opentelemetry/exporter-trace-otlp-grpc');
const sdk = new NodeSDK({ traceExporter: new OTLPTraceExporter({ url: 'http://localhost:4317', // Adresse du Collector }),});
sdk.start();
// Dans votre codeconst opentelemetry = require('@opentelemetry/api');const tracer = opentelemetry.trace.getTracer('mon-service');
const span = tracer.startSpan('mon-operation');// Votre codespan.end();go get go.opentelemetry.io/otelgo get go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpcpackage main
import ( "context" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" "go.opentelemetry.io/otel/sdk/trace")
func main() { ctx := context.Background()
// Configurer l'exporter OTLP exporter, _ := otlptracegrpc.New(ctx, otlptracegrpc.WithEndpoint("localhost:4317"), otlptracegrpc.WithInsecure(), )
// Configurer le tracer provider tp := trace.NewTracerProvider( trace.WithBatcher(exporter), ) otel.SetTracerProvider(tp)
// Utiliser tracer := otel.Tracer("mon-service") _, span := tracer.Start(ctx, "mon-operation") defer span.End()}<dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-sdk</artifactId> <version>1.32.0</version></dependency><dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-exporter-otlp</artifactId> <version>1.32.0</version></dependency>import io.opentelemetry.api.trace.Tracer;import io.opentelemetry.api.trace.Span;import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;import io.opentelemetry.sdk.trace.SdkTracerProvider;import io.opentelemetry.sdk.trace.export.BatchSpanProcessor;
public class Application { public static void main(String[] args) { // Configurer l'exporter OtlpGrpcSpanExporter exporter = OtlpGrpcSpanExporter.builder() .setEndpoint("http://localhost:4317") .build();
SdkTracerProvider tracerProvider = SdkTracerProvider.builder() .addSpanProcessor(BatchSpanProcessor.builder(exporter).build()) .build();
Tracer tracer = tracerProvider.get("mon-service");
Span span = tracer.spanBuilder("mon-operation").startSpan(); // Votre code span.end(); }}Option 2 : Auto-instrumentation (zéro code)
Section intitulée « Option 2 : Auto-instrumentation (zéro code) »Pour les frameworks populaires, OpenTelemetry peut instrumenter automatiquement sans modifier le code.
pip install opentelemetry-distro opentelemetry-exporter-otlpopentelemetry-bootstrap -a install# Lancer votre app avec auto-instrumentationOTEL_SERVICE_NAME=mon-service \OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 \opentelemetry-instrument python app.py# Télécharger l'agentcurl -LO https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar# Lancer avec l'agentjava -javaagent:opentelemetry-javaagent.jar \ -Dotel.service.name=mon-service \ -Dotel.exporter.otlp.endpoint=http://localhost:4317 \ -jar mon-app.jarnpm install @opentelemetry/auto-instrumentations-node# Lancer avec auto-instrumentationOTEL_SERVICE_NAME=mon-service \OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 \node --require @opentelemetry/auto-instrumentations-node/register app.jsOption 3 : Variables d’environnement (Kubernetes)
Section intitulée « Option 3 : Variables d’environnement (Kubernetes) »Sur Kubernetes, configurez les pods avec des variables d’environnement :
apiVersion: apps/v1kind: Deploymentmetadata: name: mon-servicespec: template: spec: containers: - name: app image: mon-image env: - name: OTEL_SERVICE_NAME value: "mon-service" - name: OTEL_EXPORTER_OTLP_ENDPOINT value: "http://otel-collector.observability.svc:4317" - name: OTEL_TRACES_EXPORTER value: "otlp"Validation : vérifier que ça fonctionne
Section intitulée « Validation : vérifier que ça fonctionne »-
Vérifiez les logs du Collector
Fenêtre de terminal docker logs otel-collector --tail 50Si des traces arrivent, vous verrez :
2026-02-09T10:05:00.000Z info TracesExporter {"kind": "exporter", "data_type": "traces", "name": "otlp/jaeger", "spans": 5} -
Vérifiez dans Jaeger
Ouvrez http://localhost:16686
- Sélectionnez le service dans le menu déroulant
- Cliquez sur “Find Traces”
- Vous devez voir vos traces
-
Générez du trafic de test
Si vous n’avez pas encore d’application instrumentée, utilisez
telemetrygen:Fenêtre de terminal docker run --rm --network observability \ghcr.io/open-telemetry/opentelemetry-collector-contrib/telemetrygen:0.145.0 \traces --otlp-insecure --otlp-endpoint otel-collector:4317Cette commande génère 1 trace de test. Vérifiez qu’elle apparaît dans Jaeger.
Pipeline complet : métriques, logs et traces
Section intitulée « Pipeline complet : métriques, logs et traces »Voici une configuration complète pour les trois types de signaux :
receivers: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 http: endpoint: 0.0.0.0:4318
# Scraper les métriques Prometheus des apps prometheus: config: scrape_configs: - job_name: 'applications' scrape_interval: 30s static_configs: - targets: ['app1:8080', 'app2:8080']
processors: memory_limiter: check_interval: 1s limit_mib: 512 spike_limit_mib: 128 batch: timeout: 5s send_batch_size: 1000 # Ajouter des attributs à toutes les données resource: attributes: - key: environment value: production action: insert
exporters: # Traces vers Tempo otlp/tempo: endpoint: tempo:4317 tls: insecure: true
# Métriques vers Mimir (compatible remote write) prometheusremotewrite: endpoint: http://mimir:9009/api/v1/push
# Logs vers Loki loki: endpoint: http://loki:3100/loki/api/v1/push labels: resource: service.name: "service_name"
debug: verbosity: basic
extensions: health_check: endpoint: 0.0.0.0:13133 zpages: endpoint: 0.0.0.0:55679
service: extensions: [health_check, zpages] pipelines: traces: receivers: [otlp] processors: [memory_limiter, resource, batch] exporters: [otlp/tempo, debug]
metrics: receivers: [otlp, prometheus] processors: [memory_limiter, resource, batch] exporters: [prometheusremotewrite]
logs: receivers: [otlp] processors: [memory_limiter, resource, batch] exporters: [loki]Dépannage
Section intitulée « Dépannage »| Symptôme | Cause probable | Solution |
|---|---|---|
connection refused | Collector ne tourne pas ou mauvais endpoint | docker ps + vérifiez l’URL |
| Pas de traces dans Jaeger | Exporter mal configuré | Vérifiez les logs du Collector |
| Traces dans logs mais pas dans backend | Backend injoignable | Testez la connexion : curl backend:port |
| OOM du Collector | Pas de memory_limiter | Ajoutez le processor en premier |
| Données perdues | Batch trop gros ou timeout trop court | Réduisez send_batch_size |
| Health check échoue | Collector crashé ou mal démarré | docker logs otel-collector |
| zpages inaccessible | Extension non activée ou mauvais port | Vérifiez service.extensions |
Commandes de diagnostic
Section intitulée « Commandes de diagnostic »# État du collectordocker ps | grep otel-collector
# Health checkcurl http://localhost:13133/
# Logs récentsdocker logs otel-collector --tail 100
# Valider la configurationdocker exec otel-collector otelcol-contrib validate --config /etc/otelcol-contrib/config.yaml
# Debug des pipelines (zpages)curl http://localhost:55679/debug/pipelinezcurl http://localhost:55679/debug/servicezcurl http://localhost:55679/debug/tracezChecklist production
Section intitulée « Checklist production »Avant de passer en production, validez ces points :
- Version pinnée : pas de
:latest, utilisez0.145.0ou supérieur - Pas de conflit de ports : Jaeger et Collector sur le même réseau Docker
- health_check activé :
curl localhost:13133/retourne OK - memory_limiter configuré : évite les OOM
- debug exporter retiré : ou passé en
verbosity: basic - OTEL_EXPORTER_OTLP_PROTOCOL défini : évite les surprises gRPC/HTTP
- Bind localhost en dev :
-p 127.0.0.1:4317:4317 - Labels Loki maîtrisés : faible cardinalité (service, namespace, level)
- Kubernetes : choix clair entre DaemonSet (agent) et Deployment (gateway)
À retenir
Section intitulée « À retenir »- Le Collector est un intermédiaire entre vos apps et vos backends
- Architecture Receiver → Processor → Exporter pour chaque pipeline
- Utilisez toujours
memory_limiteretbatch(dans cet ordre) - Activez
health_checketzpagespour le diagnostic - Vos apps envoient en OTLP : port 4317 (gRPC) ou 4318 (HTTP)
- Pinnez les versions en production, évitez
:latest - Changez de backend en modifiant la config, pas le code