Distributed Systems for Backend Engineers · Distributed Systems in Practice

Observing Distributed Systems

Tracing, correlation and debugging across services and queues.

Debugging distributed systems requires following a request across services and async hops: distributed tracing (OpenTelemetry, W3C traceparent propagated through HTTP and message headers), correlation IDs in logs, span links for batch/async work, and service maps built from traces. Measure end-to-end latency of async workflows (event created → processed) and per-hop queue time.

Context propagation

Hop type Propagation Span relationship
HTTP / gRPC traceparent header Child span
Message queue traceparent in message headers/attributes Child or link
Batch processing many messages Each message's context Span links to all producers
Scheduled job New trace Link to triggering event if any

Python (OpenTelemetry + Kafka headers)

from opentelemetry import propagate, trace
tracer = trace.get_tracer("orders")

def publish(producer, topic, event):
    headers = {}
    propagate.inject(headers)                                     # adds traceparent
    producer.send(topic, value=event, headers=[(k, v.encode()) for k, v in headers.items()])

def consume(record):
    ctx = propagate.extract({k: v.decode() for k, v in record.headers})
    with tracer.start_as_current_span("process order.paid", context=ctx):
        handle(record.value)

Common pitfalls

  • Traces that stop at the first queue.
  • Logs without trace IDs.
  • Measuring only synchronous latency for async workflows.

Key points

  • Propagate context through queues
  • Span links for batches
  • Measure end-to-end async latency

Further reading: OpenTelemetry: Messaging semantic conventions

Practice questions

How do you continue a trace across a Kafka message?

Answer

Inject the trace context (traceparent) into message headers when producing and extract it when consuming to start the consumer span with that parent.

When are span links better than parent-child spans?

Answer

When one operation processes many messages from different traces (batching), linking to each producer span instead of picking one parent.

Open in the app to mark lessons complete, take notes and track your progress.