Skip to main content
Distributed Tracinglesson 4 of 4 · 3 min read

Tracing in Practice

One instrumentation standard

The instrumentation question has a settled answer now: OpenTelemetry.

It came from merging two earlier projects in 2019. You get vendor-neutral libraries, automatic instrumentation for common frameworks, and a collector that ships your data to whichever backend you choose.

Instrument once and switching backends later becomes a configuration change rather than a rewrite. That neutrality is why writing directly against one vendor's library today is a mistake.

Choose a backend from two camps: the self-hosted open-source ones, and the paid platforms that bundle storage, search and analytics.

Look past the waterfall view when you compare them, because the querying is the real differentiator. Finding every trace where checkout exceeded two seconds and touched the promotions service, grouped by cart size, is where the paid tools earn their invoice.

Reading a trace

Read traces by pattern recognition, and a short list covers most of the wins. A staircase of sequential sibling spans sharing no data dependency is parallelism waiting to happen.

Dozens of identical short database spans under one parent is a loop that should be one query. Repeated identical spans with gaps between them are retries. A span that ends in a timeout while its child keeps running means work continued after the caller gave up.

Watch for wide gaps between a parent and its first child, which are queue time or waits on a connection pool, and invisible to every other tool you own.

Adopt the practice that multiplies all three signals. Stamp the trace identifier onto every log line, and attach example traces to your latency metrics.

See what that gives you. A latency spike on a dashboard links to example traces, and each trace links to its logs. Metric to trace to log in three clicks is what people mean when they say observability rather than monitoring.

the shape of it
Latency spikeExample tracelinked from the graphIts log linessame trace idThe actual cause1. click through2. follow the id3. three clicks
step 1 of 3
Metric to trace to log, in three clicks, is what observability means in practice.

Worked example

Camila joins a fintech as a senior engineer and inherits a loan application API whose slowest one request in twenty, its p95, takes 6 seconds that previous efforts had failed to crack. The service already ships traces to Grafana Tempo, so she skips profiling and queries for traces over 5 seconds. The waterfall shows a tidy staircase: credit bureau call, 1.8 seconds, then income verification, 1.5 seconds, then fraud scoring, 1.9 seconds, each waiting for the previous despite none consuming another's output. A two-day change fires all three concurrently and joins the results. p95 drops from 6 seconds to 2.3, bounded by the slowest bureau. Her writeup notes that the fix required no optimization of any service, just seeing the call graph, and the follow-up ticket adds a CI check flagging sequential spans with no data dependency.

Distributed Tracing: wrapping up

In the real world

  • 01Google's 2010 Dapper paper introduced the trace and span model, describing production sampling rates around 1 in 1024 on high-traffic services with negligible overhead.
  • 02Twitter open-sourced Zipkin in 2012 as a Dapper implementation, and its B3 propagation headers are still found in systems predating the W3C traceparent standard.
  • 03Uber built Jaeger to debug its microservice sprawl and donated it to the CNCF in 2017, where it reached graduated status alongside Prometheus and Kubernetes.
  • 04OpenTelemetry formed in 2019 by merging OpenTracing and OpenCensus, and has grown into one of the CNCF's most active projects, standardizing traces, metrics, and logs in one SDK.
  • 05The W3C traceparent header became an official recommendation in 2020, so cloud load balancers and service meshes like Istio can propagate trace context without application changes.

Questions people ask

We have logs with correlation IDs. Do we still need tracing?

Correlation IDs let you collect one request's log lines, which is a big step, but you still reconstruct timing and causality by reading timestamps. Traces record the parent-child structure and precise durations directly, so an N+1 pattern or a serial call chain is visible as a shape instead of something you infer from log timestamps across machines with imperfect clocks.

How much overhead does tracing add to a request?

With sampling on, very little. Creating spans is nanoseconds of bookkeeping, and export happens off the request path in batches. Dapper measured negligible impact at 1 in 1024 sampling. The real costs are elsewhere: network and storage for span data, and collector infrastructure if you run tail-based sampling, which is why sampling strategy matters more than SDK overhead.

Is tracing worth it for a monolith?

Less urgent but still useful. A monolith calling a database, a cache, and three external APIs benefits from span timing on those calls, and in-process spans around major phases of a request show where time goes. The bigger payoff comes later: if you ever split the monolith, the propagation plumbing is already in place.

Quick review

Trace:
end-to-end record of one request. Composed of spans, one per service or operation
Span:
unit of work with start time, duration, service name, and metadata. Parent-child hierarchy
Trace ID propagated via HTTP headers:
W3C traceparent (standard), B3 (Zipkin), X-Amzn-Trace-Id (AWS)
Sampling:
100% tracing is too expensive at scale. Head-based sampling (decide at entry) or tail-based (sample slow/erroring traces)
Tools:
Jaeger (CNCF open-source), Zipkin (Twitter-originated), AWS X-Ray, Datadog APM, Honeycomb
OpenTelemetry:
vendor-neutral SDK for traces + metrics + logs. Instrument once, ship to any backend
Critical for finding N+1 queries, slow downstream dependencies, and unexpected service call chains
the trade-off

Tail-based sampling (keep slow traces) requires buffering all spans. Memory intensive. Head-based is simpler but may miss rare failures.

in the room

Microservices with latency issues. Debugging 'why is this request slow' across service boundaries.