OpenTelemetryCollectorObservabilitéTélémétrie

Observer l'observateur : la télémétrie interne de l'OpenTelemetry Collector

Logs, métriques et traces que le Collector émet sur lui-même : toutes les options de service::telemetry, stdout ou OTLP pour les logs, Prometheus ou OTLP pour les métriques, et comment tout configurer.

Le Collector est souvent la pièce la plus critique de votre chaîne d’observabilité : tout transite par lui. S’il ralentit, sature sa file ou laisse tomber des données, c’est tout votre pipeline qui est aveugle — et vous avec. D’où la question : qui observe l’observateur ?

Bonne nouvelle, le Collector est lui-même instrumenté. Il émet ses propres logs, métriques et traces, et tout se configure au même endroit : la section service::telemetry. Cet article fait le tour des options, signal par signal, avec des exemples concrets — notamment le choix stdout ou OTLP pour les logs et Prometheus ou OTLP pour les métriques.

Le contexte de versions : depuis la v0.123 du Collector, la configuration de la télémétrie interne s’appuie sur la config déclarative du SDK OpenTelemetry (readers, processors, exporters). C’est ce schéma moderne que nous décrivons ici. L’ancien champ service::telemetry::metrics::address est déprécié au profit de readers.

La carte générale : service::telemetry

Toute la télémétrie interne se déclare sous service::telemetry, avec quatre sous-sections :

service:
  telemetry:
    resource: {}   # attributs de ressource communs aux 3 signaux
    logs: {}       # journalisation du Collector
    metrics: {}    # métriques sur le Collector lui-même
    traces: {}     # traces internes (expérimental)
flowchart LR
    C[OpenTelemetry Collector] --> T[service::telemetry]
    T --> L[Logs<br/>stderr · fichier · OTLP]
    T --> M[Métriques<br/>Prometheus :8888 · OTLP]
    T --> Tr[Traces<br/>OTLP · expérimental]

Chaque signal peut rester local (stderr, endpoint Prometheus) ou être exporté vers un backend via OTLP. On peut même combiner les deux.

Les logs : du stderr lisible au push OTLP

Par défaut, le Collector écrit ses logs sur stderr, au format console (lisible par un humain), au niveau info. Voici l’ensemble des options :

service:
  telemetry:
    logs:
      level: info                 # debug | info | warn | error  (défaut: info)
      encoding: console           # console (lisible) | json (machine)
      development: false          # mode dev de zap (stacktraces verbeuses)
      disable_caller: false       # n'annote plus chaque ligne avec fichier:ligne
      disable_stacktrace: false   # désactive la capture auto des stacktraces
      output_paths: [stderr]      # destinations des logs (stderr, stdout, /var/log/otelcol.log…)
      error_output_paths: [stderr]# où zap écrit ses propres erreurs internes
      initial_fields:             # champs ajoutés à CHAQUE entrée de log
        service: edge-collector
      sampling:                   # limite le volume en cas de logs répétitifs
        enabled: true
        tick: 10s                 # fenêtre d'échantillonnage
        initial: 10               # nb de logs identiques laissés passer par fenêtre
        thereafter: 100           # ensuite, 1 sur N (thereafter: 0 = tout couper)

En production : passez en JSON

Pour une ingestion par une stack de logs (Loki, Elastic, un autre Collector…), le format json est quasi obligatoire — il rend chaque champ structuré et requêtable :

service:
  telemetry:
    logs:
      level: info
      encoding: json # permet de définit l'encodage en json
      initial_fields:
        cluster: prod-eu-west-1

Exporter les logs en OTLP

Au-delà de stdout/stderr, vous pouvez émettre les logs du Collector en OTLP vers un backend, grâce à la sous-section processors (le même mécanisme de log record processors que dans le SDK OpenTelemetry) :

service:
  telemetry:
    logs:
      level: info
      encoding: json            # les logs locaux restent aussi sur stderr
      processors:
        - batch:                # batch (recommandé) ou simple (sync, pour debug)
            exporter:
              otlp:
                protocol: http/protobuf   # ou grpc
                endpoint: https://otlp.example.com:4318
                headers:
                  - name: Authorization
                    value: "Bearer ${env:OTLP_TOKEN}"

