Predict what a change does to latency, from the traces you already collect.
rhobound-cli reads OpenTelemetry traces, rebuilds your service graph and predicts the mean latency of every service, before and after a change. One static Go binary, open source under Apache-2.0.
- Apache-2.0
- Go 1.23+
- Single static binary
- Standard library only
- OpenTelemetry in
$ rhobound predict testdata/capture-chain --patch b=+6ms
capture testdata/capture-chain
window 120 s, 3099 entry requests (25.8 /s), 15495 spans
busiest c at 26% utilization
service own ms model ms seen ms err % after ms change ms change %
a * 7.83 45.22 43.74 +3.4 52.37 +7.15 +15.8
b 19.94 35.40 35.91 -1.4 42.56 +7.15 +20.2
c 9.98 13.75 14.06 -2.2 13.71 -0.04 -0.3
change applied: b +6 ms * entry service+6 ms of work in b makes the entry service 7.15 ms slower, because b also queues more. That extra waiting is what a model of the whole graph captures and a per-service benchmark doesn’t.
What it does
Reads the traces you already collect
Point it at OTLP/JSON files from the OpenTelemetry Collector’s file exporter, plain or gzipped. It reads only ids, kinds, times and a few resource attributes.
Rebuilds your architecture
Which service calls which, how often, and whether calls run in turn, in parallel or in stages. For every pod it reads the worker count and the service time without the wait.
Models each service as a queue
M/G/c queues with Erlang C and the Allen-Cunneen correction. Arrival burstiness is carried through the graph, and parallel calls take the expected maximum of correlated branches.
Answers what-if questions
Say that checkout does 3 ms more work, or 10% more, and see the effect on every service above it, including the extra waiting a busier service causes.
Refuses instead of guessing
When the data or the load is outside what it can model, it stops and says why, rather than printing a number that looks right.
Yours to script and extend
Machine-readable output with --json, the inferred graph as plain topology JSON, and a model command to evaluate a topology you write or edit at any request rate.
Install and run
# install
go install github.com/Sharvil2704/rhobound-cli/cmd/rhobound@latest
# or build from source
git clone https://github.com/Sharvil2704/rhobound-cli.git
cd rhobound-cli && go build -o bin/rhobound ./cmd/rhobound
# try the example capture that ships in the repository
rhobound predict testdata/capture-chain --patch b=+6msCommands
rhobound predict CAPTURE [--patch svc=+3ms,...]Infer the call graph from traces and predict the mean latency, before and after a change.
rhobound infer CAPTUREPrint the inferred call graph as topology JSON.
rhobound model TOPOLOGY.json --rps NEvaluate a topology you wrote or edited, at N requests per second.
rhobound versionPrint the version.
Common flags: --workers, --kept-share, --max-rho, --plain, --json, --out. Every flag is in USAGE.md.
What you give it
Traces, and nothing else. No metrics, no logs, no access to your cluster.
- SERVER spans, and CLIENT spans for outgoing calls, with W3C trace context across services.
service.nameandk8s.pod.name(orservice.instance.id) on each span’s resource.- Every request, or a known head-sampling share with
--kept-share. - One steady window of at least 100 entry requests. A few minutes at 20 or more requests per second is a good start.
- OTLP/JSON files in
CAPTURE/traces/, as the Collector’s file exporter writes them.
REQUIREMENTS.md has an example Collector configuration.
How it works
Read
The trace files are read in parallel, keeping only ids, kinds, times and a few resource attributes.
Infer the graph
Calls, their frequency and their order. Health probes are dropped, and calls sent after the response stay off the latency path.
Rebuild each pod’s queue
First come, first served, from the spans, to read the worker count and the service time without the wait.
Model
Every service becomes an M/G/c queue, with arrival variability carried through the graph.
Predict the change
Apply +N ms or +N% to a service, solve again, and read the new latency of every service above it.
Measured
- 2.0%Median error on entry latency across 288 simulated scenarios at 70% to 80% utilization.
- 46.15 msPredicted entry latency on a Kubernetes (kind) demo, against 46.10 ms measured.
- −0.8% to +1.4%Entry latency against the traces, on five captures of real Python services at 55% to 57% utilization.
Measured on simulated systems, a Kubernetes demo and real Python services. Method and every table are in ACCURACY.md.
Documentation
USAGE
The command line step by step: capture, infer, predict, model, flags and exit codes.
REQUIREMENTS
What the traces must contain, how much data, and an example Collector configuration.
DEMO
What a result looks like: the example capture line by line, and the Kubernetes demo.
BUILD
Building, cross-compiling, installing and running the tests.
ACCURACY
The full accuracy study: method, tables and results.
VALIDATION
Every check that has been run.