Lexikon · C

Context Propagation

Weitergabe von Trace- und Request-Kontext über Prozessgrenzen, damit Spans verschiedener Services einen Trace bilden.

Von Obseria-RedaktionAktualisiert

Definition

Context Propagation ist der Mechanismus, der Trace-Kontext wie Trace-ID, Parent-Span-ID und Sampling-Entscheidung mit jedem Request oder jeder Nachricht von einem Service zum nächsten trägt. Erst dadurch werden Spans aus verschiedenen Prozessen zu einem einzigen Distributed Trace verknüpft. Das Standardformat für HTTP ist der traceparent-Header aus W3C Trace Context.

Was Context Propagation ist

Ein Distributed Trace setzt sich aus vielen Spans zusammen, die in unterschiedlichen Prozessen entstehen, oft auf verschiedenen Maschinen und in verschiedenen Sprachen. Jeder Service kennt nur seine eigene Arbeit. Context Propagation teilt dem nachgelagerten Service mit: „Dieser Request gehört zu Trace X, und der Span, der dich aufruft, ist Y.“ Der Service erfasst seine Spans mit derselben Trace-ID und Y als Parent, sodass das Backend den vollständigen Request-Baum rekonstruieren kann.

Der Kontext besteht aus zwei Teilen. Der Span Context identifiziert Trace und aktuellen Span und trägt Flags, etwa ob der Trace gesampelt wird. Baggage sind optionale, selbst definierte Schlüssel-Wert-Paare, zum Beispiel eine Mandanten-ID, die mit dem Request mitreisen, damit spätere Services sie nutzen können.

Funktionsweise: Inject und Extract

Propagation erfolgt in zwei Schritten. Bei einem ausgehenden Aufruf injiziert die Instrumentierung den aktuellen Kontext in den Träger, typischerweise HTTP-Header, gRPC-Metadaten oder Message-Header. Der empfangende Service extrahiert den Kontext und macht ihn zum Parent des neuen Server-Spans. In OpenTelemetry übernehmen sogenannte Propagatoren diese Aufgabe, die Umgebungsvariable OTEL_PROPAGATORS wählt sie aus. Standard ist tracecontext,baggage.

Auch innerhalb eines Prozesses muss Kontext über Threads, Callbacks und asynchrone Tasks fließen. Laufzeitumgebungen lösen das unterschiedlich, etwa über Thread-Local Storage in Java oder Async Context Tracking in Node.js. Die Context-API von OpenTelemetry abstrahiert diese Unterschiede.

Der Standard W3C Trace Context

Vor der Standardisierung nutzte jedes Tracing-System eigene Header, etwa die B3-Header von Zipkin oder herstellerspezifische Formate. Traces rissen dadurch an jeder Grenze zwischen Tools ab. Die W3C-Recommendation Trace Context definiert zwei HTTP-Header, die alle konformen Systeme verstehen:

traceparent: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01
tracestate: vendorname=opaque-value
FeldBeispielBedeutung
version00Formatversion, derzeit 00
trace-id0af7651916cd43dd8448eb211c80319c16 Byte als 32 Hex-Zeichen, identifiziert den gesamten Trace
parent-idb7ad6b71692033318 Byte als 16 Hex-Zeichen, ID des aufrufenden Spans
trace-flags01Bitfeld; 01 bedeutet, dass der Aufrufer den Trace gesampelt hat

Der Header tracestate transportiert zusätzlich herstellerspezifische Daten, die separate W3C-Spezifikation Baggage definiert den Header baggage für eigene Schlüssel-Wert-Paare.

Messaging und asynchrone Verarbeitung

Auch Queues und Event-Streams brauchen Propagation. Bei Kafka schreibt etwa die Instrumentierung des Producers traceparent in die Record-Header, der Consumer liest ihn aus. Weil ein Consumer-Batch Nachrichten aus vielen Traces enthalten kann, verbinden die OpenTelemetry-Konventionen für Messaging Consumer-Spans häufig über Span Links statt über einen einzelnen Parent mit ihren Producern. Ohne Propagation in den Message-Headern beginnt jeder asynchrone Schritt einen neuen, unverbundenen Trace.

