Aller au contenu
Outils medium

OpenTelemetry Collector : le routeur de vos données d'observabilité

22 min de lecture

logo opentelemetry

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.

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 config
from jaeger_client import Config as JaegerConfig
from prometheus_client import start_http_server
import logging_loki
# 3 connexions différentes, 3 formats différents
jaeger_tracer = JaegerConfig(...).initialize_tracer()
start_http_server(8000) # Endpoint Prometheus
loki_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

Avec l’OpenTelemetry Collector, vos applications envoient tout au même endroit :

Architecture OpenTelemetry Collector : Application → Receiver → Processor → Exporter → Backends (Tempo, Prometheus, Loki)

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

Le Collector fonctionne comme un pipeline avec trois étapes :

Les receivers écoutent sur des ports et ingèrent les données entrantes.

ReceiverCe qu’il reçoitPort par défaut
otlpTraces, métriques, logs au format OpenTelemetry4317 (gRPC), 4318 (HTTP)
jaegerTraces au format Jaeger14268
prometheusMétriques scrapées depuis des endpoints-
filelogLogs depuis des fichiers-

En pratique : utilisez otlp pour vos nouvelles applications. Les autres receivers servent à intégrer des outils existants.

Les processors modifient les données entre réception et envoi.

ProcessorCe qu’il faitQuand l’utiliser
batchRegroupe les données (réduit le trafic réseau)Toujours
memory_limiterÉvite les OOM en limitant la mémoireToujours
filterSupprime les données inutilesRéduire les coûts
attributesAjoute/supprime des métadonnéesEnrichir ou masquer des données sensibles
k8sattributesAjoute les métadonnées Kubernetes (pod, namespace…)Sur Kubernetes

Les exporters transmettent les données aux backends finaux.

ExporterDestinationQuand l’utiliser
otlpTout backend compatible OTLP (Tempo, Jaeger, Honeycomb…)Traces et métriques
prometheusremotewritePrometheus, Mimir, CortexMétriques
lokiLokiLogs
debugConsole (stdout)Dépannage
  1. Créez un fichier de configuration

    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
    exporters:
    debug:
    verbosity: detailed
    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: [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) et zpages (port 55679) pour le diagnostic
    • Affiche les traces dans la console (pour vérifier que ça marche)
  2. 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
  3. Vérifiez qu’il fonctionne

    Fenêtre de terminal
    # Vérifier les logs
    docker logs otel-collector
    # Vérifier le health check
    curl 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 ready et le health check passe, le Collector est opérationnel.

Maintenant que le Collector tourne, configurons un pipeline réaliste qui envoie les traces vers Jaeger.

Vous avez besoin de Jaeger. Créez un réseau Docker pour éviter les conflits de ports :

Fenêtre de terminal
# 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.64

L’interface Jaeger est sur http://localhost:16686

Modifiez votre config.yaml :

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 :

  1. Les applications envoient des traces OTLP au Collector (port 4317 ou 4318)
  2. Le Collector limite la mémoire (memory_limiter) pour éviter les OOM
  3. Les traces sont regroupées par batch de 1000 ou toutes les 5 secondes
  4. Les traces sont envoyées à Jaeger ET affichées dans les logs (debug)
Fenêtre de terminal
# Arrêter l'ancien collector
docker stop otel-collector && docker rm otel-collector
# Relancer avec le réseau et la nouvelle config
docker 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.0

C’est la partie la plus importante : comment vos applications envoient-elles des données au Collector ?

Installez le SDK OpenTelemetry dans votre application et configurez l’endpoint.

Fenêtre de terminal
pip install opentelemetry-api opentelemetry-sdk opentelemetry-exporter-otlp
app.py
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
# Configurer l'exporter OTLP vers le Collector
otlp_exporter = OTLPSpanExporter(
endpoint="http://localhost:4317", # Adresse du Collector
insecure=True
)
# Configurer le tracer
provider = TracerProvider()
provider.add_span_processor(BatchSpanProcessor(otlp_exporter))
trace.set_tracer_provider(provider)
# Utiliser
tracer = trace.get_tracer(__name__)
with tracer.start_as_current_span("mon-operation"):
# Votre code ici
print("Cette opération est tracée !")

Pour les frameworks populaires, OpenTelemetry peut instrumenter automatiquement sans modifier le code.

Fenêtre de terminal
pip install opentelemetry-distro opentelemetry-exporter-otlp
opentelemetry-bootstrap -a install
Fenêtre de terminal
# Lancer votre app avec auto-instrumentation
OTEL_SERVICE_NAME=mon-service \
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317 \
opentelemetry-instrument python app.py

Option 3 : Variables d’environnement (Kubernetes)

Section intitulée « Option 3 : Variables d’environnement (Kubernetes) »

Sur Kubernetes, configurez les pods avec des variables d’environnement :

deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: mon-service
spec:
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"
  1. Vérifiez les logs du Collector

    Fenêtre de terminal
    docker logs otel-collector --tail 50

    Si des traces arrivent, vous verrez :

    2026-02-09T10:05:00.000Z info TracesExporter {"kind": "exporter", "data_type": "traces", "name": "otlp/jaeger", "spans": 5}
  2. 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
  3. 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:4317

    Cette commande génère 1 trace de test. Vérifiez qu’elle apparaît dans Jaeger.

Voici une configuration complète pour les trois types de signaux :

config-complet.yaml
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]
SymptômeCause probableSolution
connection refusedCollector ne tourne pas ou mauvais endpointdocker ps + vérifiez l’URL
Pas de traces dans JaegerExporter mal configuréVérifiez les logs du Collector
Traces dans logs mais pas dans backendBackend injoignableTestez la connexion : curl backend:port
OOM du CollectorPas de memory_limiterAjoutez le processor en premier
Données perduesBatch trop gros ou timeout trop courtRéduisez send_batch_size
Health check échoueCollector crashé ou mal démarrédocker logs otel-collector
zpages inaccessibleExtension non activée ou mauvais portVérifiez service.extensions
Fenêtre de terminal
# État du collector
docker ps | grep otel-collector
# Health check
curl http://localhost:13133/
# Logs récents
docker logs otel-collector --tail 100
# Valider la configuration
docker exec otel-collector otelcol-contrib validate --config /etc/otelcol-contrib/config.yaml
# Debug des pipelines (zpages)
curl http://localhost:55679/debug/pipelinez
curl http://localhost:55679/debug/servicez
curl http://localhost:55679/debug/tracez

Avant de passer en production, validez ces points :

  • Version pinnée : pas de :latest, utilisez 0.145.0 ou 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)
  • Le Collector est un intermédiaire entre vos apps et vos backends
  • Architecture Receiver → Processor → Exporter pour chaque pipeline
  • Utilisez toujours memory_limiter et batch (dans cet ordre)
  • Activez health_check et zpages pour 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

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.