OpenTelemetry OpenTelemetry

Logs und Infrastruktur-Metriken mit Receivern sammeln

Nutze die Receiver filelog, hostmetrics, kubeletstats und prometheus und leite Metriken aus Traces ab.

14 min Fortgeschritten

Anwendungen, die ein OpenTelemetry-SDK nutzen, pushen ihre eigene Telemetrie, aber vieles, was du beobachten musst, tut das nicht: Logdateien, Host-Ressourcen, der kubelet und Services, die bereits Prometheus-Metriken bereitstellen. Der Collector holt diese über Receiver herein. Diese Anleitung zeigt die nützlichsten, alle als Konfiguration. Optionsnamen von Komponenten ändern sich zwischen Releases, prüfe also die README jedes Receivers für die Version, die du betreibst. Alle diese sind in den Contrib- und Kubernetes-Distributionen enthalten.

Logdateien mit filelog

Der Receiver filelog verfolgt Dateien und verwandelt Zeilen in Log-Records.

receivers:
  filelog:
    include:
      - /var/log/myapp/*.log
    exclude:
      - /var/log/myapp/*.gz
    start_at: end            # oder "beginning", um vorhandenen Inhalt zu lesen
    include_file_path: true
    operators:
      - type: json_parser
        timestamp:
          parse_from: attributes.time
          layout: '%Y-%m-%dT%H:%M:%S.%LZ'
        severity:
          parse_from: attributes.level

Operatoren bilden eine kleine Parsing-Pipeline, die auf jeden Eintrag angewendet wird. Gängige sind json_parser, regex_parser, move, add, remove und recombine (um mehrzeilige Stacktraces wieder zu einem Record zu verbinden). Ein mehrzeiliges Beispiel:

    operators:
      - type: recombine
        combine_field: body
        is_first_entry: body matches "^\\d{4}-\\d{2}-\\d{2}"
        source_identifier: attributes["log.file.path"]

Damit er Neustarts übersteht, ohne Daten erneut zu lesen oder zu überspringen, gib dem Receiver eine Storage-Extension:

extensions:
  file_storage:
    directory: /var/lib/otelcol/storage

receivers:
  filelog:
    include: [/var/log/myapp/*.log]
    storage: file_storage

service:
  extensions: [file_storage]

Auf Kubernetes liegen Container-Logs unter /var/log/pods/*/*/*.log. Das Preset logsCollection des Helm-Charts konfiguriert diesen Receiver, mountet den Host-Pfad und parst das Format der Container-Runtime für dich, bevorzuge es also gegenüber dem Schreiben des Receivers von Hand.

Host-Metriken mit hostmetrics

Auf einer VM oder einem Knoten liest der Receiver hostmetrics CPU-, Speicher-, Disk-, Dateisystem- und Netzwerkwerte vom Betriebssystem:

receivers:
  hostmetrics:
    collection_interval: 30s
    scrapers:
      cpu:
      memory:
      load:
      disk:
      filesystem:
        exclude_mount_points:
          mount_points: [/dev/*, /proc/*, /sys/*, /run/*]
          match_type: regexp
      network:
      paging:

Betreibe ihn in einem Agent auf jedem Host. In einem Container meldet er die Sicht des Containers, es sei denn, du mountest das Dateisystem des Hosts und setzt root_path, prüfe also die Receiver-README, bevor du dich dort darauf verlässt. Füge den Prozessor resourcedetection hinzu, um Metriken mit Host-, Cloud- oder Kubernetes-Details zu labeln:

processors:
  resourcedetection:
    detectors: [env, system]
    timeout: 5s
    override: false

Kubernetes-Metriken

Ressourcennutzung von Knoten und Pods kommt vom kubelet über kubeletstats, betrieben als DaemonSet:

receivers:
  kubeletstats:
    collection_interval: 30s
    auth_type: serviceAccount
    endpoint: ${env:K8S_NODE_NAME}:10250
    insecure_skip_verify: true
    metric_groups: [node, pod, container]

Reiche den Knotennamen über die Downward API weiter:

env:
  - name: K8S_NODE_NAME
    valueFrom:
      fieldRef:
        fieldPath: spec.nodeName

insecure_skip_verify ist verbreitet, weil Zertifikate des kubelet oft selbstsigniert sind; nutze nach Möglichkeit eine korrekte CA-Konfiguration. Der Service Account braucht die Berechtigung, nodes/stats zu lesen, die das Helm-Preset gewährt.

Zustand auf Cluster-Ebene (Deployment-Replikas, Pod-Phase, Knotenbedingungen) kommt vom Receiver k8s_cluster, und Kubernetes-Events von k8sobjects. Betreibe beide einmal pro Cluster in einem Deployment mit einem Replikat, sonst sammelst du Duplikate. Beide sind als Helm-Presets verfügbar (clusterMetrics und kubernetesEvents).

Prometheus-Endpunkte abfragen

Der Receiver prometheus akzeptiert eine Standard-Prometheus-Scrape-Konfiguration, sodass bestehende Targets ohne Umschreiben übernommen werden:

receivers:
  prometheus:
    config:
      scrape_configs:
        - job_name: node-exporter
          scrape_interval: 30s
          static_configs:
            - targets: ["node-exporter:9100"]
        - job_name: kubernetes-pods
          kubernetes_sd_configs:
            - role: pod
          relabel_configs:
            - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
              action: keep
              regex: "true"

Zwei Fallstricke: In einer Collector-Konfiguration schreibst du ein literales Dollarzeichen in einem Prometheus-Regex oder -Replacement als $$, weil der Collector es sonst als Variable zu expandieren versucht; und wenn du mehrere Replikas betreibst, die alle dieselben Targets abfragen, bekommst du Duplikate. Der Target Allocator des OpenTelemetry Operators existiert, um Targets auf Collector-Replikas zu verteilen, ebenso wie der Betrieb eines einzelnen Scraper-Replikats.

Viele Receiver, eine Pipeline

Receiver speisen Pipelines desselben Signaltyps:

service:
  pipelines:
    metrics:
      receivers: [otlp, hostmetrics, kubeletstats, prometheus]
      processors: [memory_limiter, resourcedetection, batch]
      exporters: [otlphttp/prometheus]
    logs:
      receivers: [otlp, filelog]
      processors: [memory_limiter, batch]
      exporters: [otlphttp/loki]

Du kannst pro Signal auch in mehrere Pipelines aufteilen (metrics/infra, metrics/apps), um für jede Quelle andere Prozessoren anzuwenden.

Metriken aus Traces mit dem Connector spanmetrics

Wenn deine Services Traces, aber keine Anfrage-Metriken ausgeben, leitet der Connector spanmetrics aus Spans Anfragezahlen, Fehlerzahlen und Latenz-Histogramme ab. Ein Connector ist in einer Pipeline ein Exporter und in einer anderen ein Receiver:

connectors:
  spanmetrics:
    histogram:
      explicit:
        buckets: [10ms, 50ms, 100ms, 250ms, 500ms, 1s, 2.5s, 5s]
    dimensions:
      - name: http.request.method
      - name: http.response.status_code

service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: [memory_limiter, batch]
      exporters: [otlp/tempo, spanmetrics]
    metrics/spanmetrics:
      receivers: [spanmetrics]
      processors: [batch]
      exporters: [otlphttp/prometheus]

Jede Dimension vervielfacht die Zahl der Zeitreihen, füge also nur Attribute mit einer kleinen, begrenzten Wertemenge hinzu. Nutze niemals Benutzer-IDs oder URLs mit Kennungen. Platziere den Connector vor jedem Sampling, damit die Zahlen den gesamten Traffic widerspiegeln (siehe die Sampling-Anleitung).

Prüfen

Füge der Kopie der Pipeline den debug-Exporter mit verbosity: detailed hinzu und betreibe den Collector im Vordergrund. Du solltest Log-Records mit dem geparsten Schweregrad sehen oder Metriknamen wie system.cpu.time, k8s.pod.cpu.usage oder traces.span.metrics.calls (die Benennung kann je nach Version abweichen). Erscheint nichts, prüfe Dateiberechtigungen für filelog, die Variable für den Knotennamen bei kubeletstats und dass jeder Receiver in einer Pipeline aufgeführt ist.

Beliebte Anleitungen