Where the chain breaks: queues, pools, batches — context injection and span links across queues
A queue hop has no request to attach a header to, so the context must be written into the message itself — and because one consumer batch can have many causes while a span has exactly one parent, the consumer records a link to each cause instead.
Copying a header works while one service calls another over the wire. checkout does not call orders-worker — it publishes a message and returns.
Scene 04
Where the chain breaks: queues, pools, batches
- Watch
- Try it
- Predict
- Capture
What happens to the chain when a service never calls the next one at all? checkout does not make a request to orders-worker — it drops a message on a queue and returns to the customer. (How a queue stores and hands out messages is the build-kafka curriculum's job; here it is simply a barrel that holds messages.) There is no outbound request, so there is nothing to put a header on. Watch what the two halves of this checkout end up looking like.
Highlighted lines are the ones running in the diagram right now.
def publish(destination, order):span = tracer.start_span(f"publish {destination}", kind = PRODUCER,)msg = Message(body = order)with use_context(span):propagator.inject(msg.headers) # into the messagebroker.send(destination, msg)span.end()return # checkout has answered the customer
def poll_loop():loop forever:msgs = broker.poll(max_messages)origins = []for m in msgs:# extracted at process time, not at publish timectx = propagator.extract(m.headers)if ctx.is_valid():origins.append(ctx)on_batch(msgs, origins)
def on_batch(msgs, origins):parent = current_context()if len(msgs) == 1 and origins:# MAY — single message only; a link also worksparent = origins[0]span = tracer.start_span(f"process {destination}", kind = CONSUMER,parent = parent, # exactly one# span_limits.max_links defaults to 128links = [Link(c) for c in origins],)with use_context(span): handle_all(msgs)
Where this sits in Build a distributed tracing system (Jaeger / Zipkin style)
Scene 04 of 17, in the Carry it act — The header, the queue that drops it, what rides along.. A queue hop has no request to attach a header to, so the context must ride inside the message. And because one batch can have many causes while a span has exactly one parent, the consumer records a link to each.
Up next. The context now reaches every hop, including the one across the queue, so every hop produces a span in the right trace. What else is worth writing onto that span?
All 17 scenes in Build a distributed tracing system (Jaeger / Zipkin style) · Every curriculum