Explorando el Collector de OpenTelemetry

El OpenTelemetry Collector se encuentra en el centro de la arquitectura de OpenTelemetry pero no está relacionado con el W3C Trace Context. En mi demo de trazado, utilizo Jaeger en lugar del Collector. Sin embargo, es ubicuo, como en cada publicación relacionada con OpenTelemetry. Quería explorarlo más a fondo.

En esta publicación, exploro los diferentes aspectos del Collector:

  • El tipo de datos: registros, métricas y trazas
  • Modelos de push y pull
  • Operaciones: lecturas, transformaciones y escrituras

Primeros pasos

A long time ago, observability as we know it didn’t exist; what we had instead was monitoring. Back then, monitoring was a bunch of people looking at screens displaying dashboards. Dashboards themselves consisted of metrics and only system metrics, mainly CPU, memory, and disk usage. For this reason, we will start with metrics.

Prometheus es una de las principales soluciones de monitoreo. Funciona con un modelo basado en pull: Prometheus raspa los puntos finales compatibles de tu aplicación(es) y los almacena internamente.

Utilizaremos el OTEL Collector para raspar un punto final compatible con Prometheus y mostrar el resultado en la consola. Grafana Labs ofrece un proyecto que genera métricas aleatorias para jugar. Por simplicidad, utilizaré Docker Compose; la configuración se ve de la siguiente manera:

YAML

 

version: "3"

services:
  fake-metrics:
    build: ./fake-metrics-generator                                         #1
  collector:
    image: otel/opentelemetry-collector:0.87.0                              #2
    environment:                                                            #3
      - METRICS_HOST=fake-metrics
      - METRICS_PORT=5000
    volumes:
      - ./config/collector/config.yml:/etc/otelcol/config.yaml:ro           #4

  1. No hay una imagen de Docker disponible para el proyecto de métricas falsas; por lo tanto, necesitamos construirla
  2. Última versión del OTEL Collector en el momento de escribir esto
  3. Parametrizar el siguiente archivo de configuración
  4. Todo sucede aquí

Como mencioné anteriormente, el OTEL Collector puede hacer mucho. Por lo tanto, la configuración es todo.

YAML

 

receivers:                                                                  #1
  prometheus:                                                               #2
    config:
      scrape_configs:                                                       #3
        - job_name: fake-metrics                                            #4
          scrape_interval: 3s
          static_configs:
            - targets: [ "${env.METRICS_HOST}:${env.METRICS_PORT}" ]
            
exporters:                                                                  #5
  logging:                                                                  #6
    loglevel: debug
    
service:
  pipelines:                                                                #7
    metrics:                                                                #8
      receivers: [ "prometheus" ]                                           #9
      exporters: [ "logging" ]                                              #10

  1. Lista de receptores. Un receptor lee datos; puede ser de tipo push o pull.
  2. Utilizamos el receptor predefinido prometheus
  3. Definir trabajos de pull
  4. Configuración del trabajo
  5. Lista de exportadores. A diferencia de los receptores, un exportador escribe datos.
  6. El exportador más simple es escribir datos en la salida estándar
  7. Las canalizaciones ensamblan receptores y exportadores
  8. Definir una canalización relacionada con las métricas
  9. La canalización obtiene datos del receptor prometheus previamente definido y los envía al exportador logging,es decir, los imprime

Aquí hay una muestra del resultado:

