Skip to content

perf(frontend): load the trace drawer on demand in /m - #8050

Merged
mmabrouk merged 3 commits into
release/v0.128.5from
perf/m-trace-drawer-lazy
Nov 4, 2026
Merged

mmabrouk merged 3 commits into
release/v0.128.5from
perf/m-trace-drawer-lazy

Conversation

@mmabrouk

@mmabrouk mmabrouk commented Nov 3, 2026

Copy link
Copy Markdown
Member

Do not merge into v0.128.4. This goes into the next release.

Context

Every page in /m loads 263 KB gzip less JavaScript on first load. The app shell went from 1,241,531 to 972,022 bytes gzip, and the shell is the code every page loads. Before this change, the shell carried the trace drawer's body and its drill-in panel (the JSON tree with its editor), although most page visits never open a trace. The change is not behind a switch, so every user gets it.

Changes

The drawer body and the drill-in panel now load on demand, with next/dynamic.

  • TraceDrawer (in @agenta/observability-ui) loads TraceDrawerContent on the first open. The drawer panel still opens at once, and it shows a skeleton until the body arrives. /w already loads the whole drawer with next/dynamic, so its first load does not change.
  • registerTraceDrawerSlots registers the drill-in panel (TraceSpanPanel) as a dynamic component. The slot registrations stay in the shell, so the add-to-queue picker and the panels reach the drawer the same way as before, and also reach the annotation queue session, which renders the drawer's overview outside the drawer.
  • If either chunk fails to load, the skeleton changes to a load error with a "Try again" button, so the user does not wait on a skeleton that never ends.

There is one behaviour change. The first trace open in a page waits for one chunk. In live QA on a dev stack the skeleton showed for about 215 ms, and later opens in the same page show no skeleton.

The change also fixes a bug that production /m has today. The trace drawer showed annotation authors as raw user ids, because /m never gave the drawer a member list. While the drawer is open, /m now loads the workspace members (the same query that Settings uses) and binds them, so the drawer shows the author's user name. The member query also loads on demand, so the shell does not carry it.

First load, gzip, built on the same machine (release head cfbe8af2d1 against this branch):

Page Before After Change
App shell (every page) 1,241,531 972,022 -263.2 KB
Observability 1,484,422 1,240,244 -238.5 KB
Apps 1,416,515 1,151,458 -258.8 KB
Sessions 1,851,822 1,839,662 -11.9 KB
One session (agent chat) 1,794,472 1,777,253 -16.8 KB
Annotation queue session 1,418,898 1,412,184 -6.6 KB

The session and queue pages drop less, because they already load the JSON tree for their own content. scripts/speed/budget.json now holds the new sizes, so a later change cannot add the weight back without failing speed:check. It also adds the routes that had no budget yet.

Tests

  • New traceDrawerLazy.render.test.tsx. It opens the drawer from a chat turn's "View trace" action and from a traces list row. The first open shows the loading panel and then the drawer, and the shell's add-to-queue slot renders inside the lazily loaded header. The author names resolve with no binding in the test, and the shell import does not load the drill-in panel.
  • New tests for both loading states: a failed load shows the error and calls retry, with no technical text.
  • /m types, /w types (@agenta/oss), @agenta/observability-ui types and tests, speed:check, and the antd route check (playground, observability, session, annotation queue session) pass. Full /m tests pass except four that fail on the release head too (testsetCommit, membersTabRoleChange).
  • A ?trace= link does not open the drawer on page load. The release branch does not do it either, because nothing in /m reads that parameter to open the drawer, so this PR leaves it as it is.

What to QA

  • Open Observability, Traces, and click a row on a fresh page load. The drawer slides in once and shows a short skeleton, then the trace. Close it and open another row. There is no skeleton.
  • Annotate a trace, reload the page, open that trace and hover the score. The author shows as a user name, not an id.
  • Open a trace from an annotation queue session ("Open trace"). The drawer opens, and the "Add annotation queue" button in its header works.
  • Regression: open a trace at phone width (390 px). The stacked layout and the Inputs and Outputs panels show as before.

@mmabrouk

mmabrouk commented Nov 3, 2026

Copy link
Copy Markdown
Member Author

🤖 The AI agent says: Live QA as a real user passed, with no bug found. I ran it on a fresh OSS dev stack built from this branch, in headless Chromium at 1440 px and 390 px, with SDK-traced Mistral runs and one annotation. The recording (checks 1, 5, 6 and 8 at 1440 px) is posted separately, because gh cannot attach a video.

