Die Erkundung des OpenTelemetry Collectors

Der OpenTelemetry Collector befindet sich im Zentrum der OpenTelemetry-Architektur, ist jedoch unabhängig vom W3C Trace Context. In meinem Tracing-Demo verwende ich Jaeger anstelle des Collectors. Dennoch ist er allgegenwärtig, wie in jedem OpenTelemetry-bezogenen Beitrag. Ich wollte ihn genauer untersuchen.

In diesem Beitrag untersuche ich die verschiedenen Aspekte des Collectors:

  • Datentypen: Protokolle, Metriken und Spuren
  • Push- und Pull-Modelle
  • Betriebsabläufe: Lesen, Transformationen und Schreiben

Erste Schritte

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 ist eine der Hauptüberwachungslösungen. Es arbeitet auf Basis eines pull-basierten Modells: Prometheus scrapt kompatible Endpunkte Ihrer Anwendung(en) und speichert sie intern.

Wir werden den OTEL Collector verwenden, um einen Prometheus-kompatiblen Endpunkt zu scrapen und das Ergebnis in der Konsole auszugeben. Grafana Labs bietet ein Projekt, das zufällige Metriken zum Spielen generiert. Aus Gründen der Einfachheit verwende ich Docker Compose; die Einrichtung sieht wie folgt aus:

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. Für das Fake-Metrics-Projekt steht kein Docker-Image zur Verfügung; daher müssen wir es selbst erstellen
  2. Aktuellste Version des OTEL Collectors zum Zeitpunkt des Schreibens
  3. Konfigurationsdatei parametrisieren
  4. Alles passiert hier

Wie oben erwähnt, kann der OTEL Collector vieles. Daher ist die Konfiguration alles.

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 der Empfänger. Ein Empfänger liest Daten; es kann entweder push-basiert oder pull-basiert sein.
  2. Wir verwenden den vordefinierten Empfänger prometheus
  3. Definieren Sie Pull-Jobs
  4. Konfiguration des Jobs
  5. Liste der Exporter. Im Gegensatz zu Empfängern schreibt ein Exporter Daten.
  6. Der einfachste Exporter ist das Schreiben von Daten auf die Standardausgabe
  7. Pipelines setzen sich aus Empfängern und Exportern zusammen
  8. Definieren Sie eine metrikbezogene Pipeline
  9. Die Pipeline erhält Daten vom zuvor definierten prometheus Empfänger und sendet sie an den logging Exporter, d.h., druckt sie

Hier ist ein Beispiel des Resultats:

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)

Jenseits des Druckens

Das obige ist ein ausgezeichneter erster Schritt, aber es gibt mehr als das Drucken auf der Konsole. Wir werden die Metriken dafür freigeben, von einer regulären Prometheus-Instanz abgerufen zu werden; wir können eine Grafana-Ansicht hinzufügen, um sie zu visualisieren. Es mag zwar sinnlos erscheinen, aber seien Sie geduldig, denn es ist nur ein Zwischenschritt.

Um das obige zu erreichen, ändern wir nur die Konfiguration des OTEL Collectors:

YAML

 

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

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

  1. Fügen Sie einen prometheus Exporter hinzu
  2. Stellen Sie einen Prometheus-kompatiblen Endpunkt zur Verfügung
  3. Ersetzen Sie das Drucken durch das Freigeben

Das war’s. Der OTEL Collector ist sehr flexibel.

Beachten Sie, dass der Collector mehrfach eingeben und mehrfach ausgeben kann. Um sowohl Daten zu drucken als auch sie über den Endpunkt freizugeben, fügen wir sie der Pipeline hinzu:

YAML

 

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

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

  1. Daten freigeben
  2. Daten drucken
  3. Die Pipeline wird sowohl Daten ausdrucken als auch sie offenbaren

Mit dem konfigurierten Prometheus-Exporter können wir Metriken in Grafana visualisieren.

