WASM hosted reports: embed network.ndjson into the bundle so the Network tab appears
- Dominant language
- Kotlin
- Stars
- 310
- Forks
- 28
- Avg merge
- 7h 45m
- Merged PRs (30d)
- 8
Description
## Context
The Compose Multiplatform desktop app surfaces a "Network" tab in the bottom log panel for sessions that have a `/network.ndjson` artifact (captured by Playwright via `--capture-network`). The wiring lives in [`SessionLogsPanel`](https://github.com/block/trailblaze/blob/main/opensource/trailblaze-ui/src/commonMain/kotlin/xyz/block/trailblaze/ui/tabs/session/SessionLogsPanel.kt) + [`NetworkLogSource`](https://github.com/block/trailblaze/blob/main/opensource/trailblaze-ui/src/commonMain/kotlin/xyz/block/trailblaze/ui/tabs/session/NetworkLogSource.kt) and works on the JVM target — `loadNetworkLogs` reads the file from disk.
On the WASM target (hosted HTML reports generated by [`WasmReport`](https://github.com/block/trailblaze/blob/main/opensource/trailblaze-report/src/main/java/xyz/block/trailblaze/report/WasmReport.kt)) the `loadNetworkLogs` actual returns null today because the report bundle doesn't embed a `network_logs/` entry. The Network tab therefore never appears on hosted reports — it works only on the local desktop app.
The parallel `device_logs` codepath shows what the wiring should look like — see `WasmReport.kt` (the `device_logs:` block in `createCompressedDataBlock`) and the `index.html` dispatcher branch under `key.startsWith("device_logs/")`.
## Scope
Three small pieces, no new logic.
### 1. `WasmReport.kt` — accept and emit network logs
Add a `compressedNetworkLogs: Map = emptyMap()` parameter to `createCompressedDataBlock` and `writeCompressedDataBlock`, mirroring the existing `compressedDeviceLogs`. Emit a `network_logs: { … }` JSON block alongside the existing `device_logs` block in both functions.
### 2. `index.html` dispatcher — recognize the `network_logs/` key prefix
Add a branch alongside the existing device-logs lookup:
```js
else if (key.startsWith("network_logs/")) {
const sessionId = key.substring("network_logs/".length);
if (window.trailblaze_report_compressed.network_logs) {
compressedData = window.trailblaze_report_compressed.network_logs[sessionId];
}
}
```
### 3. Populate `compressedNetworkLogs` at the report-generation call site
Wherever `createCompressedDataBlock` / `writeCompressedDataBlock` is invoked with `compressedDeviceLogs` populated, do the same for `network.ndjson` files. Read `/network.ndjson` per session, JSON-encode the raw text the same way device logs are, and pass through the existing compression pipeline.
## Out of scope
- No changes to the JVM `loadNetworkLogs` actual — already works.
- No changes to the parser, panel, or schema.
- Body-file embedding (`bodies/req_.bin` and future `bodies/res_.bin`) is a separate decision — they're referenced from NDJSON via relative paths but aren't part of the NDJSON itself. Likely deferred until response-body capture lands.
## Why a separate issue
This is referenced from a TODO comment in `ActualsWasm.kt`'s `loadNetworkLogs` so a future maintainer hitting "no Network tab on the hosted report" can find it.
## Estimated diff
~30 LOC in `WasmReport.kt` + ~5 lines of JS in `index.html` + ~10 LOC in the call site that reads ndjson per session. Single PR.
Contributor guide
Research direction
Start by comparing the device_logs handling in WasmReport.kt and the index.html dispatcher, then trace the loadNetworkLogs TODO in ActualsWasm.kt to the report-generation call site. Add network log embedding and dispatch for each session, and verify that a hosted WASM report with network.ndjson displays its Network tab while the JVM path remains unchanged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, kotlin, wasm
- Domain
- frontend, web-dev
- Issue type
- Feature
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100