Check Result What I saw
Traces table, first open on a fresh page pass The panel opened once, with no close and reopen and no second slide. The "Loading trace" skeleton appeared together with the panel and left about 215 ms later. With 1.5 s of added network latency, the skeleton was still on screen at 700 ms, and then the body arrived.
Second open pass No skeleton.
Annotation queue session, "Open trace" pass The skeleton showed on the first open only, and the queue page kept its state.
Author names pass On a fresh page load straight into Traces, the score popover in the drawer showed the user name, not the raw id.
State pass Switching spans, closing and reopening left no stuck skeleton. The traces table kept its scroll position and search.
Add to annotation queue button pass It renders in the drawer header and opens the shadcn picker. Picking a queue adds the trace.
Console pass Only the known noise. No chunk load errors, and no API errors during drawer steps.
Sessions tab not applicable The tab has no trace entry point on this branch.
Agent chat "View trace" not tested live The agent run could not reach the API on this stack, because I bound the stack port to localhost on purpose. A unit test covers this entry point. It uses the same open action as the table.
?trace= and ?span= links loaded directly no change No drawer opens. The release branch behaves the same, because nothing in /m reads these parameters to open the drawer.

@mmabrouk

mmabrouk commented Nov 3, 2026

Copy link
Copy Markdown
Member Author

🤖 The AI agent says:

Review loop result for head f3599a0fa3 (base cfbe8af2d1), 2 rounds, Codex. The later head f12dd6d785 only changes budget.json.

Lens Final rating
Correctness Low
Simplify Low

Fixed: If the drawer body or the drill-in panel chunk failed to load, the skeleton stayed forever. Both loading states now show a load error with a retry (f3599a0).
Left on purpose: The reviewer worried that members arriving after the annotations would leave raw ids. A store test showed the annotation query refetches when the member list changes, and the name resolves. Live QA on a fresh page load showed the name too.

@coderabbitai

coderabbitai Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Important

Review skipped

Review was skipped as selected files did not have any reviewable changes.

Run configuration
Commits

Reviewing files that changed from the base of the PR and between d3e0e83 and d3e0e83.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Trigger review
Summary

Summary by CodeRabbit

  • Performance

    • Updated initial-load size budgets for existing routes and added budgets for annotations, archived apps, endpoints, evaluators, prompts, testsets, and variants.
  • User Experience

    • Trace drawer content now loads on demand, with loading placeholders and a retry option if loading fails.

The trace drawer content and mobile drill-in panel now load on demand and show loading or retry states. The mobile app binds workspace members while the drawer is open. The first-load gzip byte budgets are updated for the shell and routes.

Changes: Trace Drawer Loading

Layer / File(s) Summary
Load shared drawer content
web/packages/agenta-observability-ui/src/traceDrawer/TraceDrawer.tsx, web/packages/agenta-observability-ui/src/traceDrawer/TraceDrawerContentSkeleton.tsx, web/packages/agenta-observability-ui/tests/unit/traceDrawerContentSkeleton.render.test.tsx
TraceDrawerContent loads dynamically with a skeleton fallback. Tests cover loading and retry states.
Load mobile drawer panels
web/mobile/src/features/app/GlobalDrawers.tsx, web/mobile/src/features/observability/TraceDrawerMembers.tsx, web/mobile/src/features/observability/useBindWorkspaceMembers.ts, web/mobile/src/features/observability/registerTraceDrawerSlots.ts, web/mobile/src/features/observability/TraceSpanPanel.tsx, web/mobile/src/features/observability/states/TraceSpanPanelSkeleton.tsx, web/mobile/tests/unit/traceDrawerLazy.render.test.tsx, web/mobile/tests/unit/traceSpanPanelSkeleton.render.test.tsx, web/mobile/tests/unit/traceDrawerTabs.render.test.tsx, web/mobile/tests/unit/addToQueueSlotRegistration.test.tsx
GlobalDrawers mounts the workspace-member binding component only while the drawer is open. The drill-in panel loads dynamically with a skeleton fallback. Tests cover the loading flow, retry behavior, and rendering after load.

Mobile Byte Budgets

Layer / File(s) Summary
Update route byte budgets
web/mobile/scripts/speed/budget.json
The shell and existing route byte budgets are updated. Budgets are added for annotations, archived apps, endpoints, evaluators, prompts, testsets, and variants.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: Low · previous review f12dd

The drawer now loads on demand and the reported bundle reduction is a real benefit. Remaining issues are small and recoverable: an annotation author may briefly appear as an ID, a chunk-load failure after a deployment may need a page reload, and one test is order-dependent. These can be fixed before or shortly after merge.

Pre-merge checks: Passed 5
Check name Status Explanation
Title check Passed The title "perf(frontend): load the trace drawer on demand in /m" matches the main change. The PR defers the trace drawer body and drill-in panel (TraceSpanPanel) in /m with next/dynamic, which the ra…
Description check Passed The description explains the change. It covers the lazy loading of the drawer body and drill-in panel with next/dynamic, the skeleton and retry states, the workspace member binding that fixes raw user…
Docstring Coverage Passed No eligible functions found in the changed files. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title "perf(frontend): load the trace drawer on demand in /m" matches the main change. The PR defers the trace drawer body and drill-in panel (TraceSpanPanel) in /m with next/dynamic, which the raw summary and objectives confirm. The title is specific and concise, and it uses a conventional commit prefix.

Full details: Description check

Explanation

The description explains the change. It covers the lazy loading of the drawer body and drill-in panel with next/dynamic, the skeleton and retry states, the workspace member binding that fixes raw user ids in annotation authors, the budget.json update, and the tests. The figures match the objectives. It also notes that the PR should not merge into v0.128.4.

