janhoy opened a new pull request, #109:
URL: https://github.com/apache/solr-orbit/pull/109

   ## What this is
   
   `reportr` — the benchmark trends website from #99, phase 1: everything 
local, no cloud. It reads the enriched reports `launchr` writes under 
`./benchmark-results/` and emits a self-contained static site: one page per 
workload, charts of every metric over Solr's own version timeline, and the full 
report behind any point one click away.
   
   ```
   reportr build --local ./benchmark-results --serve
   ```
   
   That is the whole workflow. No S3, no registry polling, no services — the 
output is a directory of files that works from any file server.
   
   > **This stacks on #108 — please review that one first.** It is opened 
against `main` only because GitHub requires a PR's base branch to live in the 
base repository, and `launchr-phase1-local-mvp` currently exists only in the 
fork; the base will be retargeted to it. Until then the diff carries #108's two 
commits as well — `Add launchr, the benchmark orchestrator` and `Let 
SolrDockerLauncher use a configurable image repository`. Everything from `Add 
reportr, the benchmark trends site generator` onward is this PR: nine commits.
   
   ## The decisions worth arguing about
   
   **The x-axis is Solr's history, not the benchmark's.** A point sits at the 
date its Solr version was created, not the date the benchmark ran, so 
re-benchmarking an old release lands it in its correct historical position 
rather than at the right-hand edge. The version is labelled on the axis, as an 
upright chip under the date ticks — once per build rather than once per dot, 
since every line crossing that date ran the same one.
   
   **Not every point is a release.** A release is named by its version. A 
snapshot is named by where it came from and what it was built at — 
`9x#a1b2c3d`, `main-nightly` — because a nightly's version string is identical 
for every build on that branch. The word "release" appears in the UI only when 
every line on the page is one.
   
   **A line is one version kind, branch, profile and cluster config.** That is 
the whole identity, deliberately excluding the run id, the hostname and the 
workload revision: a workload change gets an annotation rather than a new line, 
so the long-run trend stays continuous. It means the site will not silently 
compare a 3-node EC2 result against a laptop run.
   
   **A query is charted on what it was driven for.** Solr Orbit now records 
each task's target throughput with the result, so reportr can tell a query held 
at three requests a second from one pushed as hard as it would go. The first 
says nothing through its throughput — that number is the rate that was asked 
for — so it is read on latency. The second is read on queries per second, and 
leads its section.
   
   **Query latency charts lead with p50 and p90.** The stock query tasks 
measure 100 iterations after warmup, and the 99th percentile of 100 samples is 
the second-highest observation — a single draw that moves run to run for 
reasons unrelated to Solr. p99 is still charted when a run carries it, because 
the tail is what users feel. It is just not the headline.
   
   **A band shows what the headline number came out of** — the slowest and 
fastest sampling interval behind a mean throughput, the median and the tail 
behind a p90. Solr Orbit reports these and nothing was drawing them, so a mean 
whose intervals ranged 3k–9k docs/s looked exactly as settled as one where 
every interval hit 4.7k.
   
   **A heatmap answers "what moved, and when?"** — one row per task, one column 
per build, signed so positive always means better. A page of line charts 
answers that question only by making you scan every one of them.
   
   **Nothing is inferred to be a regression.** What a step means is a 
judgement, and a detector that cried wolf would be worse than no annotation, so 
markers come from three places that each know something the numbers do not: the 
workload revision changed, a task's own `reportr.note` changed, or somebody 
wrote a release note in `reportr.yaml`.
   
   **Workloads describe and curate themselves.** `workload.json` has had a 
`description` field all along; Solr Orbit now carries it into the result the 
way it already carries `workload-revision`. Everything else a workload wants to 
say goes in the `meta` block Solr Orbit already merges onto every operation:
   
   ```json
   "meta": { "reportr.description": "165 million rides, and what they 
exercise." }
   { "name": "range", "operation": "range", "meta": {
       "reportr.chart": "own",
       "reportr.note": "json.facet, not the legacy facet component" } }
   ```
   
   Editing `reportr.note` is the workload saying the thing it measures is no 
longer quite the same thing, and the chart marks the point it happened. 
`reportr.yaml` overrides all of it per workload (`description`, `tasks`, 
`default_tasks`, `featured_tasks`) and rejects a misspelled key rather than 
silently ignoring it. The workload suggests; whoever runs the site decides.
   
   ## Reading the page
   
   Chips are the tasks the run measured, and nothing else, and a chip makes one 
promise: this task gets a chart of its own, inside the section for the kind of 
work it does — `range` is one of the queries, not a peer of `Query`. 
`featured_tasks` is the initial selection, not a ceiling; any task can join or 
leave it. Queries lead the page and indexing closes it.
   
   Each chart's legend carries every task of its kind and merely opens with 
some of them, so comparing one query against its neighbour never means leaving 
the chart. Sections fold from the caret and stay folded on the next visit. 
Every section and every task chart has a permalink, and a link produces what it 
points at — switching a task on and unfolding its section if it has to, since 
the URL carries none of the reader's own selection.
   
   ## Changes outside reportr
   
   Two, both in `solrorbit/metrics.py`, both additive:
   
   - `TestRun` gained `workload_description`, taken from the workload's own 
`description`, written to `as_dict()` and each result record as 
`workload-description`, round-tripping through `from_dict`. A workload without 
one omits the key rather than storing an empty string.
   - `op_metrics` entries gained a `schedule` block — target throughput and 
unit, clients, warmup and measurement windows — so a consumer reading stored 
JSON can tell how a task was driven.
   
   ## Reviewing it
   
   - `models.py`, `extract.py`, `series.py` — the data model, and what is 
deliberately tolerated (a missing percentile) versus refused (a 
`schema_version` newer than this code understands).
   - `builder.py`, `config.py` — what lands in the site, and how a workload is 
curated.
   - `site/` — the page. Vanilla HTML/CSS/JS plus a vendored Apache ECharts 
5.5.1 (Apache-2.0). Nothing is fetched from a CDN at runtime, and there is a 
test asserting that.
   
   179 reportr tests, 1610 in the suite, ruff clean.
   
   ## What is not here
   
   Cloud storage, incremental builds, retention, and deployment to 
`nightlies.apache.org` are later phases of #99. So are the dashboard-overview 
and cluster-topology ideas from the mockup.
   
   Refs #99
   
   🤖 Assisted by Claude Code
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to