Design Specification: pgbench Telemetry Viewer (bottle.py + Water.css + WASM)
[!NOTE] Companion specification to Evolving
pgbenchinto a Universal Database Benchmark Engine.
- 1. Architectural Principles
- 2. End-to-End Architecture
- 3. Phase 1: Run Selector, Benchmark Views & Live Monitor
- 4. Phase 2: Metatemplate Data Explorer & WASM Diagram Framework
1. Architectural Principles
- Single-JSON-Payload Database Fetch:
- Every view in the web application retrieves its entire page state from the logging/telemetry PostgreSQL database in one round-trip SQL query returning a single JSON document (
SELECT pgbench_viewer_page_json(...)orSELECT jsonb_build_object(...)). - The
bottle.pyserver acts as a thin, stateless presenter: it fetches the single JSON document from PostgreSQL (or serves it directly at/api/page.json), passes it intobottle.template(), and renders clean semantic HTML styled by classlessWater.css.
- Every view in the web application retrieves its entire page state from the logging/telemetry PostgreSQL database in one round-trip SQL query returning a single JSON document (
- Regular Telemetry Commits for Real-Time Visibility:
- In
logdb.c,pgbench_progress_log(-P) commits every interval, andstreammode (pgbench_agg_log/pgbench_tx_log) commits each flushedCOPY ... FROM STDINbatch (PQputCopyEnd+ re-initiateCOPYon next flush or interval tick). - Because stream tables are
UNLOGGED(--log-db-unlogged), committing a batch does not trigger a WAL flush (XLogFlush) on the secondary database, keeping ingestion overhead near zero while making in-flight rows immediately visible under PostgreSQLREAD COMMITTED.
- In
- Zero-Build, Modular Runtime & Source Separation (
html/,css/,wasm/,src/):- Built with standalone
bottle.py(SimpleTemplate),Water.css(css/water.css+css/viewer.css), modular HTML templates (html/*.html.stpl), and a 439-byte WebAssembly (wasm/pgbench_chart.wasm) micro-plotter that computes SVG polyline/bar coordinates and scales directly from JSON arrays. PartsLoaderinpgbench_viewer.pyloads templates, stylesheets, and the WASM binary on demand withst_mtimehot-reload caching, while non-runtime WebAssembly sources and the zero-dependency assembler (src/pgbench_chart.wat,src/pgbench_chart.c,src/build_wasm.py) are isolated insrc/. Seesrc/bin/pgbench/viewer/README.mdfor complete CLI usage and endpoint documentation.
- Built with standalone
2. End-to-End Architecture
3. Phase 1: Run Selector, Benchmark Views & Live Monitor
3.1 Single-JSON Database Payload (pgbench_viewer_json)
A single SQL query (or helper function pgbench_viewer_json(p_run_ids bigint[], p_live_run_id bigint)) returns one unified JSON document:
{
"generated_at": "2026-10-19T08:55:00Z",
"active_runs": [ ... ],
"runs_catalog": [ ... ],
"selected_run": {
"overview": { ... },
"sections": [ ... ],
"groups": [ ... ],
"scripts": [ ... ],
"recalls": [ ... ],
"commands": [ ... ],
"slas": [ ... ],
"timeseries": [ ... ]
},
"comparison": {
"mode": "pair | multi",
"run_ids": [1, 2],
"rows": [ ... ]
}
}
3.2 Phase 1 UI Components (Water.css Semantic Elements)
- Benchmark Run Selector:
- Top navigation bar and
<details>/<form>selector listing all runs fromruns_catalogwith status pills (COMPLETED,RUNNING,SLA_FAILED,ABORTED), scale, clients, TPS,p95latency, andrun_label. - Allows selecting:
- Single Run (inspects via
pgbench_show_run(run_id)) - Pair of Runs (baseline vs. candidate diff via
pgbench_compare_runs(base_id, cand_id)) - Set of Runs (multi-run checkbox selection rendered via
pgbench_compare_runs(run_ids[]))
- Single Run (inspects via
- Top navigation bar and
- Benchmark Views:
- Single-Run View: Clean
Water.csscards and tables for Overall Summary, Latency Percentiles (p50,p90,p95,p99,p99.9), Client Groups, Scripts, Vector Recall@K 10-bucket distribution & Q1-vs-Q4 Aging Degradation, Per-Statement latencies (-r), and SLA pass/fail badges. - Comparison View: Side-by-side delta table with automatic polarity coloring (
IMPROVEDin green,REGRESSEDin red,UNCHANGEDneutral).
- Single-Run View: Clean
- Live View of Currently Running Benchmark:
- Auto-detects any run in
pgbench_runswithstatus = 'running'(or lets the user pin the live tab). - Polls
/api/live.json(which executes a single SQL query joiningpgbench_runs,pgbench_progress_log, and committed batches inpgbench_agg_log/pgbench_tx_log) every 1–2 seconds and updates the live KPIs and time-series charts without page flicker.
- Auto-detects any run in
4. Phase 2: Metatemplate Data Explorer & WASM Diagram Framework
4.1 SQL Data Explorer with Python Metatemplates
Instead of a generic unformatted loop over cells, the Data Explorer uses a two-stage Python Metatemplate pipeline:
- Single-JSON Query Execution + Introspection:
-
When the user submits a
SELECTquery (or selects a preset query such as “Top Slowest Statements”, “Per-Thread Throughput Skew”, “Recall Aging Curve”, or “Latency Tail Anomalies”), the server wraps the query in a read-only transaction and extracts both column metadata and rows as a single JSON payload:WITH q AS (<user_query> LIMIT 500) SELECT jsonb_build_object( 'row_count', count(*), 'rows', COALESCE(jsonb_agg(to_jsonb(q)), '[]'::jsonb) ) FROM q;
-
- Python Metatemplate Generator (
generate_explorer_stpl_metatemplate+html/explorer_table_meta.html.stpl):infer_column_Descriptors()inspects the inferred type and name of each column in the JSON result (run_link,badge,meter_pct,meter_ratio,metric_num,num,json, ortext) and expands the Stage-1 metatemplatehtml/explorer_table_meta.html.stpl(using custom delimiter syntax<@ @> @ {| |}) into a specialized Stage-2bottle.SimpleTemplate(stpl) source string tailored to that exact result schema:- Columns ending in
_ms,_us,_sec,tps, orpctget right-aligned numeric formatting and inline proportional meter bars (meter_pct/meter_ratio). status/passed/validation_ok/verdict/sla_all_passedcolumns compile into semantic badge markup.- When rows are returned,
html/explorer_body.html.stplincludeshtml/wasm_chart_box.html.stplbound to the WASM chart renderer (renderExplorerChart()).
- Columns ending in
- The generated Stage-2 template string is also displayed in a collapsible
<details><summary>Inspect Generated stpl Metatemplate Source</summary><pre>...</pre></details>panel so users can inspect how the template was synthesized.
4.2 Minimalistic WebAssembly (WASM) Diagram Framework (wasm/pgbench_chart.wasm & src/)
To keep the frontend dependency-free and fast while supporting rich charts:
- The viewer loads a 439-byte WebAssembly statistical & 1D projection module (
wasm/pgbench_chart.wasm, expanded inline as Base64 viahtml/wasm_chart_module.html.stplwith/static/pgbench_chart.wasmstreaming fallback, and built reproducibly fromsrc/pgbench_chart.wat,src/pgbench_chart.c, andsrc/build_wasm.py):- Exported WASM interface:
memory(2 pages = 128 KiB linear memory for zero-copyFloat64Arrayviews).series_min(ptr, n) -> f64,series_max(ptr, n) -> f64,series_mean(ptr, n) -> f64\(\rightarrow\) computef64series bounds and mean in linear memory.project_1d(in_ptr, n, min_v, max_v, out_start, out_span, out_ptr)\(\rightarrow\) normalizes and projects data arrays into SVG viewport coordinates for time-series curves (tps,latency_avg_ms), HDR latency percentiles (p50..p99.9), multi-run TPS comparisons, and Explorer bar charts.
- Exported WASM interface:
- The JS bridge in
html/wasm_chart_module.html.stplfeeds numeric arrays from the page’s single JSON object into WASM linear memory (Float64Array) and renders crisp, responsive<svg>charts (html/wasm_chart_box.html.stpl) that automatically adapt toWater.csslight/dark mode (currentColor/ CSS variables).