obs: NR browser agent → pro_plus_spa mode with route-level page views + custom attrs#49
Merged
Merged
Conversation
…custom attrs Builds on PR #37 (JS error reports) so the dashboard's NR browser agent emits the full APM surface, not just errors. Changes: 1. src/lib/newrelic-config.ts — extract the BrowserAgent init options into a pure function buildBrowserAgentOptions() so a unit test can pin the pro_plus_spa feature set. Tagged with NR_BROWSER_MODE = 'pro_plus_spa'. Explicit flags for soft_navigations, page_view_event, page_view_timing, metrics, jserrors, ajax, distributed_tracing — all defaults of the BrowserAgent loader, but stating them in source means a regression to lite shows up in review here, not in a grafana panel that suddenly goes flat. 2. src/main.tsx — now imports buildBrowserAgentOptions and passes the shaped options to `new BrowserAgent(...)`. Docstring lists what each enabled feature buys us (LCP/FID/CLS via page_view_timing, AJAX waterfalls via ajax, SPA pushState events via soft_navigations). 3. src/components/RouteTracker.tsx — null-rendering component that sits inside <BrowserRouter>. On every useLocation change it calls newrelic.setPageViewName(pathname) + setCustomAttribute(...) for tier (from ctx.me.team.tier), is_admin (ctx.me.is_platform_admin), and commit_id (VITE_COMMIT_ID). Falls back to "anonymous"/false when ctx.me hasn't resolved. Fail-open when window.newrelic is absent — telemetry must never crash the router. 4. src/App.tsx — mounts <RouteTracker /> just inside <BrowserRouter> and outside any Suspense boundary so a lazy-chunk fetch never unmounts it mid-navigation. Tests: - 7 RouteTracker.test.tsx cases (initial fire, route-change fire, tier/admin/commit_id stamping, anonymous fallback, missing-agent fail-open, upgrade-webhook tier flip, null render) - 8 newrelic-config.test.ts cases (mode tag + every feature flag) - ErrorBoundary.test.tsx (PR #37) still passes — no regression Run: vitest run → 397 passed | 3 skipped (was 382 | 3 before) Bundle size delta (npm run build): - main index.js: 632.33 kB → 634.40 kB (+2.07 kB raw) - gzipped: 174.21 kB → 174.76 kB (+0.55 kB) The agent itself was already in the bundle from PR #37 (full BrowserAgent loader, not lite). The +2 kB is RouteTracker + config builder; no loader swap. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Builds on PR #37 (JS error reports) so the dashboard's NR browser agent emits the full APM surface — page loads, SPA route changes, AJAX waterfalls, and Core Web Vitals — not just JS errors.
src/lib/newrelic-config.tswith aNR_BROWSER_MODE = 'pro_plus_spa'constant + explicitsoft_navigations,page_view_event,page_view_timing,metrics,jserrors,ajax, anddistributed_tracingenabled. Defaults already match in the agent, but stating them in source means a regression to lite shows up in code review, not in a grafana panel that goes flat.<RouteTracker />mounts inside<BrowserRouter>, watchesuseLocation, and on every change callsnewrelic.setPageViewName(pathname)+setCustomAttribute(...)fortier(fromctx.me.team.tier),is_admin(ctx.me.is_platform_admin), andcommit_id(VITE_COMMIT_ID). Falls back toanonymous/falsewhenctx.mehasn't resolved. Fail-open whenwindow.newrelicis absent.page_view_timingon, the agent emits LCP/FID/CLS/FCP/TTFB as PageViewTiming events with no extra wiring — verified the feature is in the BrowserAgent loader's instrumentation set.Bundle size
The agent itself was already in the bundle from PR #37 (full BrowserAgent loader, not lite). The +2 kB is the new
RouteTracker+ config builder; no loader swap.Test plan
npm test— 397 passed | 3 skipped (was 382 passed | 3 skipped before; +15 new tests)npm run buildsucceeds — main bundle + 116 prerendered HTML files/app/resources, then click to/app/billing, and confirm NR Page Views UI shows two distinct page-view rows (route-level granularity, not just/)SELECT count(*) FROM PageView FACET tier, is_admin, commit_id🤖 Generated with Claude Code