feat(performance-monitor-plugin): expand data coverage#264
Merged
V3RON merged 7 commits intoMay 14, 2026
Merged
Conversation
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
…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
approved these changes
May 14, 2026
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.
Closes #249.
Summary
Closes three gaps in
@rozenite/performance-monitor-plugin's coverage ofreact-native-performance:react-native-markentries — added a new React Native Marks tab. These are the native-runtime startup taxonomy (nativeLaunchStart,runJSBundleStart, …) emitted on the native side. The observer usesbuffered: trueso startup entries flushed before the user clicks Start Session still reach the panel.resourceentries — added a new Resources tab. Table shows Name / Type / Duration / Size. The DetailsSidebar renders the fullPerformanceResourceTimingbreakdown: sizes (transfer / encoded body / decoded body), all 12 timing phases, plus optionalserverTiming/workerTimingarrays.mark.detailpreservation — the runtime previously droppeddetailwhen 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 newsrc/react-native/serialize.ts. Tests pin every serializer's field-copy contract, with extra coverage onserializeResource— its 20-field copy is the place a typo would silently land anundefinedin the sidebar.The plugin had no test surface before this PR. Vitest is wired in via a single
testscript inpackage.json; the runner itself was already in the workspace root devDeps.Wire format is the existing per-type append pattern:
appendResourcesandappendReactNativeMarksjoinappendMeasures/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.detailregression, string-valued metric, exhaustive ResourceTiming fixture pinning every one of ~20 fields, explicit assertion that sub-phase timing fields are not clock-shifted, optionalinitiatorType/secureConnectionStartundefined 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):
setResourceLoggingEnabled(true)on mount, then afetch()on click — resource timing appears on the Resources tab.buffered: trueis load-bearing here).mark.detailregression: fire a mark with adetailpayload, click into it in the Marks tab — sidebar shows the payload.Playground change
The PR touches
apps/playground/src/app/screens/PerformanceMonitorScreen.tsxso the new tabs can be exercised without writing app code:setResourceLoggingEnabled(true)on mount.fetch('https://jsonplaceholder.typicode.com/posts/1')).ScrollViewso the now-taller screen is fully reachable.Out of scope
addEntryis not part of the public API, so manual emission would require hacks. Native startup entries cover the test case naturally.