dsh-rerun
其他 活跃维护

dsh-rerun

drindr/dsh-rerun

支持将Rerun可视化组件无缝集成到DSH开发流程,无需额外复杂配置即可调用Rerun的多维数据可视化、运行调试追踪能力,简化DSH环境下数据流、模型执行过程的观测与排查工作。

0
Stars 标星
0
Forks 分支
0
Watchers 关注
0
Open Issues
TypeScript
主要语言
None
开源协议
27 KB
仓库大小
1 个月前
最后推送
一键安装扩展 / 插件指令
dsh plugin --profile web add github:drindr/dsh-rerun
git clone https://github.com/drindr/dsh-rerun.git
git clone git@github.com:drindr/dsh-rerun.git
README.md main

dsh-rerun

Embed the Rerun web viewer in the dsh web GUI: browse .rrd
recordings from the workspace root and connect to live rerun --serve streams —
all inside the harness, fully offline.

What it does

  • A Rerun button in the sidebar footer opens a full-window overlay.
  • Recordings mode lists .rrd / .rrd.zst files under the workspace root
    (env override: DSH_RERUN_RECORDINGS_DIR) and renders the selected one.
  • Live mode connects the viewer to a running Rerun server, e.g. started
    with rerun --serve-web (note: the flag is --serve-web, not --serve).
    The default URL is shown/edited in the namespaced alias form
    rerun+<page-scheme>://<page-host>/dsh-rerun/live — the same origin as
    the GUI. Because it is same-origin there is no CORS and no mixed content,
    so Live works on any GUI access scheme — http://127.0.0.1:3080,
    http://<host>, or https://<host>. How the 0.34.1 viewer actually
    connects (verified via Network capture):
    • the URL is only a parse token: the viewer accepts live URLs whose
      path is exactly /proxy (host/scheme free; any other path — including
      the /dsh-rerun/live alias — fails as "Failed to parse URL"),
    • the real connection is grpc-web to
      <origin>/rerun.sdk_comms.v1alpha1.MessageProxyService/<Method>
      (OPTIONS preflight + POST streaming) — /proxy itself is never fetched.
      The panel therefore speaks the alias and maps it to the canonical
      /proxy path before the viewer sees it (canonicalLiveUrl in
      src/client/store.ts); typing the canonical form directly also works.
      The host half registers a passthrough to the rerun server
      (http://127.0.0.1:9876, env override: DSH_RERUN_LIVE_ORIGIN) at both
      /rerun.sdk_comms.v1alpha1.MessageProxyService/* (the actual live stream)
      and /proxy / /dsh-rerun/live/* (parse-token safety + legacy URLs).
      On an https page the one remaining prerequisite is that the browser
      trusts the GUI's TLS certificate — fetch has no "proceed anyway" path
      (page loads can be bypassed, fetches cannot). Until it is trusted the
      panel shows a 证书不受信任 hint. One-time trust for Caddy's internal CA:
      sudo cp ~/.local/share/caddy/pki/authorities/local/root.crt /usr/local/share/ca-certificates/
      sudo update-ca-certificates

      (or import root.crt into the browser's CA store), then restart the
      browser.

How it stays light (lazy load + local cache)

The viewer is a 48 MB WASM binary. This plugin never ships it in the client
bundle and never hits a CDN:

  • The host half serves the viewer straight out of the installed
    @rerun-io/web-viewer npm package
    (a plain dependency → package-manager
    cache = local disk cache). See src/index.tsfindViewerRoot.
  • The client half only carries an 8 KB panel UI. The viewer iframe — and
    therefore every viewer byte — is fetched only when the overlay opens.
  • Versioned asset URLs (/dsh-rerun/viewer/0.34.1/…) are served with
    Cache-Control: immutable, so after the one-time 48 MB fetch every re-open
    is instant from the browser cache. The wasm response also sets
    rerun-final-length so the viewer shows a download progress bar.

Version alignment

@rerun-io/web-viewer@0.34.1 matches the local rerun-cli 0.34.1. Keep the
dependency in lockstep with the Rerun SDK/CLI that produces your .rrd files
(the viewer reads files from the previous minor version and speaks the matching
gRPC protocol for live streaming).

Live operations & troubleshooting

Quick start for a live demo with data streaming in real time:

rerun --serve-web                  # gRPC server on :9876 (+ web viewer on :9090)
python feed-live.py                # any rerun SDK: connect_grpc + rr.log in a loop
                                   # or: rerun --serve-web demo-dna.rrd  (pre-loaded file)

rerun-sdk 0.36 API changes vs older docs: connectconnect_grpc,
set_time_sequenceset_time(..., sequence=), ScalarScalars.

Stream connection hygiene — the /proxy passthrough is a long-lived
stream, and the viewer drops it whenever the overlay closes. The host half
destroys the upstream connection on client close
(res.on('close') → proxyReq.destroy()); without that, every closed viewer
leaks one idle TCP connection into the rerun server. Symptoms of the leak:
the viewer renders an empty light screen and the rerun server log fills with
re_quota_channel: Sender has been blocked for over 5 seconds…. Diagnosis:
ss -tn | grep 9876 shows a client socket with a multi-MB Send-Q/Recv-Q
that never drains. Leaked sockets live in the dsh web process, so they
survive rerun server restarts — clearing them requires a dsh web restart
(which also loads any rebuilt lib/index.js).

Note that the rerun server and the data feeder are external processes, not
owned by the plugin — if Live shows an empty screen, check they are still up
(ss -tln | grep 9876) before anything else.

Host routes

Route Purpose
GET /dsh-rerun/viewer/<version>/ iframe entry page
GET /dsh-rerun/viewer/<version>/index.js, re_viewer.js, re_viewer_bg.wasm viewer assets (immutable)
GET /dsh-rerun/recordings/<rel>.rrd workspace recording (traversal-safe)
GET /dsh-rerun/api/recordings { recordings[], viewerVersion }
GET /dsh-rerun/api/health { ok, viewerVersion, recordingsRoot }

Routes mount on the existing web server (ctx.webServer.register), so there is
no second port and no CORS. Same-origin iframe → no CORS shenanigans.

Build

pnpm install --store-dir <writable-store> --cache-dir <writable-cache>  # sandbox note below
node build.mjs       # -> lib/index.js (host ESM) + lib/client.js (browser CJS)
node watch.mjs       # dev watcher (optional)

Sandbox note: pnpm's default store sqlite cannot open under the harness file
sandbox; point --store-dir/--cache-dir at a writable location (the repo
uses .pnpm-store / .pnpm-cache).

Wiring into a profile

  1. ln -s <repo>/dsh-rerun $DSH_HOME/plugins/dsh-rerun
  2. Add "dsh-rerun": "link:../../plugins/dsh-rerun" to the profile's
    package.json dependencies and pnpm install.
  3. Add a loader entry to the profile's cordis.patch.yml:
    - insert:
       - id: rerun
         name: dsh-rerun
  4. Restart dsh web — new plugins are loader entries fixed at boot.

Dev iteration after restart

  • lib/client.js changes hot-swap without a page refresh (dsh-client-hmr polls
    the bundle).
  • lib/index.js changes need an hmr watch row covering this package's real
    path in the profile's cordis.patch.yml, otherwise a dsh web restart.