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:
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
- Aucune image Docker n’est disponible pour le projet de métriques factices ; nous devons donc la construire
- Dernière version du Collecteur OTEL au moment de la rédaction
- Paramétrer le fichier de configuration suivant
- 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.
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
- Liste des récepteurs. Un récepteur lit des données ; il peut être soit à base de poussée, soit à base de tirage.
- Nous utilisons le récepteur prédéfini
prometheus
- Définir les tâches de tirage
- Configuration de la tâche
- Liste des exportateurs. En contraste avec les récepteurs, un exportateur écrit des données.
- Le plus simple exportateur est d’écrire des données sur la sortie standard
- Les pipelines assemblent les récepteurs et les exportateurs
- Définir un pipeline lié aux métriques
- Le pipeline obtient des données du récepteur
prometheus
précédemment défini et les envoie à l’exportateurlogging
, 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:
exporters:
prometheus: #1
endpoint: ":${env:PROMETHEUS_PORT}" #2
service:
pipelines:
metrics:
receivers: [ "prometheus" ]
exporters: [ "prometheus" ] #3
- Ajouter un exportateur
prometheus
- Exposer un point de terminaison compatible Prometheus
- 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:
exporters:
prometheus: #1
endpoint: ":${env:PROMETHEUS_PORT}"
logging: #2
loglevel: debug
service:
pipelines:
metrics:
receivers: [ "prometheus" ]
exporters: [ "prometheus", "logging" ] #3
- Exposer les données
- Imprimer les données
- 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.
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
- Utiliser la version
contrib
- Pour plus de plaisir, le fichier de configuration est situé dans un autre chemin
À ce stade, nous pouvons ajouter le processeur lui-même:
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
- Invoquer le processeur de transformation des métriques
- Liste des transformations appliquées dans l’ordre
- Correspond à toutes les métriques avec le regexp défini
- Liste des opérations appliquées dans l’ordre
- Ajouter l’étiquette
- Renommer la métrique en supprimant le préfixe du groupe de regexp
- Chose amusante : la syntaxe est
$${x}
Enfin, nous ajoutons le processeur défini au pipeline :
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 :
receivers:
filelog:
include: [ "/var/logs/generated.log" ]
Ensuite, ajoutons un connecteur :
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 :
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.
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
- Le log est au format JSON ; nous pouvons utiliser le parseur JSON fourni
- Attributs de métadonnées à définir
- Champs à lire
- Modèle de parsing
- Tableau de mapping
- Accepter une plage, par exemple,
501-599
. L’opérateur a une valeur interprétée spéciale5xx
(et similaires) pour les codes de statut HTTP. - 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.
exporters:
loki:
endpoint: "http://loki:3100/loki/api/v1/push"
Nous pouvons également utiliser les logs provenant du collecteur lui-même :
service:
telemetry:
logs:
Enfin, ajoutons une autre pipeline :
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