Full details: Docstring Coverage

Explanation

No eligible functions found in the changed files. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 0 functions across 13 files. (1 skipped: 1 unsupported.)

Finishing Touches
Generate docstrings
  • Commit to this branch
  • Create a new PR
Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

Share

CodeRabbit Verify

  • Run CodeRabbit Verify to test the changes in this pull request.
Recent review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between cfbe8af and f12dd6d.

Files selected for processing: 14
  • web/mobile/scripts/speed/budget.json
  • web/mobile/src/features/app/GlobalDrawers.tsx
  • web/mobile/src/features/observability/TraceDrawerMembers.tsx
  • web/mobile/src/features/observability/TraceSpanPanel.tsx
  • web/mobile/src/features/observability/registerTraceDrawerSlots.ts
  • web/mobile/src/features/observability/states/TraceSpanPanelSkeleton.tsx
  • web/mobile/src/features/observability/useBindWorkspaceMembers.ts
  • web/mobile/tests/unit/addToQueueSlotRegistration.test.tsx
  • web/mobile/tests/unit/traceDrawerLazy.render.test.tsx
  • web/mobile/tests/unit/traceDrawerTabs.render.test.tsx
  • web/mobile/tests/unit/traceSpanPanelSkeleton.render.test.tsx
  • web/packages/agenta-observability-ui/src/traceDrawer/TraceDrawer.tsx
  • web/packages/agenta-observability-ui/src/traceDrawer/TraceDrawerContentSkeleton.tsx
  • web/packages/agenta-observability-ui/tests/unit/traceDrawerContentSkeleton.render.test.tsx

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 2 remain after this review.

@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Website preview

Preview URL: https://pr-8050-agenta-website-preview.mahmoud-637.workers.dev

Built from d3e0e83a46c55d2e6ad9d7a2a82ce8a510011402. This comment updates in place on every push.

@mmabrouk

mmabrouk commented Nov 3, 2026

Copy link
Copy Markdown
Member Author

🤖 The AI agent says: /w also uses the package TraceDrawer, so the lazy drawer body reaches /w users too. I checked /w live on head f12dd6d785 at 1440 px, on a fresh OSS dev stack, and it passed with no bug.

Check Result What I saw
Traces table, first open on a fresh page pass The panel opened once and was never removed during the open. The "Loading trace" skeleton appeared with the panel and left 30 to 150 ms later.
Second open pass No skeleton and no flash.
Drawer tabs pass Overview, Raw Data, Linked Spans and Annotations all render content.
Session drawer, "Open trace" pass The trace opened once, and the skeleton showed for 69 ms. All four tabs render, and the annotated trace shows its annotation. The session drawer stays open after the trace closes, and a reopen shows no skeleton.
Evaluation run focus drawer not tested It needs an app, a test set and an evaluator, and the runner could not reach the API on this stack, because the stack port was bound to localhost.
Console pass Nothing new from the drawer and no chunk load errors. A Failed to fetch JWT message also appears on a page load with no drawer open, so the drawer does not cause it.

@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Railway Preview Environment

Item Value
Status stopped
Commit d3e0e83a46c55d2e6ad9d7a2a82ce8a510011402
Manual expiry (UTC) Not granted
CI deadline (UTC) Not granted
Workflow https://github.com/Agenta-AI/agenta/actions/runs/41684932893

Preview use finished or expired. Environment absence verified; retained storage requires separate provider accounting.

Post /preview as a new comment to request a one-hour preview. Repeating it while active does not extend the hour.
Preview data is disposable. Expiry is enforced by the next successful cleanup sweep, not an exact timer.
Environment deletion stops its compute. Provider-retained storage and permanent services may still be billed.

Agenta Product Agent added 3 commits November 3, 2026 17:48
…and in /m

The app shell carried the trace drawer's body and its drill-in panel
(the JSON tree and editor) on every page. Both now load on the first
trace open. The drawer panel still opens at once and shows a skeleton
until the body arrives.

While the drawer is open, /m loads the workspace members, so the
drawer names annotation authors instead of showing raw user ids.
The drawer body and the drill-in panel load on demand. If their chunk
failed, the skeleton stayed on screen with no way out. Both loading
states now show a load error with a Try again button.
The app shell is 263 KB gzip smaller now that the trace drawer body and
drill-in panel load on demand. The budget records the new sizes so a
later change cannot quietly add the weight back. It also adds the routes
that had no budget yet.
@mmabrouk
mmabrouk force-pushed the perf/m-trace-drawer-lazy branch from f12dd6d to d3e0e83 Compare November 3, 2026 17:30
@mmabrouk
mmabrouk changed the base branch from release/v0.128.4 to release/v0.128.5 November 3, 2026 18:58
@mmabrouk
mmabrouk merged commit 5868794 into release/v0.128.5 Nov 4, 2026
79 of 88 checks passed
@mmabrouk mmabrouk added the lgtm This PR has been approved by a maintainer label Nov 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lgtm This PR has been approved by a maintainer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant