L’OpenTelemetry Collector si trova al centro dell’architettura di OpenTelemetry ma non è correlato al W3C Trace Context. Nel mio demo di tracing, uso Jaeger invece del Collector. Tuttavia, è onnipresente, come in ogni post relativo a OpenTelemetry. Volevo esplorarlo ulteriormente.
In questo post, esploro gli aspetti diversi del Collector:
- Il tipo di dati: log, metriche e tracce
- Modelli push e pull
- Operazioni: letture, trasformazioni e scritture
Primi passi
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 è una delle principali soluzioni di monitoraggio. Funziona con un modello basato su pull: Prometheus esegue scraping degli endpoint compatibili del tuo applicativo(i) e li memorizza internamente.
Utilizzeremo l’OTEL Collector per eseguire lo scraping di un endpoint compatibile con Prometheus e stampare il risultato nella console. Grafana Labs offre un progetto che genera metriche casuali con cui giocare. Per semplicità, userò Docker Compose; la configurazione è simile alla seguente:
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
- Non è disponibile un’immagine Docker per il progetto delle metriche false; pertanto, dobbiamo compilarla
- Versione più recente dell’OTEL Collector al momento della stesura di questo articolo
- Parametrizzare il seguente file di configurazione
- Tutto accade qui
Come ho detto sopra, l’OTEL Collector può fare molto. Quindi, la configurazione è tutto.
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
- Elenco dei ricevitori. Un ricevitore legge i dati; può essere di tipo push-based o pull-based.
- Utilizziamo il ricevitore predefinito
prometheus
- Definire i job di pull
- Configurazione del job
- Elenco degli esportatori. Al contrario dei ricevitori, un esportatore scrive dati.
- L’esportatore più semplice è quello di scrivere dati sull’uscita standard
- I pipeline assemblano ricevitori ed esportatori
- Definire un pipeline relativo alle metriche
- Il pipeline ottiene dati dal ricevitore
prometheus
precedentemente definito e li invia all’esportatorelogging
, cioè, li stampa
Ecco un esempio del risultato:
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)
Oltre la Stampa
Il passo precedente è ottimo per iniziare, ma c’è più che stampare a video. Esamineremo come rendere le metriche disponibili per essere raccolte da un’istanza di Prometheus regolare; possiamo aggiungere un dashboard Grafana per visualizzarle. Anche se potrebbe sembrare inutile, abbiate pazienza, poiché è solo un gradino.
Per realizzare quanto sopra, basta modificare la configurazione del Collector OTEL:
exporters:
prometheus: #1
endpoint: ":${env:PROMETHEUS_PORT}" #2
service:
pipelines:
metrics:
receivers: [ "prometheus" ]
exporters: [ "prometheus" ] #3
- Aggiungere un esportatore
prometheus
- Esporre un endpoint conforme a Prometheus
- Sostituire la stampa con l’esposizione
Ecco tutto. Il Collector OTEL è molto flessibile.
Si noti che il Collector è multi-input, multi-output. Per stampare i dati e contemporaneamente esporli tramite l’endpoint, li aggiungiamo al pipeline:
exporters:
prometheus: #1
endpoint: ":${env:PROMETHEUS_PORT}"
logging: #2
loglevel: debug
service:
pipelines:
metrics:
receivers: [ "prometheus" ]
exporters: [ "prometheus", "logging" ] #3
- Esporre dati
- Stampare dati
- Il pipeline stamperà sia i dati che li esporrà
Con l’esportatore Prometheus configurato, possiamo visualizzare le metriche in Grafana.
Si noti che ricevitori ed esportatori specificano il loro tipo e ognuno di essi deve essere unico. Per rispettare l’ultima richiesta, possiamo aggiungere un qualificatore per distinguerli, cioè, prometheus/foo
e prometheus/bar.
Elaborazione dei Dati Intermedi
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.
Si dichiarano i processori di dati nella sezione processors
del file di configurazione. Il collector li esegue nell’ordine in cui sono dichiarati. Implementiamo la trasformazione sopra descritta.
Il primo passo verso il nostro obiettivo è capire che il collector ha due varianti: una “nuda” e una contrib che si basa su di essa. I processori inclusi nella prima sono limitati, sia in numero che in capacità; pertanto, dobbiamo passare alla versione 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
- Utilizzare il sapore
contrib
- Per maggiore divertimento, il file di configurazione si trova in un altro percorso
A questo punto, possiamo aggiungere il processore stesso:
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
# Fai lo stesso con le metriche generate da NodeJS
- Invoca il processore di trasformazione delle metriche
- Elenco delle trasformazioni applicate in ordine
- Corrisponde a tutte le metriche con la regexp definita
- Elenco delle operazioni applicate in ordine
- Aggiungi il label
- Rinomina la metrica rimuovendo il prefisso del gruppo regexp
- Roba da divertirsi: la sintassi è
$${x}
Infine, aggiungiamo il processore definito al pipeline:
service:
pipelines:
metrics:
receivers: [ "prometheus" ]
processors: [ "metricstransform" ]
exporters: [ "prometheus" ]
Ecco i risultati:
Collegamento di Ricevitori ed Esportatori
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.
Iniziamo aggiungendo un ricevitore di log:
receivers:
filelog:
include: [ "/var/logs/generated.log" ]
Quindi, aggiungiamo un connettore:
connectors:
count:
requests.errors:
description: Number of 500 errors
condition: [ "status == 500 " ]
Infine, colleghiamo il ricevitore di log e l’esportatore di metriche:
service:
pipelines:
logs:
receivers: [ "filelog" ]
exporters: [ "count" ]
metrics:
receivers: [ "prometheus", "count" ]
La metrica è denominata log_record_count_total
, ma il suo valore rimane a 1.
Manipolazione dei Log
I processori consentono la manipolazione dei dati; gli operatori sono processori specializzati che lavorano sui log. Se hai familiarità con lo stack ELK, sono l’equivalente di Logstash.
Finora, l’ora del log è l’ora di inserimento. Cambieremo questo invece con l’ora di creazione del log.
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
- Il log è in formato JSON; possiamo utilizzare il parser JSON fornito
- Attributi di metadati da impostare
- Campi da leggere
- Pattern di parsing
- Tabella di mappatura
- Accetta un intervallo, ad esempio,
501-599
. L’operatore ha un valore interpretato speciale5xx
(e simili) per i codici di stato HTTP. - Rimuovi dati duplicati
Log
A questo punto, possiamo inviare i log a qualsiasi componente di aggregazione dei log. Rimarremo nell’ambito di Grafana Labs e utilizzeremo Loki.
exporters:
loki:
endpoint: "http://loki:3100/loki/api/v1/push"
Possiamo anche utilizzare i log dal collector stesso:
service:
telemetry:
logs:
Infine, aggiungiamo un’altra pipeline:
service:
pipelines:
logs:
receivers: [ "filelog" ]
exporters: [ "loki" ]
Grafana può anche visualizzare i log. Scegli Loki come datasource.
Conclusione
In questo post, abbiamo approfondito il raccoltore OpenTelemetry. Nonostante non sia parte obbligatoria dell’architettura OTEL, è un’utile coltellino svizzero per tutte le tue esigenze di elaborazione dei dati. Nel caso in cui non ti sei attaccato a una specifica pila o non vuoi farlo, è di grande aiuto.
Il codice sorgente completo per questo post è disponibile su GitHub.
Per andare oltre
Source:
https://dzone.com/articles/exploring-the-opentelemetry-collector