OpenTelemetry Visual Handbook · phase 02 · lab
One request.
How many traces?
A click becomes six services. What makes their spans one trace is a 55-character header. Each service has to read it, continue it and write it again. Watch it travel. Then switch off one proxy's manners and see what the backend receives.
Every id, colour and arrow on the stage is computed from a propagation model. The switches change the model, and the film is rebuilt from it at the same moment.
Packet flow
- first trace
| No. | Step | Source | Destination | Protocol | Size | Info |
|---|---|---|---|---|---|---|
| 1 | 02 | browser | gateway | HTTP | — | POST /checkout · traceparent 00-34b62e90a10911c5b658229682045116-9e22945adee533d1-01 · baggage user.tier=gold |
| 2 | 03 | gateway | checkout | HTTP | — | POST /orders · traceparent 00-34b62e90a10911c5b658229682045116-47ecbe54d71b412b-01 · baggage user.tier=gold |
| 3 | 04 | checkout | inventory | HTTP | — | POST /reserve · traceparent 00-34b62e90a10911c5b658229682045116-ed1f3162e5bd2e1f-01 · baggage user.tier=gold |
| 4 | 05 | proxy | payments | HTTP | — | POST /charge · traceparent 00-34b62e90a10911c5b658229682045116-ed1f3162e5bd2e1f-01 · baggage user.tier=gold |
| 5 | 06 | browser | collector | OTLP | — | span "click checkout" · trace 34b62e90… · span 9e22945a… · root |
| 6 | 06 | gateway | collector | OTLP | — | span "POST /checkout" · trace 34b62e90… · span 47ecbe54… · parent 9e22945a… |
| 7 | 06 | checkout | collector | OTLP | — | span "PlaceOrder" · trace 34b62e90… · span ed1f3162… · parent 47ecbe54… |
| 8 | 06 | inventory | collector | OTLP | — | span "ReserveStock" · trace 34b62e90… · span ed2bbf73… · parent ed1f3162… |
| 9 | 06 | payments | collector | OTLP | — | span "Charge" · trace 34b62e90… · span 3fae7ecb… · parent ed1f3162… |
Break it, one switch at a time
- Play it through once. The trace-id stays the same on every hop. The parent-id changes on every hop. That pair is the entire mechanism.
- Turn off “Proxy forwards headers”. Payments receives no
traceparentand starts a new root. The backend now holds two traces for one click, and the payments span has lostuser.tier. - Turn it back on, and look for the proxy in the trace view. It is not there. A hop without an SDK is invisible, but it can still pass the context on. It does not break the trace unless it drops the headers.
- Turn off “Root sampled”. Every span inherits
-00. Context still propagates, but no span is exported. Sampling decides what gets recorded, not what gets propagated.
Why “hard” context
Trace context is the minimum needed to join spans: ids and a flag. Baggage is application data that rides on the same hops, such as a tenant or a tier. It is not recorded on spans unless code copies it there. Both survive only where every hop carries them. W3C Trace Context → · W3C Baggage →
The boundary of this experiment
The topology is fixed, and every hop is a synchronous HTTP request. Ids come from a seeded generator, so they repeat between visits. It models traceparent and baggage only. It leaves out tracestate, baggage properties, B3 and Jaeger propagators, messaging links, and span timing. The proxy is a two-state switch. A real proxy can also rewrite, truncate or duplicate headers.
An uninstrumented proxy forwards every header untouched. Does it appear as a span in the trace?
Commit to an answer first. You cannot change it afterwards.