2023-11-11 08:28:54 otel-collector-collector-1     | StartTimestamp: 1970-01-01 00:00:00 +0000 UTC
2023-11-11 08:28:54 otel-collector-collector-1     | Timestamp: 2023-11-11 07:28:54.14 +0000 UTC
2023-11-11 08:28:54 otel-collector-collector-1     | Value: 83.090000
2023-11-11 08:28:54 otel-collector-collector-1     | NumberDataPoints #1
2023-11-11 08:28:54 otel-collector-collector-1     | Data point attributes:
2023-11-11 08:28:54 otel-collector-collector-1     |      -> fake__embrace_world_class_systems: Str(concept)
2023-11-11 08:28:54 otel-collector-collector-1     |      -> fake__exploit_magnetic_applications: Str(concept)
2023-11-11 08:28:54 otel-collector-collector-1     |      -> fake__facilitate_wireless_architectures: Str(extranet)
2023-11-11 08:28:54 otel-collector-collector-1     |      -> fake__grow_magnetic_communities: Str(challenge)
2023-11-11 08:28:54 otel-collector-collector-1     |      -> fake__reinvent_revolutionary_applications: Str(support)
2023-11-11 08:28:54 otel-collector-collector-1     |      -> fake__strategize_strategic_initiatives: Str(internet_solution)
2023-11-11 08:28:54 otel-collector-collector-1     |      -> fake__target_customized_eyeballs: Str(concept)
2023-11-11 08:28:54 otel-collector-collector-1     |      -> fake__transform_turn_key_technologies: Str(framework)
2023-11-11 08:28:54 otel-collector-collector-1     |      -> fake__whiteboard_innovative_partnerships: Str(matrices)
2023-11-11 08:28:54 otel-collector-collector-1     | StartTimestamp: 1970-01-01 00:00:00 +0000 UTC
2023-11-11 08:28:54 otel-collector-collector-1     | Timestamp: 2023-11-11 07:28:54.14 +0000 UTC
2023-11-11 08:28:54 otel-collector-collector-1     | Value: 53.090000
2023-11-11 08:28:54 otel-collector-collector-1     | NumberDataPoints #2
2023-11-11 08:28:54 otel-collector-collector-1     | Data point attributes:
2023-11-11 08:28:54 otel-collector-collector-1     |      -> fake__expedite_distributed_partnerships: Str(approach)
2023-11-11 08:28:54 otel-collector-collector-1     |      -> fake__facilitate_wireless_architectures: Str(graphical_user_interface)
2023-11-11 08:28:54 otel-collector-collector-1     |      -> fake__grow_magnetic_communities: Str(policy)
2023-11-11 08:28:54 otel-collector-collector-1     |      -> fake__reinvent_revolutionary_applications: Str(algorithm)
2023-11-11 08:28:54 otel-collector-collector-1     |      -> fake__transform_turn_key_technologies: Str(framework)
2023-11-11 08:28:54 otel-collector-collector-1     | StartTimestamp: 1970-01-01 00:00:00 +0000 UTC
2023-11-11 08:28:54 otel-collector-collector-1     | Timestamp: 2023-11-11 07:28:54.14 +0000 UTC
2023-11-11 08:28:54 otel-collector-collector-1     | Value: 16.440000
2023-11-11 08:28:54 otel-collector-collector-1     | NumberDataPoints #3
2023-11-11 08:28:54 otel-collector-collector-1     | Data point attributes:
2023-11-11 08:28:54 otel-collector-collector-1     |      -> fake__exploit_magnetic_applications: Str(concept)
2023-11-11 08:28:54 otel-collector-collector-1     |      -> fake__grow_magnetic_communities: Str(graphical_user_interface)
2023-11-11 08:28:54 otel-collector-collector-1     |      -> fake__target_customized_eyeballs: Str(extranet)

Más allá de la impresión

Lo anterior es un excelente primer paso, pero hay más que imprimir en la consola. Expondremos las métricas para que sean raspadas por una instancia regular de Prometheus; podemos agregar unpanel de Grafana para visualizarlas. Aunque puede parecer inútil, tenga paciencia, ya que es solo un escalón.

Para lograr lo anterior, solo cambiamos la configuración del OTEL Collector:

YAML

 

exporters:
  prometheus:                                                               #1
    endpoint: ":${env:PROMETHEUS_PORT}"                                     #2

service:
  pipelines:
    metrics:
      receivers: [ "prometheus" ]
      exporters: [ "prometheus" ]                                           #3

  1. Agregar un exportador prometheus
  2. Exponer un punto final compatible con Prometheus
  3. Reemplazar la impresión por exposición

Eso es. El OTEL Collector es muy flexible.

Tenga en cuenta que el Collector es de múltiples entradas, múltiples salidas. Para imprimir datos y exponerlos a través del punto final, los agregamos a la canalización:

YAML

 

exporters:
  prometheus:                                                               #1
    endpoint: ":${env:PROMETHEUS_PORT}"
  logging:                                                                  #2
    loglevel: debug

service:
  pipelines:
    metrics:
      receivers: [ "prometheus" ]
      exporters: [ "prometheus", "logging" ]                                #3

  1. Exponer datos
  2. Imprimir datos
  3. La tubería imprimirá datos y los exponerá

Con el exportador de Prometheus configurado, podemos visualizar métricas en Grafana.

Tenga en cuenta que los receptores y exportadores especifican su tipo y cada uno de ellos debe ser único. Para cumplir con el último requisito, podemos agregar un calificador para distinguir entre ellos, por ejemplo, prometheus/foo y prometheus/bar.

Procesamiento de Datos Intermedios

A valid question would be why the OTEL Collector is set between the source and Prometheus, as it makes the overall design more fragile. At this stage, we can leverage the true power of the OTEL Collector: data processing. So far, we have ingested raw metrics, but the source format may not be adapted to how we want to visualize data. For example, in our setup, metrics come from our fake generator, “business,” and the underlying NodeJS platform, “technical.” It is reflected in the metrics’ name. We could add a dedicated source label and remove the unnecessary prefix to filter more efficiently.

Declara los procesadores de datos en la sección processors del archivo de configuración. El recopilador los ejecuta en el orden en que se declaran. Implementemos la transformación anterior.

El primer paso hacia nuestro objetivo es comprender que el recopilador tiene dos versiones: una “básica” y una contribuyente que se basa en ella. Los procesadores incluidos en el primero son limitados, tanto en número como en capacidades; por lo tanto, necesitamos cambiar a la versión contrib.

YAML

 