Beachten Sie, dass Empfänger und Exporter ihren Typ angeben und jeder von ihnen muss einzigartig sein. Um dieser letzten Anforderung zu entsprechen, können wir einem Qualifikator anhängen, um sie voneinander zu unterscheiden, z.B., prometheus/foo und prometheus/bar.

Zwischen Datenverarbeitung

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.

Sie deklarieren Datenprozessoren im Abschnitt processors der Konfigurationsdatei. Der Collector führt sie in der Reihenfolge aus, in der sie deklariert sind. Lassen Sie uns die obige Transformation implementieren.

Der erste Schritt zum Erreichen unseres Ziels ist zu verstehen, dass der Collector zwei Varianten hat: eine „nackte“ und eine contrib-Variante, die darauf aufbaut. Prozessoren, die in der ersten enthalten sind, sind sowohl in Anzahl als auch in Fähigkeiten begrenzt; daher müssen wir zur contrib-Version wechseln.

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. Verwenden Sie die contrib Geschmack
  2. Zur zusätzlichen Freude befindet sich die Konfigurationsdatei an einem anderen Pfad

An diesem Punkt können wir den Prozessor selbst hinzufügen:

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
# Fahren Sie mit den von NodeJS generierten Metriken fort

  1. Führen Sie den Metriktransformationsprozessor aus
  2. Liste der in der Reihenfolge angewendeten Transformationen
  3. Passt alle Metriken mit der definierten Regexp
  4. Liste der in der Reihenfolge angewendeten Operationen
  5. Fügen Sie das Etikett hinzu
  6. Benennen Sie die Metrik um, indem Sie den Regexp-Gruppenpräfix entfernen
  7. Spaßiges Zeug: Die Syntax ist $${x}

Schließlich fügen wir den definierten Prozessor zur Pipeline hinzu:

YAML

 

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

Hier sind die Ergebnisse:

Verbinden von Empfängern und Exporteuren

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.

Fangen wir zunächst mit einem Log-Empfänger an:

YAML

 

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

Dann fügen wir einen Connector hinzu:

YAML

 

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

Zuletzt verbinden wir den Log-Empfänger und den Metriksexporter:

YAML

 

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

Die Metrik heißt log_record_count_total, aber ihr Wert bleibt bei 1.

Logs Manipulation

Prozessoren ermöglichen die Datenmanipulation; Operatoren sind spezialisierte Prozessoren, die auf Logs arbeiten. Wenn Sie mit der ELK-Stack vertraut sind, entsprechen sie Logstash.

Bisher ist die Log-Zeitstempel die Ingestionszeit. Wir werden sie in den Erstellungszeitstempel ändern.

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. Das Log ist im JSON-Format; wir können den bereitgestellten JSON-Parser verwenden
  2. Metadatenattribute zur Einstellung
  3. Felder zum Lesen aus
  4. Parsermuster
  5. Zuordnungstabelle
  6. Akzeptieren eines Bereichs, z.B., 501-599. Der Operator hat einen speziell interpretierten Wert 5xx (und ähnliche) für HTTP-Statuscodes.
  7. Doppelte Daten entfernen

Logs

An dieser Stelle können wir die Logs an jedes Log-Aggregationselement senden. Wir bleiben im Grafana Labs-Bereich und verwenden Loki.

YAML

 

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

Wir können auch Logs vom Collector selbst verwenden:

YAML

 

service:
  telemetry:
    logs:

Schließlich fügen wir eine weitere Pipeline hinzu:

YAML

 

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

Grafana kann auch die Logs visualisieren. Wählen Sie Loki als Datenquelle.

Schlussfolgerung

In diesem Beitrag haben wir uns dem OpenTelemetry Collector zugewandt. Obwohl er nicht zwingend Teil der OTEL-Architektur ist, ist er ein nützliches Schweizer Taschenmesser für alle Ihre Datenverarbeitungsanforderungen. Falls Sie nicht an eine bestimmte Technologiestack gebunden sind oder es nicht möchten, ist er von unschätzbarem Wert.

Der vollständige Quellcode für diesen Beitrag ist auf GitHub zu finden.

Weiterführendes

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