Skip to content

Commit 29fae38

Browse files
thinkingfishclaude
andcommitted
feat(wasm-viewer): Save as Report works offline via shared report-save crate
The static-site WASM viewer's Save as Report button was POSTing to `/api/v1/save_with_selection`. On rezolus.com (a static deployment with no backend) the CDN returned 405 Method Not Allowed. Port the trim + tarball-repack flow into a shared workspace crate so both the server viewer and the WASM viewer run the same projection logic. ## Shared crate: `crates/report-save/` Single source of truth for the trim/embed/tarball flow: - `ReportPayload` / `ReportEntry` / `Side` payload types - `resolve_kept_columns` (generic over `T: Deref<Target = Tsdb>`) - `save_single_parquet(Bytes, …) -> Vec<u8>` - `save_combined_ab_tarball(Bytes, Bytes, manifest_bytes: &[u8], …) -> Vec<u8>` - All operating on `metriken_query::Bytes` — the unified primitive the server reads paths into and the WASM viewer already holds. - 10 unit tests covering kept-column resolution + the full round-trip for both trim/no-trim and single/AB paths. The shared crate is manifest-agnostic: it takes pre-serialized manifest bytes for the AB tar entry, so it doesn't need to know about either crate's `AbContainers` struct. ## Server-side shim: `src/viewer/report_save.rs` Reads paths into `Bytes`, serializes the binary crate's `AbContainers`, delegates to `report-save`. ~70 LOC (was ~250 LOC of trim logic + tests). ## WASM-side shim: `crates/viewer/src/report_save.rs` Synthesizes an `AbContainers` manifest from the two attached viewers (compare mode loads two separate parquets — there's no pre-existing tar manifest), serializes it, delegates to `report-save`. The WASM crate keeps its own `AbContainers` definition since it doesn't depend on the rezolus binary crate. `Viewer` now keeps the original parquet `Bytes` alongside the Tsdb so the trim writer can project columns from the source schema (the Tsdb has lost Arrow field metadata like the `metric` key that `parquet filter`'s keep-field predicate needs). `WasmCaptureRegistry::save_with_selection(payload_json)` dispatches based on slot attachment. ## Unified JS surface Both `site/viewer/lib/viewer_api.js` (WASM) and `src/viewer/assets/lib/viewer_api.js` (server) expose `saveWithSelection(payload) -> { bytes, mime, extension }`. `saveToParquet` in `selection.js` calls through `ViewerApi` instead of raw XHR — swaps the filename's `.parquet` suffix for the reported extension so AB tarballs land as `*.parquet.ab.tar`. ## Cost WASM bundle: 3.6 MB → 4.3 MB (parquet writer + tar). The `no_asm` zstd-sys feature is target-scoped — resolver 2 doesn't propagate it to `cargo build --bin rezolus`, so the standalone binary's zstd keeps its x86 asm path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 5e0cc7b commit 29fae38

11 files changed

Lines changed: 910 additions & 661 deletions

File tree

Cargo.lock

Lines changed: 16 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[workspace]
2-
members = [".", "crates/dashboard", "crates/systeminfo", "crates/viewer"]
2+
members = [".", "crates/dashboard", "crates/report-save", "crates/systeminfo", "crates/viewer"]
33
exclude = ["xtask"]
44
resolver = "2"
55

@@ -21,13 +21,14 @@ serde = { version = "1.0.228", features = ["derive"] }
2121
serde_json = "1.0.149"
2222
thiserror = "2.0.18"
2323
dashboard = { path = "crates/dashboard" }
24+
report-save = { path = "crates/report-save" }
2425
include_dir = "0.7.4"
2526
walkdir = "2.5.0"
2627
wasm-bindgen = "0.2.120"
2728

2829
[package]
2930
name = "rezolus"
30-
version = "5.13.1-alpha.6"
31+
version = "5.13.1-alpha.7"
3132
description = "High resolution systems performance telemetry agent"
3233
edition = "2021"
3334
license.workspace = true
@@ -121,6 +122,7 @@ tower-http = { version = "0.6.8", features = [
121122
] }
122123
tower-livereload = "0.10.3"
123124
dashboard.workspace = true
125+
report-save.workspace = true
124126
systeminfo = { path = "crates/systeminfo" }
125127
walkdir.workspace = true
126128
tar = { version = "0.4.45", default-features = false }

crates/report-save/Cargo.toml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[package]
2+
name = "report-save"
3+
version = "0.1.0"
4+
edition = "2021"
5+
license.workspace = true
6+
repository.workspace = true
7+
homepage.workspace = true
8+
publish = false
9+
10+
[lib]
11+
path = "src/lib.rs"
12+
13+
[dependencies]
14+
arrow = "58.2.0"
15+
parquet = { version = "58.2.0", default-features = false, features = ["arrow", "simdutf8", "zstd"] }
16+
tar = { version = "0.4.45", default-features = false }
17+
serde.workspace = true
18+
serde_json.workspace = true
19+
metriken-query.workspace = true
20+
tracing = "0.1"

0 commit comments

Comments
 (0)