Chronicle — a longitudinal reporting server for Choreo test performance analytics
Project description
Chronicle — Longitudinal Test Performance Analytics
A reporting server that ingests Choreo test results over time, stores them in TimescaleDB, detects latency regressions automatically, and serves an interactive dashboard. It answers questions no single test report can: "Is this topic getting slower?", "What regressed after Tuesday's deploy?", "Which topics have the most budget violations this month?"
- Python 3.11+ / FastAPI / SQLAlchemy 2.0 async / asyncpg
- TimescaleDB for time-series storage with continuous aggregates
- React + Recharts dashboard (pre-built, included in the wheel — no Node.js needed)
Install
pip install choreo-chronicle
For development from source:
pip install -e 'packages/chronicle[test]'
Quick start
# 1. Start TimescaleDB
docker run -d --name chronicle-db \
-p 5433:5432 \
-e POSTGRES_USER=chronicle \
-e POSTGRES_PASSWORD=chronicle \
-e POSTGRES_DB=chronicle \
timescale/timescaledb-ha:pg18
# 2. Run migrations
DATABASE_URL=postgresql+asyncpg://chronicle:chronicle@localhost:5433/chronicle \
python -m chronicle migrate
# 3. Start the server
DATABASE_URL=postgresql+asyncpg://chronicle:chronicle@localhost:5433/chronicle \
python -m chronicle
# 4. Ingest a test report
curl -X POST http://localhost:5173/api/v1/runs \
-H "Content-Type: application/json" \
-H "X-Chronicle-Tenant: my-team" \
-d @test-report/results.json
# 5. Open the dashboard
open http://localhost:5173
CLI
python -m chronicle # start dev server (hot reload on :5173)
python -m chronicle --no-reload # start without reload
python -m chronicle migrate # run database migrations (upgrade to head)
python -m chronicle migrate status # show current migration revision
python -m chronicle migrate downgrade -1 # rollback one migration
All commands read DATABASE_URL or CHRONICLE_DATABASE_URL from the
environment.
CI integration
Add one line to your pipeline after pytest completes:
curl -X POST https://chronicle.internal/api/v1/runs \
-H "Content-Type: application/json" \
-H "X-Chronicle-Tenant: my-team" \
-d @test-report/results.json
API
All endpoints under /api/v1/. Interactive docs at /api/v1/docs.
| Method | Path | Purpose |
|---|---|---|
POST |
/runs |
Ingest a test-report-v1 JSON report |
GET |
/runs |
List runs for a tenant |
GET |
/runs/{id} |
Run detail with scenarios |
GET |
/runs/{id}/raw |
Original JSON as ingested |
GET |
/tenants |
List tenants |
GET |
/topics |
List topics with latency stats |
GET |
/topics/{topic}/latency |
Time-series p50/p95/p99 data |
GET |
/topics/{topic}/runs |
Runs containing a topic |
GET |
/anomalies |
Anomaly feed |
GET |
/anomalies/topics/{topic} |
Anomalies for a topic |
GET |
/stream |
SSE live events |
GET |
/health |
Health check (shallow + deep) |
Architecture
Repository + Service Layer (ADR-0021). Three layers with strict import direction:
api/ → services/ → repositories/ → models/
(thin routes) (business logic) (database access) (ORM tables)
The ingest pipeline flows through IngestService.ingest():
validate → normalise → persist (single transaction with COPY) →
detect anomalies (separate session) → broadcast SSE events.
Configuration
All config via environment variables with CHRONICLE_ prefix.
DATABASE_URL accepts both prefixed and unprefixed forms.
DATABASE_URL=postgresql+asyncpg://user:pass@db:5432/chronicle
CHRONICLE_ENVIRONMENT=production # triggers startup validation
CHRONICLE_LOG_FORMAT=json # required in production
CHRONICLE_DB_POOL_SIZE=10
CHRONICLE_MAX_SSE_CONNECTIONS=200
The app refuses to start in production with default localhost credentials.
See config.py for the full list.
Distribution
The React dashboard is pre-built in CI and included in the Python wheel
via Hatchling force-include. When a consumer runs pip install choreo-chronicle, they get a working dashboard without Node.js:
choreo_chronicle-0.1.0.whl
chronicle/
app.py, config.py, ...
static/ ← pre-built React app
index.html
assets/index-*.js
assets/index-*.css
FastAPI serves the static files at / and the API at /api/v1/.
Tests
# Unit + integration (no database needed)
pytest packages/chronicle/tests/
# Unit only
pytest packages/chronicle/tests/unit/
# E2E against real TimescaleDB
docker compose -f docker/compose.chronicle.yaml up -d
python -m chronicle migrate
pytest packages/chronicle/tests/ -m chronicle_db
The test suite includes Hypothesis property-based tests and API fuzz testing. DB tests truncate all tables after each test for isolation.
Design docs
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file choreo_chronicle-1.0.0.tar.gz.
File metadata
- Download URL: choreo_chronicle-1.0.0.tar.gz
- Upload date:
- Size: 433.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
809bb6242f032ca4617a047693b7b6bbfa4e8e61a6fb213be5e5dc084617532a
|
|
| MD5 |
a60030ee4efe7902c275c0cb3cfda934
|
|
| BLAKE2b-256 |
8b84cb95c70cf787edf373b8d035eb44bb3a6d99c1e357933ef39cdcadb6743f
|
Provenance
The following attestation bundles were made for choreo_chronicle-1.0.0.tar.gz:
Publisher:
release.yml on clear-route/choreo
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
choreo_chronicle-1.0.0.tar.gz -
Subject digest:
809bb6242f032ca4617a047693b7b6bbfa4e8e61a6fb213be5e5dc084617532a - Sigstore transparency entry: 1439278680
- Sigstore integration time:
-
Permalink:
clear-route/choreo@529361b13df52808255ea8d5b16661d84e98065f -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/clear-route
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@529361b13df52808255ea8d5b16661d84e98065f -
Trigger Event:
push
-
Statement type:
File details
Details for the file choreo_chronicle-1.0.0-py3-none-any.whl.
File metadata
- Download URL: choreo_chronicle-1.0.0-py3-none-any.whl
- Upload date:
- Size: 327.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.8
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
199e48583a77ab0a9c774ef2968a0717a7c03af6ec3c10ada25cb4a302e1c63d
|
|
| MD5 |
fff66f0640820c87587854b0dfce27c2
|
|
| BLAKE2b-256 |
adf7f99237cc10226a264ae1e758d5eb3b5add60ab02274f5df59fe40cb6afac
|
Provenance
The following attestation bundles were made for choreo_chronicle-1.0.0-py3-none-any.whl:
Publisher:
release.yml on clear-route/choreo
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
choreo_chronicle-1.0.0-py3-none-any.whl -
Subject digest:
199e48583a77ab0a9c774ef2968a0717a7c03af6ec3c10ada25cb4a302e1c63d - Sigstore transparency entry: 1439278701
- Sigstore integration time:
-
Permalink:
clear-route/choreo@529361b13df52808255ea8d5b16661d84e98065f -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/clear-route
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@529361b13df52808255ea8d5b16661d84e98065f -
Trigger Event:
push
-
Statement type: