wu-sheng opened a new pull request, #48: URL: https://github.com/apache/skywalking-horizon-ui/pull/48
## What Adds a **Browser Logs** tab to the BROWSER layer and **source-map de-obfuscation** for the JS errors the browser agent reports — the long-standing ask in [apache/skywalking#6784](https://github.com/apache/skywalking/issues/6784). The tab lists `queryBrowserErrorLogs` rows (message, category, page, app version, time, minified `line:col`), filterable by category, app version, page path, and time window. Expanding a row shows the **raw stack** next to a **de-obfuscated** view: pick a loaded `.map` and the BFF resolves each frame back to the original file / line / column / symbol name plus a source snippet. ## Why it's UI-only (no SWIP) Per the discussion on #6784, this is implemented entirely in Horizon UI — **no OAP, agent, or query-protocol change**. It reads the existing `queryBrowserErrorLogs` GraphQL query and hosts source maps in the **BFF process memory** as a deliberate, no-backend-change pilot: - **Uploaded `.map` files are temporary** — held in BFF memory only, evicted least-recently-used past a configurable budget, and lost on restart. The UI surfaces this explicitly (a "temporary" badge, a usage bar, and a warning). - **Durable provisioning is a static mount** — drop `.map` files into the server's source-map directory (`HORIZON_SOURCEMAPS_DIR`, `/app/sourcemaps` in the image); those reload automatically and can't be deleted from the UI. Resolution runs server-side in Node (`@jridgewell/trace-mapping`, pure-JS/sync) so maps — and their `sourcesContent` — never ship to the browser. ## Config New `sourceMaps` block in `horizon.yaml` (all hot-reloadable except the boot mount and *raising* the per-file upload cap): ```yaml sourceMaps: enabled: true maxFileBytes: 67108864 # 64 MiB — reject a single .map larger than this maxTotalBytes: 536870912 # 512 MiB — resident in-memory upload budget (LRU past it) maxFileCount: 128 # per-set cap (uploaded set / mounted set each) bootMountDir: /app/sourcemaps ``` RBAC: uploading/deleting maps needs the new **`source-map:write`** verb; listing errors, listing maps, and resolving ride on **`browser-errors:read`**. Both are granted to the default roles in the example/demo configs. ## Scope of the change - **BFF** — `POST /api/layer/:key/browser-errors` (mirrors the logs route; SECOND step, OAP-server-local time, per-page time range, DESC re-sort for BanyanDB segment order); source-map admin routes (multipart upload / list / delete / resolve); a process-global `SourceMapStore` (budget accounting, LRU eviction, lazy mount reads, bounded parsed cache). - **UI** — `layer/browser-errors/` (view + composable + embedded source-map manager), api façade, tab wiring across sidebar / router / caps / topbar opt-out. The view matches the general Logs tab vocabulary (histogram, category legend, dense stream); the tab owns its own time range and pauses auto-refresh. - **i18n** — all operator strings wrapped in `t()`; 40 new keys added to English and translated into the 7 other catalogs (de/es/fr/ja/ko/pt/zh-CN), placeholders + technical tokens preserved. - **Docs** — operator page `docs/operate/browser-source-maps.md` (+ menu entry), plus `horizon.yaml`, container-image, and RBAC doc updates. - **Bundled BROWSER layer template** — gains the `browserErrors` widget; the generic `logs` tab is disabled for BROWSER (browser errors replace it there). ## Validation - **Live OAP** (local OAP + version-locked BanyanDB, real browser-error data): tab appears, `queryBrowserErrorLogs` returns rows; verified the SECOND-precision rolling **and** custom epoch-ms time ranges agree, results are strictly newest-first, a statically-mounted `.map` loads and is non-deletable, and an uploaded `.map` resolves a real minified stack to the correct original positions + snippet. - **Unit tests** — 194 pass (109 BFF + 85 UI), including the source-map pipeline (esbuild-generated real `.map` → original positions), budget/eviction/hot-reload invariants, and the multipart HTTP surface (200 / 413 / 403). - `type-check`, `lint`, and `license-eye` header check all clean. ## Out of scope OAP/agent-side changes (Debug-ID matching, ingest-time resolution, OAP-side map storage) — the proper long-term home, deferred. The general service **Logs** tab is untouched. -- 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]
