Propagation Scenarios
There are two general scenarios:Join an external span
This occurs when a service receives a request (response) or message that includes tracing context from an external source. The service then joins this existing trace, continuing the span from where it was left off.
Configuration
There are multiple propagators available out of the box:| Propagator | Description |
|---|---|
tracecontext | W3C Trace Context (default) |
baggage | W3C Baggage |
b3 | B3 Single Header |
b3multi | B3 Multi Header |
jaeger | Jaeger |
Setting the Propagator
Thetracecontext is the default propagator. The propagator can be configured via environment variables or system properties:
Viewing Configured Propagators
Otel4s#propagators shows the configured propagators:
Propagation Models
Let’s take a look at common cross-service propagation models.HTTP Propagation
MQTT Propagation
Propagating Current Span Downstream
TheTracer[F].propagate injects current span details into the given carrier:
TextMapUpdater is available for this type. For example, Map[String, String] and Seq[(String, String)] work out of the box.
Implementing TextMapUpdater for http4s Headers
We can implement aTextMapUpdater for arbitrary types, for example org.http4s.Headers:
Joining an External Span
TheTracer[F].joinOrRoot extracts span details from the carrier:
Implementing TextMapGetter for http4s Headers
Similarly to theTextMapUpdater, we can implement a TextMapGetter for arbitrary types:
Implementing a Custom Propagator
TextMapPropagator injects and extracts values in the form of text into carriers that travel in-band.
Let’s say we use platform-id in the HTTP headers. We can implement a custom TextMapPropagator that will use platform-id header to carry the identifier.
Custom Propagator Example
Registering the Custom Propagator
And wire it up:Best Practices
Use standard propagators
Prefer W3C Trace Context (
tracecontext) as it’s the industry standard and works across different tracing systems.Implement both getter and updater
When supporting a new carrier type, implement both
TextMapGetter and TextMapUpdater for bidirectional propagation.Handle missing context gracefully
Use
joinOrRoot which creates a root span if no context is available, ensuring your traces don’t break.Test cross-service propagation
Verify that trace IDs and span IDs propagate correctly across service boundaries in your integration tests.