// zombie-work x-ray for OpenTelemetry traces

Is your backend doing work nobody is waiting for?

Drop in OpenTelemetry traces. See how much work was wasted on retries and on callers that had already given up, and which fix is missing.

No traces handy?
or run locally curl --data-binary @traces.json <this site>/api/analyze

  • No install
  • No account
  • Analyzed in memory, never stored or logged

// how it works

It counts the work nobody used.

xray reads the spans of each trace, matches every call to the work it caused downstream, and checks who was still waiting for the answer.

01 · MEASURE

Amplification and goodput

How many calls one user request causes, and how much of a callee's running time the caller actually used.

02 · DETECT

Zombie work

Work that kept running after its caller gave up, and for how long, all the way down the chain.

03 · FIX

The missing guard

Every finding names its fix: a retry budget, backoff, or sending the caller's remaining time downstream.

The bundled retry-storm sample, drawn to scale
Three jobs of 3.0 s each: 9.0 s of work, 6.0 s of it after the caller had left, none of it used.

// private by design

Your traces are looked at, not kept.

IN MEMORY

Parsed, analyzed, dropped

Nothing you upload is written anywhere. There is no account to create and nothing to sign in to.

NOT LOGGED

Errors never repeat your data

Messages name the file, the line and the kind of problem, never what was inside the file.

BOUNDED

Hard limits

The server enforces a few files per request.

// bring your own traces

Export them with the Collector.

Every service needs OpenTelemetry tracing with context propagation, so a call from one service and the work it causes in the next end up in the same trace. Then write the traces to a file with the OpenTelemetry Collector's file exporter.

Supported: OTLP/JSON (one export request per line, or one document), the OpenTelemetry Python SDK's span JSON, Zipkin v2 JSON (an array of spans), and Jaeger Trace JSON (save the page the Jaeger UI's Trace JSON option opens, or fetch it from the query API at /api/traces). Optional: if a service queues requests before running them, set the span attribute app.queue_wait_ms on its server span, so waiting is not counted as work.

exporters:
  file:
    path: /data/otlp-traces.json
service:
  pipelines:
    traces:
      receivers: [otlp]
      exporters: [file]