How Zipkin Collects and Processes Sleuth Tracing Data – Deep Dive into Spans
This article explains Zipkin’s data model, how Spring Cloud Sleuth generates and sends Span and Annotation information, the message‑channel listener that converts Sleuth spans to Zipkin spans, debugging techniques to observe the collected data, and why the number of spans shown in Zipkin’s UI can differ from the raw count.
Data Model
Zipkin’s model mirrors Google’s Dapper and consists of four core concepts: Span: a basic work unit identified by a 64‑bit Span ID and linked to a Trace ID; it stores timestamps, annotations, binary annotations, and parent Span ID. Trace: a tree of Spans that share the same Trace ID, representing an entire request flow. Annotation: a timestamped event label. Sleuth defines four core annotations for an HTTP request: cs (Client Send), sr (Server Received), ss (Server Send), and cr (Client Received). The time differences between these annotations give network latency, server processing time, and total request time. BinaryAnnotation: key‑value pairs that add extra context (e.g., HTTP method, URL, service name) to a Span.
Collection Mechanism
When a client calls trace‑1, Sleuth creates a series of Spans and annotations. The article’s example shows ten labelled events (1‑10) that map to four distinct Spans (T, A, B, C). Each Span records its Trace ID, Span ID, and relevant annotations, allowing calculation of network delay, server processing time, and total latency.
The process can be visualised as follows:
Message‑Channel Listener
Sleuth integrates with Spring Cloud Stream. The listener class ZipkinMessageListener receives Spans objects from the channel SleuthSink.INPUT (topic sleuth) and converts them to Zipkin’s zipkin.Span type before forwarding to the collector.
@MessageEndpoint
@Conditional(NotSleuthStreamClient.class)
public class ZipkinMessageListener {
final Collector collector;
@ServiceActivator(inputChannel = SleuthSink.INPUT)
public void sink(Spans input) {
List<zipkin.Span> converted = ConvertToZipkinSpanList.convert(input);
this.collector.accept(converted, Callback.NOOP);
}
// ...
}Span Conversion and Debugging
During debugging, two batches of spans are observed: three spans from trace‑1 and two spans from trace‑2, totaling five spans sent to Zipkin. The UI shows five raw spans but merges the two B‑spans (originating from the same HTTP request) into a single entry, resulting in a “Total Spans” count of four.
Key code from Sleuth’s Span class shows how IDs are rendered as hexadecimal strings for display:
public String toString() {
return "[Trace: " + idToHex(this.traceId) + ", Span: " + idToHex(this.spanId) + ", Parent: " + getParentIdIfPresent() + ", exportable:" + this.exportable + "]";
}
public static String idToHex(long id) {
return Long.toHexString(id);
}Parent IDs, Root Span, and Merging
Each Span carries a parentId that links it to its predecessor. The Span with a null parentId is the Root Span. By traversing from the Root Span, the full call chain can be reconstructed. The article provides a table (illustrated with an image) that maps each Span (T, A, B, C) to its host, IDs, and annotations.
Because the two B‑spans belong to the same logical work unit, Zipkin merges them for the detailed view, which explains the discrepancy between the raw span count (5) and the total shown in the UI (4).
Visual Summary of Span Collection
The final diagram ties together the generation, conversion, and merging steps, illustrating how Sleuth’s annotations become Zipkin spans and how they are presented in the Zipkin UI.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Programmer DD
A tinkering programmer and author of "Spring Cloud Microservices in Action"
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
