OpenTelemetry OpenTelemetry

Prepara el Collector para producción: límites de memoria, batching y reintentos

Configura processors, colas y almacenamiento persistente para que la telemetría sobreviva a sobrecargas e interrupciones.

12 min Intermedio

Un Collector que funciona en un portátil puede caerse en producción: un pico de tráfico agota la memoria, una interrupción del backend descarta datos o un reinicio pierde todo lo que estaba en tránsito. Las soluciones son todas configuración. Esta guía cubre los processors y los ajustes de exporter que todo Collector de producción debería tener, y el orden en que ponerlos.

El pipeline base

processors:
  memory_limiter:
    check_interval: 1s
    limit_percentage: 80
    spike_limit_percentage: 20
  batch:
    timeout: 5s
    send_batch_size: 8192

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

El orden importa: los processors se ejecutan en el orden en que se listan. memory_limiter va primero para que la contrapresión llegue a los receivers antes de que nada más consuma memoria. batch va al final, tras cualquier filtrado o enriquecimiento, para que los lotes se construyan con los datos finales.

memory_limiter

Vigila la memoria del Collector y rechaza datos nuevos cuando el uso es demasiado alto, de modo que el proceso se ralentiza en lugar de ser terminado por el sistema operativo.

processors:
  memory_limiter:
    check_interval: 1s
    limit_mib: 4000
    spike_limit_mib: 800
  • check_interval es con qué frecuencia se mide la memoria. Se recomienda un valor de 1s, y el valor predeterminado de 0s desactiva la comprobación periódica.
  • limit_mib es el límite estricto de memoria de heap. El proceso completo normalmente usa algo más.
  • spike_limit_mib es el salto máximo esperado entre comprobaciones, y por defecto es el 20 por ciento del límite. El límite blando es limit_mib menos spike_limit_mib (aquí 3200 MiB).
  • limit_percentage y spike_limit_percentage expresan los mismos límites como una proporción de la memoria disponible (Linux con cgroups). Se adaptan a contenedores donde el límite de memoria lo define Kubernetes. Si limit_mib también está definido, tiene precedencia.

Por encima del límite blando, el processor rechaza datos devolviendo un error al componente anterior, y los emisores bien comportados reintentan o reducen el ritmo. Por encima del límite estricto también fuerza la recolección de basura. Defínelo algo por debajo del límite de memoria del contenedor para que actúe antes que el kernel.

batch

El batching agrupa elementos para que las exportaciones sean menos y más grandes, lo que ahorra red y trabajo del backend.

processors:
  batch:
    timeout: 5s            # envía tras este tiempo aunque el lote no esté lleno
    send_batch_size: 8192  # tamaño de lote objetivo
    send_batch_max_size: 0 # 0 significa sin límite superior

Ajusta timeout para la latencia y send_batch_size para el rendimiento. Las versiones recientes del Collector también pueden agrupar dentro de la cola de un exporter; consulta la documentación del exporter helper para tu versión.

Cola del exporter y reintentos

Los exporters que envían por la red tienen una cola de envío y una política de reintentos. Viven en el exporter, no en un processor, y son lo que te protege de las interrupciones cortas del backend:

exporters:
  otlp/backend:
    endpoint: backend.example.com:4317
    sending_queue:
      enabled: true
      queue_size: 5000        # el valor predeterminado es 1000
    retry_on_failure:
      enabled: true
      initial_interval: 5s
      max_interval: 30s
      max_elapsed_time: 10m   # el valor predeterminado es 300s

Cómo pensar en los números:

  • La cola almacena lotes en búfer mientras el backend está lento o caído. Una cola más grande aguanta incidentes más largos pero usa más memoria.
  • retry_on_failure reintenta con retrasos crecientes, hasta max_elapsed_time. Pasado ese tiempo los datos se descartan.
  • Dimensiona ambos según tu volumen y la interrupción más larga que quieras sobrevivir sin pérdida.

Cola persistente: sobrevive a los reinicios

Por defecto la cola vive en memoria, así que un fallo pierde lo que estaba en cola. Respáldala con disco usando la extensión file_storage:

extensions:
  file_storage:
    directory: /var/lib/otelcol/storage

exporters:
  otlp/backend:
    endpoint: backend.example.com:4317
    sending_queue:
      storage: file_storage

service:
  extensions: [file_storage]
  pipelines:
    traces:
      receivers: [otlp]
      processors: [memory_limiter, batch]
      exporters: [otlp/backend]

Se requieren tres piezas: define la extensión, referénciala en el exporter y habilítala bajo service.extensions. Monta un volumen persistente en ese directorio, por ejemplo un PersistentVolumeClaim para un StatefulSet. Aun así se pueden perder datos si el disco se llena o falla, o si el backend permanece caído más allá del límite de reintentos, así que monitoriza el uso del disco.

Processors útiles más allá de lo básico

Añadir o cambiar atributos:

processors:
  resource/env:
    attributes:
      - key: deployment.environment.name
        value: production
        action: upsert
  attributes/scrub:
    actions:
      - key: http.request.header.authorization
        action: delete
      - key: user.email
        action: hash

resource edita atributos que describen al productor (aplicados a un lote entero), y attributes edita atributos por span, por punto de métrica o por registro de log. Úsalos para añadir etiquetas de entorno y para eliminar o aplicar hash a valores sensibles antes de que los datos salgan de tu red.

Descartar ruido con el processor filter, escrito en OpenTelemetry Transformation Language (OTTL):

processors:
  filter/health:
    error_mode: ignore
    traces:
      span:
        - 'attributes["url.path"] == "/healthz"'
        - 'attributes["url.path"] == "/ready"'

Transformar datos con el processor transform:

processors:
  transform/normalize:
    error_mode: ignore
    trace_statements:
      - context: span
        statements:
          - set(attributes["team"], "payments") where resource.attributes["service.name"] == "checkout"

OTTL es potente, así que prueba las sentencias con el exporter debug sobre una copia de tus datos antes de habilitarlas en producción. La sintaxis de las sentencias y los contextos disponibles cambian entre versiones, así que consulta el README del processor para la tuya. Estos processors están en la distribución contrib.

Protege el propio Collector

  • Define requests y limits de recursos de Kubernetes, y mantén memory_limiter por debajo del limit.
  • Añade health_check y úsalo para las probes de liveness y readiness.
  • Monitoriza las propias métricas del Collector en el puerto 8888 para ver el tamaño de las colas, los elementos descartados y los datos rechazados. Alerta cuando otelcol_exporter_queue_size se acerque a su capacidad o cuando los exporters informen de fallos de envío.
  • Ejecuta más de una réplica detrás de un Service para los gateways, y dimensiona una sola réplica para la ráfaga que esperas.

Lista de comprobación

  • memory_limiter es el primer processor en cada pipeline.
  • batch es el último processor.
  • Los exporters de red tienen una cola de envío y una política de reintentos dimensionadas para tu tolerancia a interrupciones.
  • Hay una cola persistente configurada donde la pérdida de datos es inaceptable.
  • Los atributos sensibles se eliminan o se les aplica hash en el borde.
  • Hay health checks, límites de recursos y métricas del Collector en su sitio.

Guías populares