CRISP identifies which spans are on the critical path of a distributed trace and tells you exactly where latency comes from. Given a directory of Jaeger traces for a single service/operation, it produces:
- HTML report — interactive per-operation heatmap of critical-path time across all traces
- Flame graphs — per-percentile SVG flame graphs (P50, P75, P95, …) via Brendan Gregg's FlameGraph
- Calling-context tree (CCT) —
.cctand.dotfiles for downstream graph analysis - Protobuf output —
.pbbinary using the bundledanalyzer.protoschema - CSVs — per-trace stats, latency percentiles, saving potential, cross-region calls, error depth
The original paper: CRISP: Critical Path Analysis of Large-Scale Microservice Architectures, USENIX ATC '22.
Coming soon — the
crisp-tracePyPI package is not yet published. Install from source in the meantime (see Development).
To also run the HTTP streaming service, install the optional [server] extras:
pip install -e ".[server]" # adds fastapi, uvicorn[standard], aiofiles, httpx1. Collect Jaeger traces for a single service + operation into a directory — each trace is a .json file from the Jaeger HTTP API.
2. Run the analyzer:
crisp-trace \
-a checkout \
-s frontend \
-i traces/ \
-o output/ \
--parallelism 83. Open the report:
open output/criticalPaths.html # macOS
xdg-open output/criticalPaths.html # Linuxcrisp-trace [-h] -a OPERATIONNAME -s SERVICENAME [-i INPUTDIR] [--file FILE]
[-o OUTPUTDIR] [--parallelism PARALLELISM]
[--topN TOPN] [--numHMTrace NUMHMTRACE] [--numOperation NUMOPERATION]
[--lightMode] [--errorAnalysis] [--doRanges]
[--mergeAllRoots | --no-mergeAllRoots] [--rootTrace] [--anonymize]
[--tags TAGS] [--exclude-from-cp EXCLUDEFROMCP]
[--maxExemplars MAXEXEMPLARS]
[--deltaMicroSec DELTAMICROSEC]
[--deltaTargetService DELTATARGETSERVICE]
[--deltaTargetOperation DELTATARGETOPERATION]
[--jaegerQueryUrl JAEGERQUERYURL]
| Flag | Default | Description |
|---|---|---|
-a, --operationName |
(required) | Jaeger operation name to analyze |
-s, --serviceName |
(required) | Jaeger service name |
-i, --inputDir |
(required) | Directory of Jaeger trace .json files (mutually exclusive with --file) |
--file |
— | Single Jaeger trace file (mutually exclusive with --inputDir) |
-o, --outputDir |
same as --inputDir |
Directory where output files are written |
--parallelism |
1 | Number of parallel worker processes |
| Flag | Default | Description |
|---|---|---|
--lightMode |
off | Fast single-pass CCT + protobuf output; skips HTML/CSV generation |
--errorAnalysis |
off | Run error-path analysis in addition to critical-path analysis |
--doRanges |
off | Produce flame graphs for every 20-percentile window (P0–P20, P20–P40, …) |
--topN |
20 | Max services shown in the summary |
--numHMTrace |
200 | Max traces shown in the heatmap |
--numOperation |
20 | Max operations shown in the heatmap |
--mergeAllRoots / --no-mergeAllRoots |
on | Merge metrics from every matching root span vs. only the first |
--rootTrace |
off | Require the service/operation to be the root span of the trace |
--anonymize |
off | Anonymize service and operation names in output |
--maxExemplars |
3 | Max exemplar (trace/span) pairs kept per call path in .pb output |
| Flag | Description |
|---|---|
--tags YAML |
YAML list of {name, value, search_depth} tag filters to apply before analysis |
--exclude-from-cp FILE |
YAML file listing operations to exclude from the critical path |
--ignoreTestTraces |
Skip traces marked as synthetic test traces |
| Flag | Description |
|---|---|
--deltaMicroSec N |
Simulate adding/removing N µs from the target service/operation |
--deltaTargetService SVC |
Service to target for latency projection (use with --deltaMicroSec) |
--deltaTargetOperation OP |
Operation to target for latency projection (use with --deltaMicroSec) |
| Flag | Default | Description |
|---|---|---|
--jaegerQueryUrl URL |
— | Base URL for the Jaeger query HTTP API (used by crisp.get_trace) |
| File | Description |
|---|---|
criticalPaths.html |
Interactive HTML report with per-operation heatmap |
flame-graph-P{N}.svg |
SVG flame graph at percentile N (requires perl on PATH) |
*.cct |
calling-context tree in folded-stack format |
*.dot |
GraphViz DOT representation of the call-chain tree |
*.pb |
Protobuf binary (AnalyzeResponse message from crisp/proto/analyzer.proto) |
criticalPath*.csv |
Per-trace latency breakdown |
timeSaved*.csv |
Per-operation saving potential |
error*.csv |
Error depth / propagation stats (requires --errorAnalysis) |
CRISP ships an optional FastAPI server that exposes the same critical-path analysis over HTTP with a streaming protobuf wire protocol, suitable for programmatic integration.
pip install -e ".[server]"
uvicorn crisp.server:app --host 0.0.0.0 --port 8080| Method | Path | Description |
|---|---|---|
GET |
/health |
Liveness check — returns {"status":"ok"} |
POST |
/v2/trace/analysis/stream |
Analyze one window of traces; returns a streaming protobuf response |
POST |
/v2/trace/analysis/compare |
Analyze two windows and diff them; returns a streaming protobuf response |
Both POST endpoints accept a binary request body consisting of length-prefixed protobuf messages (StreamAnalyzeRequest / CompareAnalyzeRequest defined in crisp/proto/analyzer.proto):
[varint length][StreamAnalyzeRequest bytes] [varint length][trace JSON bytes] ...
The response is a stream of length-prefixed AnalyzeResponse protobuf messages written as they become available.
- Python 3.11 (what CI and Bazel use)
- Perl — only needed to generate SVG flame graphs; the rest works without it
brew install python@3.11 bazelisk
cd /path/to/CRISP
python3.11 -m venv .venv
source .venv/bin/activate
pip install -U pip
pip install -r requirements_lock.txt
bash scripts/ci-local.sh # pytest + smoke tests
bazel test //... # Bazel build + testpython3.11 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -U pip
pip install -r requirements_lock.txt
bash scripts/ci-local.sh # same checks as the CI "Python 3.11" jobOne-liner (no venv management; uses whatever python3 is first on PATH):
bash scripts/ci-local.sh --installSet PYTHON=/path/to/python3.11 if your default interpreter is not 3.11.
With Bazel (Bazelisk)
bazel test //... # Bazelisk reads .bazelversion and downloads the right BazelThird-party packages come from requirements_lock.txt via rules_python in MODULE.bazel.
-
Edit
requirements.in. -
Regenerate the lockfile (requires
pip-tools):PIP_INDEX_URL=https://pypi.org/simple \ pip-compile requirements.in -o requirements_lock.txt \ --strip-extras --no-emit-index-url
-
Re-run
bash scripts/ci-local.shandbazel test //....
| Problem | Fix |
|---|---|
python3.11: command not found |
macOS: brew install python@3.11, add /opt/homebrew/bin to PATH. Linux: apt install python3.11-venv. Windows: install Python 3.11. |
bazel: command not found |
macOS: brew install bazelisk. Other: download from Bazelisk releases. |
Wrong Python in .venv |
rm -rf .venv && python3.11 -m venv .venv |
ModuleNotFoundError / missing pytest |
source .venv/bin/activate && pip install -r requirements_lock.txt |
pip-compile: command not found |
pip install pip-tools |
| Flame graph SVGs not generated | Install Perl (perl -v). The .pl scripts live in crisp/ and are invoked automatically; no manual chmod needed. |
| Bazel downloads wrong version | Use Bazelisk, not a manually installed Bazel — it reads .bazelversion. |
| Job | What it runs |
|---|---|
| Python 3.11 | pip install -r requirements_lock.txt, then scripts/ci-local.sh |
| Bazel | bazel test //... (skipped if no BUILD.bazel files exist) |
Unit tests for the HTTP service live in tests/service/ and tests/test_server.py; end-to-end integration tests are in tests/test_e2e_server.py.
- Artifact from the original CRISP paper: https://zenodo.org/records/13956078
- ~1.4 million production traces from The Tale of Errors in Microservices: https://zenodo.org/records/13947828
Please cite our papers if you use the datasets in your research.
- Calligator — a critical-path analysis and resource-optimization tool for microservices that vendors CRISP (
third_party/CRISP) for graph-based critical-path summaries and flamegraph generation, building trace retiming and resource-reallocation recommendations on top.
@inproceedings{zhang2022crisp,
title={$\{$CRISP$\}$: Critical path analysis of $\{$Large-Scale$\}$ microservice architectures},
author={Zhang, Zhizhou and Ramanathan, Murali Krishna and Raj, Prithvi and Parwal, Abhishek and Sherwood, Timothy and Chabbi, Milind},
booktitle={2022 USENIX Annual Technical Conference (USENIX ATC 22)},
pages={655--672},
year={2022}
}