Die Sampling-Entscheidung weitergeben

Das Sampled-Flag in traceparent ist für Kosten und Vollständigkeit entscheidend. Beim Head-based Sampling entscheidet der erste Service, ob ein Trace aufgezeichnet wird, und nachgelagerte Services übernehmen diese Entscheidung über einen Parent-based Sampler. Ignorieren Services das Flag und sampeln unabhängig voneinander, entstehen Trace-Fragmente statt vollständiger Traces. Tail-based Sampling im Collector umgeht das Problem, weil es erst entscheidet, wenn alle Spans eingetroffen sind.

Best Practices

  • Einheitlich auf W3C Trace Context setzen, in allen Services, Proxys und Gateways. Zusätzliche Propagatoren wie B3 nur dort konfigurieren, wo Altsysteme sie benötigen.
  • Header-Weitergabe durch Proxys sicherstellen. Load Balancer, API-Gateways und Service Meshes müssen traceparent und tracestate unverändert durchreichen oder selbst am Tracing teilnehmen.
  • Baggage klein und unkritisch halten. Baggage wird mit jedem nachgelagerten Request versendet und kann Ihre Vertrauensgrenze verlassen. Zugangsdaten oder personenbezogene Daten gehören nicht hinein.
  • Umgang mit externem Input festlegen. Wer traceparent aus dem öffentlichen Internet übernimmt, lässt Clients das Sampling beeinflussen. Viele Teams starten am Edge einen neuen Trace und behalten den eingehenden Kontext als Link.
  • Trace-ID loggen. trace_id und span_id in strukturierten Logs verbinden Logs und Traces.

Häufige Fehler

Abgerissene Traces sind das typische Symptom einer Propagationslücke: ein Thread-Pool, der den Kontext verliert, ein selbst gebauter HTTP-Client ohne Instrumentierung, ein Message-Bus ohne Header-Unterstützung oder ein Proxy, der unbekannte Header entfernt. Eine weitere Quelle sind gemischte Propagator-Konfigurationen, bei denen ein Service nur B3 schreibt und der nächste nur W3C liest. Und wer in jedem Service eine neue Trace-ID erzeugt, etwa fürs Logging, hebelt das Prinzip vollständig aus.

Wie Obseria unterstützt

Obseria ist OpenTelemetry-nativ und nutzt W3C Trace Context durchgängig. Traces aus OpenTelemetry-SDKs und -Agents verbinden sich daher ohne proprietäre Header. Das Distributed Tracing in Obseria hebt Traces mit fehlenden Parents hervor und zeigt so, wo die Propagation abreißt. Mehr dazu unter Was ist OpenTelemetry? und in der Kafka-Integration.

Häufig gestellte Fragen

Der in W3C Trace Context definierte HTTP-Header enthält Version, die 32-stellige Trace-ID, die 16-stellige Parent-Span-ID und Trace-Flags, jeweils durch Bindestriche getrennt. Konforme Systeme setzen damit einen Trace über Servicegrenzen fort.

Trace Context identifiziert den Trace und den aufrufenden Span und wird vom Tracing-System genutzt. Baggage sind beliebige, von der Anwendung definierte Schlüssel-Wert-Paare, die mitpropagiert werden und von nachgelagerten Services gelesen werden können.

Ja, sofern der Producer den Kontext in die Message-Header schreibt und der Consumer ihn ausliest. OpenTelemetry-Instrumentierungen für Clients wie Kafka, RabbitMQ und Cloud-Queues übernehmen das automatisch.

Ja. OpenTelemetry unterstützt zusammengesetzte Propagatoren, etwa tracecontext,baggage,b3, die mehrere Formate schreiben und lesen. Das ist bei Migrationen von Zipkin-basierten Systemen hilfreich.

Setzen Sie das Wissen in die Praxis um

Testen Sie Obseria 14 Tage kostenlos, mit OpenTelemetry und ohne proprietäre Agenten.