Skip to content

feat(performance-monitor-plugin): expand data coverage#264

Merged
V3RON merged 7 commits into
callstackincubator:mainfrom
burczu:feat/performance-monitor-plugin-expand-data-coverage
May 14, 2026
Merged

feat(performance-monitor-plugin): expand data coverage#264
V3RON merged 7 commits into
callstackincubator:mainfrom
burczu:feat/performance-monitor-plugin-expand-data-coverage

Conversation

@burczu
Copy link
Copy Markdown
Contributor

@burczu burczu commented May 12, 2026

Closes #249.

Summary

Closes three gaps in @rozenite/performance-monitor-plugin's coverage of react-native-performance:

  • react-native-mark entries — added a new React Native Marks tab. These are the native-runtime startup taxonomy (nativeLaunchStart, runJSBundleStart, …) emitted on the native side. The observer uses buffered: true so startup entries flushed before the user clicks Start Session still reach the panel.
  • resource entries — added a new Resources tab. Table shows Name / Type / Duration / Size. The DetailsSidebar renders the full PerformanceResourceTiming breakdown: sizes (transfer / encoded body / decoded body), all 12 timing phases, plus optional serverTiming / workerTiming arrays.
  • mark.detail preservation — the runtime previously dropped detail when serializing marks (while the UI already expected it). The serializer now includes it end-to-end; the Mark Details sidebar now renders the payload.

Architecture

The PR extracts each observer's inline serializer into a named pure function (serializeMark, serializeMeasure, serializeMetric, serializeReactNativeMark, serializeResource) in a new src/react-native/serialize.ts. Tests pin every serializer's field-copy contract, with extra coverage on serializeResource — its 20-field copy is the place a typo would silently land an undefined in the sidebar.

The plugin had no test surface before this PR. Vitest is wired in via a single test script in package.json; the runner itself was already in the workspace root devDeps.

Wire format is the existing per-type append pattern: appendResources and appendReactNativeMarks join appendMeasures / appendMarks / setMetrics. No new dependencies on the plugin.

Test plan

Automated (15 tests, up from 0):

  • serialize.test.ts (15 tests): mark / measure / metric / react-native-mark / resource — field copy, mark.detail regression, string-valued metric, exhaustive ResourceTiming fixture pinning every one of ~20 fields, explicit assertion that sub-phase timing fields are not clock-shifted, optional initiatorType / secureConnectionStart undefined branches.
  • pnpm --filter @rozenite/performance-monitor-plugin test — 10/10 passing.
  • pnpm --filter @rozenite/performance-monitor-plugin typecheck — clean.
  • pnpm --filter @rozenite/performance-monitor-plugin lint — 0 warnings.

Manual (playground, performance-monitor screen):

  • Fire Network Request button (new): calls setResourceLoggingEnabled(true) on mount, then a fetch() on click — resource timing appears on the Resources tab.
  • Complex Performance Scenario (existing button, enhanced): now also fires a fetch in parallel with marks/measures so the umbrella demo exercises every tab.
  • Start Session on a fresh app launch — React Native Marks tab populates with native startup entries automatically (buffered: true is load-bearing here).
  • mark.detail regression: fire a mark with a detail payload, click into it in the Marks tab — sidebar shows the payload.
  • Export Data modal includes two new cards (React Native Marks, Resources) with their counts. Toggling them in/out of the export round-trips through the JSON.

Playground change

The PR touches apps/playground/src/app/screens/PerformanceMonitorScreen.tsx so the new tabs can be exercised without writing app code:

  • setResourceLoggingEnabled(true) on mount.
  • New "Fire Network Request" button (fetch('https://jsonplaceholder.typicode.com/posts/1')).
  • "Complex Performance Scenario" runs a fetch in parallel.
  • Screen content wrapped in a ScrollView so the now-taller screen is fully reachable.
  • Instructions note that React Native Marks come from the native runtime and need no button.

Out of scope

  • No version field in the export schema. The change is purely additive (new fields/counts) and existing consumers ignore unknown fields. Versioning is a separate concern best introduced when an actual breaking change is on the table.
  • No UI behavior tests (RTL/jsdom). The plugin has none today; standing the infrastructure up for this feature alone would expand scope. The serializer extraction means the data-shape contracts are already pinned by unit tests.
  • No new buttons to manually emit react-native-marks from JS — the lib's addEntry is not part of the public API, so manual emission would require hacks. Native startup entries cover the test case naturally.

burczu added 6 commits May 12, 2026 11:43
Refactors the three inline observer-callback map lambdas in
performance-monitor.ts into named pure functions (serializeMark,
serializeMeasure, serializeMetric) living in serialize.ts. Each takes
a PerformanceMark/Measure/Metric plus the session origin and returns
the wire-shaped serialized form.