collector:
  image: otel/opentelemetry-collector-contrib:0.87.0                        #1
  environment:
    - METRICS_HOST=fake-metrics
    - METRICS_PORT=5000
    - PROMETHEUS_PORT=8889
  volumes:
    - ./config/collector/config.yml:/etc/otelcol-contrib/config.yaml:ro     #2

  1. Utiliza el sabor contrib
  2. Para mayor diversión, el archivo de configuración está en otro camino

En este punto, podemos agregar el procesador en sí:

YAML

 

processors:
  metricstransform:                                                         #1
    transforms:                                                             #2
      - include: ^fake_(.*)$                                                #3
        match_type: regexp                                                  #3
        action: update
        operations:                                                         #4
          - action: add_label                                               #5
            new_label: origin
            new_value: fake
      - include: ^fake_(.*)$
        match_type: regexp
        action: update                                                      #6
        new_name: $${1}                                                     #6-7
# Haz lo mismo con las métricas generadas por NodeJS

  1. Invoca el procesador de transformación de métricas
  2. Lista de transformaciones aplicadas en orden
  3. Coincide con todas las métricas con la expresión regular definida
  4. Lista de operaciones aplicadas en orden
  5. Agrega la etiqueta
  6. Renombra la métrica eliminando el prefijo del grupo de expresiones regulares
  7. Cosas divertidas: la sintaxis es $${x}

Finalmente, agregamos el procesador definido a la tubería:

YAML

 

service:
  pipelines:
    metrics:
      receivers: [ "prometheus" ]
      processors: [ "metricstransform" ]
      exporters: [ "prometheus" ]

Aquí están los resultados:

Conexión de Receptores y Exportadores

A connector is both a receiver and an exporter and connects two pipelines. The example from the documentation receives the number of spans (tracing) and exports the count, which has a metric. I tried to achieve the same with 500 errors — spoiler: it doesn’t work as intended.

Primero, agreguemos un receptor de logs:

YAML

 

receivers:
  filelog:
    include: [ "/var/logs/generated.log" ]

Luego, agregamos un conector:

YAML

 

connectors:
  count:
    requests.errors:
      description: Number of 500 errors
      condition: [ "status == 500 " ]

Finalmente, conectamos el receptor de logs y el exportador de métricas:

YAML

 

service:
   pipelines:
     logs:
       receivers: [ "filelog" ]
       exporters: [ "count" ]
     metrics:
       receivers: [ "prometheus", "count" ]

La métrica se llama log_record_count_total, pero su valor se mantiene en 1.

Manipulación de Logs

Los procesadores permiten la manipulación de datos; los operadores son procesadores especializados que trabajan con logs. Si estás familiarizado con la pila ELK, son equivalentes a Logstash.

Hasta ahora, la marca de tiempo del log es la marca de tiempo de ingesta. Cambiaremos esto por la marca de tiempo de creación.

YAML

 

receivers:
  filelog:
    include: [ "/var/logs/generated.log" ]
    operators:
      - type: json_parser                                                   #1
        timestamp:                                                          #2
          parse_from: attributes.datetime                                   #3
          layout: "%d/%b/%Y:%H:%M:%S %z"                                    #4
        severity:                                                           #2
          parse_from: attributes.status                                     #3
          mapping:                                                          #5
            error: 5xx                                                      #6
            warn: 4xx
            info: 3xx
            debug: 2xx
      - id: remove_body                                                     #7
        type: remove
        field: body
      - id: remove_datetime                                                 #7
        type: remove
        field: attributes.datetime
      - id: remove_status                                                   #7
        type: remove
        field: attributes.status

  1. El log está en formato JSON; podemos usar el parser JSON proporcionado
  2. Atributos de metadatos para establecer
  3. Campos para leer
  4. Patrón de análisis
  5. Tabla de mapeo
  6. Aceptar un rango, por ejemplo, 501-599. El operador tiene un valor interpretado especial 5xx (y similares) para los códigos de estado HTTP.
  7. Eliminar datos duplicados

Logs

En este punto, podemos enviar los logs a cualquier componente de agregación de logs. Nos mantendremos en el ámbito de Grafana Labs y usaremos Loki.

YAML

 

exporters:
  loki:
    endpoint: "http://loki:3100/loki/api/v1/push"

También podemos usar logs del propio colector:

YAML

 

service:
  telemetry:
    logs:

Finalmente, agreguemos otra pipeline:

YAML

 

service:
  pipelines:
    logs:
      receivers: [ "filelog" ]
      exporters: [ "loki" ]

Grafana también puede visualizar los logs. Elige Loki como fuente de datos.

Conclusión

En esta publicación, profundizamos en el colector de OpenTelemetry. Si bien no es parte obligatoria de la arquitectura de OTEL, es un útil cuchillo suizo para todas tus necesidades de procesamiento de datos. En caso de que no estés atado a una pila específica o no quieras estarlo, es de gran ayuda.

El código fuente completo de esta publicación se puede encontrar en GitHub.

Para Avanzar Más

Source:
https://dzone.com/articles/exploring-the-opentelemetry-collector