Utilisez console comme exporter de processors si vous voulez voir les logs au format OTLP sur la sortie standard (utile en debug). Et préférez batch à simple en production : simple exporte de façon synchrone à chaque log et peut devenir un goulot d’étranglement.

Les métriques : Prometheus, OTLP, ou les deux

Le Collector expose par défaut ses métriques internes sur un endpoint Prometheus : http://127.0.0.1:8888/metrics. Deux leviers principaux : le niveau de détail (level) et les lecteurs (readers).

Le niveau de verbosité

service:
  telemetry:
    metrics:
      level: normal   # none | basic | normal | detailed
Niveau Ce qu’il produit
none Aucune métrique interne (désactive complètement).
basic Le strict essentiel : compteurs d’accept/refus, débits.
normal Défaut. basic + tailles de file, batchs, etc.
detailed Tout, y compris les métriques RPC/HTTP par appel — forte cardinalité, à réserver au diagnostic.

Quelques métriques que vous surveillerez en priorité (préfixe otelcol_) :

  • otelcol_receiver_accepted_spans / otelcol_receiver_refused_spans
  • otelcol_exporter_sent_spans / otelcol_exporter_send_failed_spans
  • otelcol_exporter_queue_size / otelcol_exporter_queue_capacity (saturation !)
  • otelcol_processor_batch_batch_send_size
  • otelcol_process_uptime, otelcol_process_memory_rss, otelcol_process_runtime_heap_alloc_bytes

Ces métriques ne sont pas réservées aux composants natifs : vos propres composants peuvent émettre les leurs au même endroit. C’est précisément le rôle du TelemetryBuilder généré par mdatagen — vous déclarez vos compteurs dans metadata.yaml, et ils ressortent ici, préfixés otelcol_, exactement comme les métriques natives. Le mécanisme (section metadata.yaml + mdatagen) est détaillé dans Développer son propre receiver OpenTelemetry.

Option A — endpoint Prometheus (pull)

Pour qu’un Prometheus puisse scraper le Collector dans un cluster, il faut souvent écouter sur 0.0.0.0 (le défaut 127.0.0.1 n’est joignable que localement) :

service:
  telemetry:
    metrics:
      level: normal
      readers:
        - pull:
            exporter:
              prometheus:
                host: 0.0.0.0
                port: 8888
                without_type_suffix: true   # supprime les suffixes _total, etc.
                without_units: true         # supprime les suffixes d'unité

Option B — push OTLP (periodic)

Pour pousser les métriques vers un backend OTLP à intervalle régulier :

service:
  telemetry:
    metrics:
      level: normal
      readers:
        - periodic:
            interval: 30s
            exporter:
              otlp:
                protocol: grpc
                endpoint: https://otlp.example.com:4317

Option C — les deux à la fois

readers est une liste : rien n’empêche d’exposer Prometheus et de pousser en OTLP en parallèle.

