Explorer le Collecteur OpenTelemetry

L’OpenTelemetry Collector se situe au cœur de l’architecture OpenTelemetry mais n’est pas lié au W3C Trace Context. Dans mon démo de traçage, j’utilise Jaeger au lieu du Collector. Pourtant, il est omniprésent, comme dans chaque article lié à OpenTelemetry. Je voulais l’explorer davantage.

Dans cet article, j’explore les différents aspects du Collector:

  • Le type de données : logs, métriques et traces
  • Modèles push et pull
  • Opérations : lectures, transformations et écritures

Premiers pas

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 est l’une des principales solutions de surveillance. Elle fonctionne sur un modèle basé sur le pull : Prometheus rassemble les points de terminaison compatibles de votre application(s) et les stocke en interne.

Nous utiliserons le Collecteur OTEL pour rassembler un point de terminaison compatible Prometheus et imprimer le résultat dans la console. Grafana Labs propose un projet qui génère des métriques aléatoires pour s’amuser. Pour simplifier, j’utiliserai Docker Compose ; le montage ressemble au suivant:

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. Aucune image Docker n’est disponible pour le projet de métriques factices ; nous devons donc la construire
  2. Dernière version du Collecteur OTEL au moment de la rédaction
  3. Paramétrer le fichier de configuration suivant
  4. Tout se passe ici

Comme je l’ai mentionné ci-dessus, le Collecteur OTEL peut faire beaucoup de choses. Par conséquent, la configuration est essentielle.

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. Liste des récepteurs. Un récepteur lit des données ; il peut être soit à base de poussée, soit à base de tirage.
  2. Nous utilisons le récepteur prédéfini prometheus
  3. Définir les tâches de tirage
  4. Configuration de la tâche
  5. Liste des exportateurs. En contraste avec les récepteurs, un exportateur écrit des données.
  6. Le plus simple exportateur est d’écrire des données sur la sortie standard
  7. Les pipelines assemblent les récepteurs et les exportateurs
  8. Définir un pipeline lié aux métriques
  9. Le pipeline obtient des données du récepteur prometheus précédemment défini et les envoie à l’exportateur logging, c’est-à-dire, les imprime

Voici un exemple du résultat:

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)

Au-delà de l’impression

Le précédent est un excellent premier pas, mais il y a plus que l’impression à l’écran. Nous allons exposer les métriques à être scrapées par une instance Prometheus régulière ; nous pouvons ajouter un tableau de bord Grafana pour les visualiser. Bien qu’il puisse sembler inutile, ayez patience, car c’est seulement un tremplin.

Pour réaliser ce qui précède, nous modifions uniquement la configuration du Collecteur OTEL:

YAML

 

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

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

  1. Ajouter un exportateur prometheus
  2. Exposer un point de terminaison compatible Prometheus
  3. Remplacer l’impression par l’exposition

C’est tout. Le Collecteur OTEL est très flexible.

Notez que le Collecteur est multi-entrées, multi-sorties. Pour imprimer les données et les exposer via le point de terminaison, nous les ajoutons au pipeline:

YAML

 

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

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

  1. Exposer les données
  2. Imprimer les données
  3. Le pipeline imprimera et exposera les données

Avec l’exportateur Prometheus configuré, nous pouvons visualiser les métriques dans Grafana.

Notez que les récepteurs et les exportateurs spécifient leur type et chacun d’eux doit être unique. Pour respecter cette dernière exigence, nous pouvons ajouter un qualificatif pour les distinguer, par exemple, prometheus/foo et prometheus/bar.

Traitement des données intermédiaires

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.

Vous déclarez les processeurs de données dans la section processors du fichier de configuration. Le collecteur les exécute dans l’ordre de leur déclaration. Implémentons la transformation ci-dessus.

La première étape vers notre objectif est de comprendre que le collecteur a deux versions : une « nu » et une contrib qui s’appuie dessus. Les processeurs inclus dans la première sont limités, tant en nombre qu’en capacités ; par conséquent, nous devons passer à la version 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. Utiliser la version contrib
  2. Pour plus de plaisir, le fichier de configuration est situé dans un autre chemin

À ce stade, nous pouvons ajouter le processeur lui-même:

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
# Faire de même avec les métriques générées par NodeJS

  1. Invoquer le processeur de transformation des métriques
  2. Liste des transformations appliquées dans l’ordre
  3. Correspond à toutes les métriques avec le regexp défini
  4. Liste des opérations appliquées dans l’ordre
  5. Ajouter l’étiquette
  6. Renommer la métrique en supprimant le préfixe du groupe de regexp
  7. Chose amusante : la syntaxe est $${x}

Enfin, nous ajoutons le processeur défini au pipeline :

YAML

 

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

Voici les résultats :

Connecter les récepteurs et les exportateurs

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.

Ajoutons d’abord un récepteur de logs :

YAML

 

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

Ensuite, ajoutons un connecteur :

YAML

 

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

Enfin, connectons le récepteur de logs et l’exportateur de métriques :

YAML

 

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

La métrique est nommée log_record_count_total, mais sa valeur reste à 1.

Manipulation des logs

Les processeurs permettent la manipulation des données ; les opérateurs sont des processeurs spécialisés qui travaillent sur les logs. Si vous connaissez le ELK stack, ils sont équivalents à Logstash.

Actuellement, l’horodatage du log est l’horodatage d’ingestion. Nous allons le changer en horodatage de création.

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. Le log est au format JSON ; nous pouvons utiliser le parseur JSON fourni
  2. Attributs de métadonnées à définir
  3. Champs à lire
  4. Modèle de parsing
  5. Tableau de mapping
  6. Accepter une plage, par exemple, 501-599. L’opérateur a une valeur interprétée spéciale 5xx (et similaires) pour les codes de statut HTTP.
  7. Supprimer les données en double

Logs

À ce stade, nous pouvons envoyer les logs à n’importe quel composant d’agrégation de logs. Nous allons rester dans le périmètre de Grafana Labs et utiliser Loki.

YAML

 

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

Nous pouvons également utiliser les logs provenant du collecteur lui-même :

YAML

 

service:
  telemetry:
    logs:

Enfin, ajoutons une autre pipeline :

YAML

 

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

Grafana peut également visualiser les logs. Choisissez Loki comme source de données.

Conclusion

Dans ce post, nous avons exploré le collecteur OpenTelemetry. Bien qu’il ne soit pas une partie obligatoire de l’architecture OTEL, c’est un outil-suisse précieux pour tous vos besoins en traitement des données. En cas de non-engagement envers une pile spécifique ou si vous ne le souhaitez pas, c’est d’une aide considérable.

Le code source complet de ce post peut être trouvé sur GitHub.

Pour Aller Plus Loin

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