One row per hop, and the id that links them — parent span ids and read-time assembly
Each hop writes one flat record carrying its own id, its parent's id and a shared trace id, and nothing is nested when it is written — the tree is rebuilt later by matching parent ids.
The recorded request became one picture because the records were tied together. This scene opens one record and shows exactly what does the tying.
Scene 02
One row per hop, and the id that links them
- Watch
- Try it
- Predict
- Capture
What actually turns five records, written on five different machines, into one picture? Watch one record fill in field by field: first the name and the times, then three ids, then two more fields. Then five records land on the rail in whatever order they finished — five flat rows with nothing nested inside anything. Watch what happens when the ids are used to link them.
Highlighted lines are the ones running in the diagram right now.
def start_span(name, ctx, kind = INTERNAL):span = Span()span.name = name # the only required argumentspan.start_time = now()parent = ctx.current_spanspan.trace_id = parent.trace_id if parent else new_id()span.span_id = new_span_id()span.parent_span_id = parent.span_id if parent else ""span.kind = kind # SERVER, CLIENT, PRODUCER, …span.status = UNSET # Ok is asserted, not inferredreturn span
def end(span):span.end_time = now()span.duration = span.end_time - span.start_time# nothing is nested here: no child is attached,# no parent is notified, no sibling is waited forexporter.enqueue(span)def on_batch(batch): # BatchSpanProcessorfor span in batch:collector.send(span) # each record travels alone
def build_tree(trace_id):rows = store.scan(trace_id = trace_id)children = defaultdict(list)root = Nonefor row in rows:if row.parent_span_id == "": # empty => rootroot = rowelse:children[row.parent_span_id].append(row)# no timestamp, host or arrival index is ever read here# a parent id naming a row that is absent matches nothingreturn render(root, children)
Where this sits in Build a distributed tracing system (Jaeger / Zipkin style)
Scene 02 of 17, in the Why trace act — Per-service records can't blame a hop; one id can.. Each hop writes one flat record carrying its own id, its parent's id and a shared trace id. Nothing is nested when it is written — the tree is rebuilt later, which is why a missing record leaves a plausible-looking hole.
Up next. The tree only assembles because every record already carried the same trace id and a pointer to its parent. So how does the next service learn that id in the first place?
All 17 scenes in Build a distributed tracing system (Jaeger / Zipkin style) · Every curriculum