As part of the serializer contract, mark.detail is now included in
the wire payload (it was being dropped in the old inline mapper while
the MarkDetails UI already expected it).

Wires vitest into the plugin (no test surface before) and adds
focused per-serializer tests, including a regression for the
mark.detail fix.

Refs callstackincubator#249
…types + tests

Extends the shared type surface to cover the two entry types missing
from the panel today:

- SerializedPerformanceResource carries every PerformanceResourceTiming
  field (14 timing phases plus body sizes, serverTiming, workerTiming,
  and optional initiatorType / secureConnectionStart).
- SerializedPerformanceReactNativeMark is the react-native-mark
  equivalent of a mark, with detail preserved.

Both are added to the SerializedPerformanceEntry union and to
PerformanceMonitorEventMap as appendResources and
appendReactNativeMarks.

Adds matching type-narrowing asserts and serializeResource /
serializeReactNativeMark in serialize.ts. Only the shared startTime is
translated by toDateTimestamp; sub-phase timing fields pass through
unchanged because they are relative timings the UI does not
clock-shift today.

Tests pin every resource field down (so any future typo in field
names trips the test) and cover the react-native-mark detail branch.

Refs callstackincubator#249
…ark entries

Adds two new PerformanceObserver subscriptions in the runtime, each
with buffered:true so entries emitted before the user clicks Start
Session (notably native startup react-native-marks) are still flushed
to the panel.

Each observer narrows entries with the new asserts, runs them through
the matching serializer, and sends the serialized payload over the
bridge via the new appendReactNativeMarks / appendResources events.

UI changes (tabs, tables, details, export) follow in Phase 4.

Refs callstackincubator#249
Adds React Native Marks and Resources to the panel:

- App.tsx: session state grows two new arrays; two new client.onMessage
  subscriptions (appendReactNativeMarks, appendResources) append with
  startTime clock-shifted; two new Tabs.Trigger + Tabs.Content panels.
- ResourcesTable: 4 columns (Name, Type/initiatorType, Duration, Size
  via formatBytes(transferSize)).
- ReactNativeMarksTable: mirrors MarksTable shape.
- ResourceDetails: full breakdown with sizes section, 2-column grid of
  the 12 timing-phase fields (relative timings, not clock-shifted),
  optional serverTiming / workerTiming sections.
- ReactNativeMarkDetails: mirrors MarkDetails shape.
- DetailsSidebar dispatch extended for the two new entryType values.
- utils.ts: formatBytes helper.

Also updates apps/playground/src/app/screens/PerformanceMonitorScreen
so the new tabs can be exercised:

- setResourceLoggingEnabled(true) on mount so any fetch from this
  screen logs a PerformanceResourceTiming entry.
- New "Fire Network Request" button.
- "Complex Performance Scenario" now fires a fetch in parallel with
  the marks/measures so the umbrella demo exercises every tab.
- Content wrapped in ScrollView so the now-taller screen is reachable
  on smaller devices.
- Instructions note that React Native Marks are emitted by the native
  runtime at startup and appear automatically when a session starts.

Refs callstackincubator#249
Extends ExportModal so React Native Marks and Resources can be
included in the exported JSON:

- Props grow two arrays; ExportOptions grows two boolean flags.
- sessionInfo gains totalReactNativeMarks and totalResources counts.
- Conditional reactNativeMarks / resources arrays mirror the existing
  measures / metrics / marks pattern.
- Two new DataTypeCard rows in the modal body, ordered to match the
  panel's tab order.
- ALL_OPTIONS_ON / ALL_OPTIONS_OFF constants centralise the default
  shape so future entry types only need one place to extend.
- "Export Data" disabled condition switched to Object.values(...).every,
  so it automatically picks up future flags.

Schema change is purely additive — no version field per the design
discussion in the issue.

Refs callstackincubator#249
Bumps @rozenite/performance-monitor-plugin as minor for the new
resource and react-native-mark coverage plus the preserved mark
detail.

Refs callstackincubator#249
@burczu burczu marked this pull request as ready for review May 12, 2026 12:33
…react-native marks

Pair *Start/*End react-native-mark entries (nativeLaunch, runJSBundle,
initialMount, ...) into UI-only derived measures so the Measures tab
shows startup-phase durations directly instead of forcing users to
subtract two marks by hand. Derived rows are marked with an "RN" badge
in the table and a short note in the details sidebar. Export is
unaffected — exports continue to emit raw session.measures only.
@V3RON V3RON merged commit 4c58099 into callstackincubator:main May 14, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Expand performance monitor plugin data coverage

2 participants