A layer that isn't your app — collector agents and the gateway pool

A collector tier takes the jobs no application should do — stamping where the span ran, stripping anything sensitive, absorbing bursts, fanning out to more than one backend — and the whole-trace decision has to live in its central pool, because only a pool can be routed to.

Previously

The exporter ships batches to an endpoint we have not yet named. Something is on the other end of that connection, and it is doing more than writing rows.

Scene 11

A layer that isn't your app

  1. Watch
  2. Try it
  3. Predict
  4. Capture
collector tier: what each hop can see, add, and take awayinstrument → export → collect → sample → store → find → readinstrumentexportcollectagents + a routable poolsamplestorefindreadappsagentsgateway poolbackendsnode-1gatewaycheckoutcartnode-2inventorypaymentsledgeragent · node-1sees 3 local processesagent · node-2sees 3 local processesgateway-1gateway-2gateway-3steps applied at the gateway poolon · redacton · enrichon · tail-sampletrace storewhole traces land hereone span, hop by hopgreen = gained · rose struck = removedpayments · app process+ service.name+ http.routehands off locally, then forgets✓can one box here see a whole trace?the pool can be routed to — hash the trace id and all six spans land on one gatewayOnly a pool can be routed to by trace id, which is why the whole-trace decision, the strip and the fan-out all live here and nowhere upstream.
What to watch for

What is actually on the other end of the connection the application ships its batches to? Watch one span travel there. It leaves payments knowing what it did but not where it ran; a program on the same machine stamps its pod, its node and its region; a central pool strips a card number out of it before anything leaves the cluster; and the same span is then written to two different places from one pipeline, without payments ever learning there are two. That layer — not your application, not your storage — is a collector, and none of those four jobs belonged in the application.

Continue unlocks when the animation finishes.
Implementation

Highlighted lines are the ones running in the diagram right now.

Collector.pipeline
every batch runs the same ordered list of jobs
def pipeline(batch):
if memory_used() > soft_limit:
return refuse(batch, retryable=True)
batch = enrich(batch, resource_of(self.host))
batch = redact(batch)
batch = regroup_into_batches(batch)
batch = tail_sample(batch) # regroups by trace id
for dest in self.destinations:
dest.send(batch)
Agent.can_decide
a collector deployed one per machine
# one per machine; each app exports to localhost
def receives(self):
return union(p.spans for p in processes_on(self.node))
def can_decide(self, trace_id):
held = self.buffer[trace_id]
return held == every_span_of(trace_id)
def resource_of(self, host):
return lookup(host) # k8s.pod, host.name, cloud.region
Gateway.can_decide
a pool with one address in front of it
# a scaled pool of interchangeable boxes
def route(span):
i = consistent_hash(span.trace_id) % len(pool)
return pool[i]
def receives(self):
return [s for s in arriving if route(s) is self]
def can_decide(self, trace_id):
held = self.buffer[trace_id]
return held == every_span_of(trace_id)

Where this sits in Build a distributed tracing system (Jaeger / Zipkin style)

Scene 11 of 17, in the Pipeline act — Off the hot path, then a tier that isn't your app.. A collector tier takes the jobs no application should do: stamping where a span ran, stripping anything sensitive, absorbing bursts, fanning out. Tail decisions live in its pool, because only a pool can be routed to.

Up next. The gateway pool is the last place a trace's spans are together in memory. Then they are written down — under what key, and what has to happen before you can read a whole trace back?

All 17 scenes in Build a distributed tracing system (Jaeger / Zipkin style) · Every curriculum

Built with Arqly
Every scene in Build a distributed tracing system (Jaeger / Zipkin style) builds on the one before it.All 17 Build a distributed tracing system (Jaeger / Zipkin style) scenes