service:
  telemetry:
    metrics:
      level: detailed
      readers:
        - pull:
            exporter:
              prometheus: { host: 0.0.0.0, port: 8888 }
        - periodic:
            interval: 60s
            exporter:
              otlp: { protocol: http/protobuf, endpoint: https://otlp.example.com:4318 }

Vous pouvez aussi affiner les métriques produites avec des views (renommage, agrégation, filtrage par instrument_name) — utile pour maîtriser la cardinalité d’un niveau detailed.

Les traces internes (expérimental)

Le Collector peut tracer son propre fonctionnement (le cheminement interne d’un batch à travers les composants). Ces traces ne sont pas émises par défaut : il faut déclarer des processors avec un exporter OTLP.

service:
  telemetry:
    traces:
      processors:
        - batch:
            exporter:
              otlp:
                protocol: http/protobuf
                endpoint: https://otlp.example.com:4318
      # propagators: [tracecontext, b3]   # propagateurs de contexte (optionnel)

⚠️ La télémétrie de traces interne est expérimentale : la documentation ne garantit ni la stabilité des spans ni leur compatibilité d’une version à l’autre. Pratique pour diagnostiquer un Collector, à manier avec prudence en production.

Les attributs de ressource

resource ajoute des attributs communs aux trois signaux — typiquement de quoi identifier l’instance dans une flotte de Collectors :

service:
  telemetry:
    resource:
      service.name: edge-collector
      service.version: 1.4.2
      deployment.environment: production
      service.instance.id: null   # mettre à null DÉSACTIVE l'attribut auto-généré

Le Collector renseigne automatiquement service.name, service.version et un service.instance.id aléatoire ; vous pouvez les surcharger ou les neutraliser en les fixant à null.

Pièges et bonnes pratiques

  • Évitez la boucle de rétroaction. Si vous exportez la télémétrie interne en OTLP vers un pipeline du même Collector, le moindre incident s’auto- amplifie. Pointez vers un backend externe ou un Collector dédié au monitoring. Le plus simple et le plus robuste reste d’exposer l’endpoint Prometheus et de le faire scraper par un Prometheus local : le pull est découplé du Collector, donc une panne ne se propage pas — et vous gardez les métriques jusqu’à la dernière seconde avant le crash.
  • detailed coûte cher. La forte cardinalité des métriques RPC/HTTP peut surcharger votre TSDB. Réservez ce niveau au diagnostic ponctuel, et taillez avec des views si besoin.
  • Attention au binding réseau. L’endpoint Prometheus écoute sur 127.0.0.1 par défaut (choix de sécurité). En conteneur/K8s, passez à 0.0.0.0 pour le scrape — mais ne l’exposez pas publiquement.
  • Secrets via variables d’environnement. Utilisez ${env:VAR} pour les tokens et endpoints plutôt que de les écrire en clair dans la config.
  • JSON en prod, console en local. encoding: console pour lire en développement, encoding: json dès que les logs sont collectés par une stack.

Côté composants, rappelez-vous que vos propres composants alimentent ces mêmes métriques : un receiver maison déclare sa télémétrie via metadata.yaml et mdatagen, et ses compteurs otelcol_* apparaissent ici aux côtés des composants natifs (voir Développer son propre receiver OpenTelemetry). Et tout cela se déploie dans la distribution que vous assemblez avec OCB.

Conclusion

La télémétrie interne du Collector n’est pas un détail : c’est ce qui transforme une boîte noire au cœur de votre infrastructure en un composant observable et diagnosticable. Quelques lignes sous service::telemetry suffisent pour choisir où vont vos logs (stderr, fichier, OTLP), comment vos métriques sont exposées (Prometheus, OTLP, les deux) et, au besoin, tracer le Collector lui-même.

La règle d’or : traitez votre Collector comme n’importe quel service de production — il mérite ses propres dashboards et ses propres alertes.

Si vous souhaitez mettre en place le monitoring de votre plateforme d’observabilité ou auditer votre configuration du Collector, parlons-en.

Domande frequenti

Où se configure la télémétrie interne de l'OpenTelemetry Collector ?

Tout se déclare sous service::telemetry, avec quatre sous-sections : resource (attributs communs), logs, metrics et traces. Chaque signal peut rester local (stderr, endpoint Prometheus) ou être exporté vers un backend en OTLP — et les deux peuvent se combiner.

Sur quel port le Collector expose-t-il ses métriques internes ?

Par défaut sur l’endpoint Prometheus http://127.0.0.1:8888/metrics. Pour qu’un Prometheus distant puisse le scraper dans un cluster, il faut écouter sur 0.0.0.0 via un reader de type pull (host: 0.0.0.0, port: 8888).

Vaut-il mieux exposer les métriques en Prometheus ou les pousser en OTLP ?

Les deux fonctionnent et sont combinables, car readers est une liste. Le plus robuste reste d’exposer l’endpoint Prometheus et de le faire scraper par un Prometheus local : le pull est découplé du Collector, donc une panne ne se propage pas. Pousser la télémétrie interne en OTLP vers un pipeline du même Collector risque une boucle de rétroaction qui auto-amplifie le moindre incident.

À quoi sert le niveau (`level`) des métriques internes du Collector ?

Il règle le détail des métriques : none, basic, normal (défaut) ou detailed. Le niveau detailed ajoute les métriques RPC/HTTP par appel, à très forte cardinalité — à réserver au diagnostic ponctuel, car il peut surcharger votre TSDB.

Sylvain Germe

Esperto freelance di OpenTelemetry con sede a Lille. Aiuta i team con l'instrumentazione, il tracing distribuito e la riduzione dei costi di osservabilità.

Torna al blog