Skip to content
BytePatterns

Critical Path Through a Trace

MediumSystem Design#distributed-tracing#interval-union#tree-walk~25m

Problem

A distributed trace is a tree of spans, each (id, parent, service, start, end) in milliseconds, with exactly one root whose parent is None. A span's self time is its duration minus the time covered by at least one of its children, since children can run in parallel and overlap. Return two things: the total self time per service, as a dict sorted by service name, and the critical path, found by starting at the root and repeatedly stepping into the child that ends last, taking the first listed on a tie, until a span has no children. There are up to 100,000 spans.

Examples

Input:  a gateway 0-100 calls auth 5-20 and orders 20-90;
        orders calls db 25-60, cache 30-40 and db again 55-85
Output: ({'auth': 15, 'cache': 10, 'db': 65, 'gateway': 15, 'orders': 10}, ['a', 'c', 'f'])
Why:    the db calls overlap, so orders only covers 25-85 with children; the second db call ends last
Input:  [("r", None, "api", 0, 50), ("p", "r", "search", 0, 50), ("q", "r", "ads", 10, 30)]
Output: ({'ads': 20, 'api': 0, 'search': 50}, ['r', 'p'])
Why:    the api span is fully covered by its children, so all of its time is spent waiting
Input:  [("x", None, "web", 0, 10)]
Output: ({'web': 10}, ['x'])
Why:    edge case, a trace with one span spends all its time in that span

Hints

0 / 3

Stuck on the idea rather than the code? Tracing a Request covers it.