Infrastructure

OpenTelemetry Collector : diagnostiquer une perte de télémétrie avant d’augmenter la mémoire

Un runbook de production pour localiser les pertes entre receivers, processors, queues et exporters, puis valider un changement de capacité ou rollbacker proprement.

05 août 2026 opentelemetrycollectorobservabilitytelemetrytracesmetricslogsprometheuskubernetesautomationrunbookrollbackproduction

Un dashboard présente des trous après un pic de trafic. Les traces arrivent par intermittence, le volume de logs baisse et le Collector redémarre une ou deux fois. La première proposition consiste souvent à augmenter la mémoire. Cela peut retarder la prochaine panne, mais ne prouve pas si les données ont été refusées par le receiver, supprimées par un processor, bloquées dans une queue d’export, rejetées par le backend ou perdues pendant un redémarrage.

Le cas d’usage est un OpenTelemetry Collector déployé comme gateway Kubernetes entre les applications et un ou plusieurs backends d’observabilité distants. Le runbook doit localiser la première perte mesurable, contenir le pipeline concerné et décider s’il faut ajuster la capacité, corriger le chemin aval, scaler horizontalement ou restaurer la configuration précédente.

Figer le pipeline et la fenêtre d’incident

Ne partez pas du pod qui a consommé le plus de mémoire. Documentez le trajet du signal manquant et les versions actives pendant la rupture.

yaml otel-drop-incident.yml
incident:
start: <timestamp>
end: <timestamp>
missing_signal: traces
affected_services:
  - checkout-api

pipeline:
clients: application SDKs
receiver: otlp
processors:
  - memory_limiter
  - resource
  - batch
exporter: otlphttp/primary
backend: <observability-backend>

versions:
collector_image: <immutable-image-reference>
configuration: <config-version>
deployment: <deployment-revision>

evidence:
- collector internal metrics
- collector logs and restart events
- backend ingestion status
- client export errors
- configuration and rollout timeline

Séparez traces, métriques et logs même s’ils utilisent le même receiver et le même exporter. Leurs débits, batchs, chaînes de processors et comportements de panne peuvent différer.

Trouver le premier compteur qui diverge

Suivez le pipeline dans l’ordre. Comparez les éléments acceptés et refusés par le receiver, les suppressions des processors, les envois et échecs des exporters, puis l’occupation des queues. Les noms de métriques et labels peuvent varier selon la version et la distribution du Collector : inventoriez l’endpoint avant de figer une requête permanente.

promql 01-collector-loss-boundaries.promql
# Pression au niveau du receiver
sum by (receiver) (rate(otelcol_receiver_refused_spans[5m]))

# Suppressions explicites des processors, lorsqu'elles sont exposées
sum by (processor) (rate(otelcol_processor_dropped_spans[5m]))

# Echecs d'export
sum by (exporter) (rate(otelcol_exporter_send_failed_spans[5m]))

# Saturation de la queue
max by (exporter) (
otelcol_exporter_queue_size
/ clamp_min(otelcol_exporter_queue_capacity, 1)
)

Utilisez les compteurs équivalents pour métriques et logs. Une hausse des refus du receiver pointe vers l’amont du traitement. Une acceptation stable suivie de suppressions côté processor indique une règle explicite ou une protection de ressources. Des échecs d’export avec une queue qui se remplit pointent vers l’aval : DNS, TLS, authentification, throttling, disponibilité du backend ou débit d’export insuffisant.

Corréler la perte avec la pression sur les ressources

La mémoire du Collector n’est pas un diagnostic. Placez sur la même chronologie le remplissage des queues, les refus, le throttling CPU, la mémoire résidente, la pression du garbage collector et les redémarrages.

text collector-pressure-reading.txt
La queue monte, les erreurs d'export aussi, puis la mémoire suit
Diagnostiquer d'abord la destination et le débit de l'exporter

Les refus du receiver montent avec un memory_limiter actif
Confirmer la charge soutenue, le budget mémoire et les retries amont

Le pod redémarre sans preuve de refus ou d'échec d'export
Vérifier OOMKilled, probes, pression du nœud et télémétrie interne absente

Le volume backend baisse mais les compteurs Collector restent équilibrés
Vérifier ingestion, indexation, périmètre de requête et rétention du backend

Un seul service disparaît
Vérifier son SDK, endpoint, sampling et attributs avant de redimensionner la gateway

La relation temporelle compte. Une queue remplie avant la hausse mémoire suggère une pression aval mise en tampon. Une hausse mémoire avant les queues pointe plutôt vers le coût de traitement, la cardinalité, des batchs trop volumineux ou un autre composant en mémoire.

Prouver le chemin aval

Les erreurs d’export doivent être classées, pas seulement additionnées. Lisez codes de statut et erreurs de transport avec les preuves DNS, TLS et d’identité. Une queue plus grande ne corrigera ni certificat incorrect, ni credential expiré, ni egress bloqué, ni throttling du backend.

N’utilisez un debug exporter que sur un pipeline de diagnostic borné ou un canary. Il peut prouver que le Collector reçoit et traite un échantillon, mais une sortie verbeuse sur le trafic de production peut exposer des données sensibles et ajouter de la charge.

yaml bounded-debug-pipeline.example.yml
exporters:
debug/incident:
  verbosity: basic

service:
pipelines:
  traces/incident:
    receivers: [otlp/incident]
    processors: [memory_limiter, batch]
    exporters: [debug/incident]

operating_rule:
scope: isolated test receiver and synthetic trace only
duration: one diagnostic window
forbidden: production payload dump

La section operating_rule est une consigne d’exploitation, pas une configuration Collector. Conservez-la dans le dossier de changement plutôt que dans le fichier déployé.

Dimensionner les queues à partir d’un budget de panne

N’agrandissez pas une queue parce qu’elle a atteint 100 %. Déduisez sa capacité du débit entrant accepté, de la taille moyenne et haute des requêtes, de l’indisponibilité aval tolérable, du budget mémoire ou disque et de la capacité de rattrapage.

text queue-capacity-model.txt
Entrées
éléments ou requêtes acceptés par seconde
taille moyenne et percentile haut des requêtes
durée maximale d'indisponibilité aval à absorber
budget mémoire ou disque disponible pour le Collector
débit d'export après reprise

Questions de validation
La queue absorbe-t-elle la fenêtre d'indisponibilité prévue ?
L'exporter peut-il drainer plus vite que l'arrivée de nouvelles données ?
L'expiration des retries couvre-t-elle la fenêtre supportée ?
La queue tient-elle sous la limite de ressources du Collector ?
La perte est-elle acceptable au-delà du budget de panne ?

Une queue en mémoire échange de la RAM contre une résilience courte et se vide lors d’un redémarrage. Une queue persistante modifie les scénarios de récupération et de panne stockage ; elle doit être testée avec l’extension, le volume et le comportement d’arrêt réels. Aucune des deux ne supprime le besoin d’un horizon de retry borné.

Modifier un seul goulot à la fois

Un changement défendable doit nommer la frontière diagnostiquée. Si le backend était indisponible, corrigez la connectivité ou l’identité avant la mémoire. Si le débit d’export reste inférieur au flux entrant, validez la concurrence de l’exporter ou scalez. Si le memory limiter refuse une charge attendue, recalculez ensemble les budgets du pod et du limiter.

yaml collector-capacity-change.example.yml
processors:
memory_limiter:
  check_interval: <tested-interval>
  limit_mib: <derived-hard-limit>
  spike_limit_mib: <derived-spike-budget>
batch:
  send_batch_size: <measured-batch-size>
  timeout: <tested-timeout>

exporters:
otlphttp/primary:
  endpoint: <backend-endpoint>
  sending_queue:
    enabled: true
    queue_size: <derived-capacity>
  retry_on_failure:
    enabled: true
    max_elapsed_time: <supported-outage-window>

Placez la protection des ressources tôt dans la chaîne et conservez le batching après filtres et transformations. Vérifiez le schéma exact de la version déployée avant rollout : les options des composants évoluent.

Tester la correction sur un canary avec comptage des pertes

Envoyez un flux synthétique identifiable vers un seul Collector canary. Augmentez progressivement la charge et injectez une indisponibilité aval bornée. Le test doit observer à la fois la complétude de la télémétrie et la stabilité du Collector.

yaml collector-canary-acceptance.yml
canary:
signals: [traces, metrics, logs]
stages:
  - steady_baseline
  - expected_peak
  - bounded_backend_failure
  - recovery_and_queue_drain

acceptance:
receiver_refusals: zero_during_supported_load
unexplained_processor_drops: zero
queue: drains_after_backend_recovery
exporter_failures: return_to_baseline
restarts: zero
backend_count: reconciled_with_sent_synthetic_items
recovery: faster_than_new_input

negative_checks:
- unsupported_outage_exceeds_budget_and_emits_clear_loss_signal
- debug_exporter_does_not_receive_production_traffic
- previous_configuration_remains_deployable

Réconciliez les volumes avec un trafic synthétique, pas avec des traces métier samplées. Sampling et filtrage sont des frontières de perte intentionnelles à exclure d’un contrôle de conservation de bout en bout.

Décider et rollbacker

Conservez le changement si la première frontière de perte disparaît sous la charge de pointe attendue, si la queue se vide après reprise, si la mémoire reste dans le budget testé et si le backend reçoit le flux synthétique. Scalez horizontalement si le débit, et non l’absorption d’une panne transitoire, constitue la limite. Corrigez le chemin aval si les échecs d’export restent le déclencheur.

Rollbackez si le canary introduit de nouveaux refus, allonge le rattrapage, redémarre sous la même charge ou masque la perte sans améliorer les volumes de bout en bout. Restaurez ensemble l’image et la configuration précédentes, retirez la route canary et rejouez le même test synthétique. Si l’ancienne version perd aussi des données, gardez l’incident ouvert : le rollback a restauré un état, pas la qualité de service.

Conclusion

La perte de télémétrie devient exploitable quand chaque frontière du pipeline expose un signal accepté, refusé, supprimé, mis en queue ou échoué. La mémoire n’est qu’une partie de cette chaîne.

Trouvez le premier compteur divergent, prouvez le chemin aval, dimensionnez la résilience à partir d’un budget de panne explicite et testez la correction avec une réconciliation synthétique. La décision de production devient alors nette : conserver le Collector ajusté, scaler le pipeline, corriger le backend ou restaurer le bundle précédent avec la preuve que le rollback a réellement aidé.