|
1 | 1 | import * as Sentry from '@sentry/react-native'; |
2 | 2 | import {Platform} from 'react-native'; |
3 | | -import performance, {PerformanceObserver} from 'react-native-performance'; |
| 3 | +import {PerformanceObserver} from 'react-native-performance'; |
4 | 4 | import {isDevelopment} from '@libs/Environment/Environment'; |
5 | | -import {endSpan, getSpan, startSpan} from '@libs/telemetry/activeSpans'; |
| 5 | +import {endSpan, startSpan} from '@libs/telemetry/activeSpans'; |
6 | 6 | import {breadcrumbsIntegration, browserProfilingIntegration, consoleIntegration, navigationIntegration, tracingIntegration} from '@libs/telemetry/integrations'; |
7 | 7 | import processBeforeSendTransactions from '@libs/telemetry/middlewares'; |
8 | 8 | import CONFIG from '@src/CONFIG'; |
@@ -41,33 +41,28 @@ export default function (): void { |
41 | 41 | op: CONST.TELEMETRY.SPAN_APP_STARTUP, |
42 | 42 | }); |
43 | 43 |
|
44 | | - const runJsBundleStartEntries = performance.getEntriesByName('runJsBundleStart'); |
45 | | - if (runJsBundleStartEntries.length > 0) { |
46 | | - const jsParseStartSecs = (runJsBundleStartEntries.at(0)?.startTime ?? 0) / 1000; |
47 | | - |
48 | | - startSpan(CONST.TELEMETRY.SPAN_JS_PARSE_TIME, { |
49 | | - name: CONST.TELEMETRY.SPAN_JS_PARSE_TIME, |
50 | | - op: CONST.TELEMETRY.SPAN_JS_PARSE_TIME, |
51 | | - startTime: jsParseStartSecs, |
52 | | - parentSpan: getSpan(CONST.TELEMETRY.SPAN_APP_STARTUP), |
53 | | - }); |
54 | | - |
55 | | - const finishJsParseSpan = (endTimeSecs: number) => { |
56 | | - endSpan(CONST.TELEMETRY.SPAN_JS_PARSE_TIME, endTimeSecs); |
57 | | - }; |
58 | | - |
59 | | - const runJsBundleEndEntries = performance.getEntriesByName('runJsBundleEnd'); |
60 | | - if (runJsBundleEndEntries.length > 0) { |
61 | | - finishJsParseSpan((runJsBundleEndEntries.at(0)?.startTime ?? 0) / 1000); |
62 | | - } else { |
63 | | - const observer = new PerformanceObserver((list) => { |
64 | | - const entries = list.getEntriesByName('runJsBundleEnd'); |
65 | | - if (entries.length > 0) { |
66 | | - finishJsParseSpan((entries.at(0)?.startTime ?? 0) / 1000); |
67 | | - observer.disconnect(); |
68 | | - } |
69 | | - }); |
70 | | - observer.observe({type: 'mark', buffered: true}); |
| 44 | + // getEntriesByName() queries the JS-side entry store, which is only populated after |
| 45 | + // CONTENT_APPEARED fires (emitBufferedMarks). Since this code runs during JS bundle |
| 46 | + // execution — before content appears — the sync check always returns []. |
| 47 | + // Use a PerformanceObserver with type 'react-native-mark' (native marks arrive as |
| 48 | + // PerformanceReactNativeMark, not PerformanceMark) and buffered: true so it fires |
| 49 | + // when CONTENT_APPEARED flushes the native mark buffer to JS. |
| 50 | + let jsParseStartMs: number | undefined; |
| 51 | + const observer = new PerformanceObserver((list) => { |
| 52 | + for (const entry of list.getEntries()) { |
| 53 | + if (entry.name === 'runJsBundleStart' && jsParseStartMs === undefined) { |
| 54 | + jsParseStartMs = entry.startTime; |
| 55 | + startSpan(CONST.TELEMETRY.SPAN_JS_PARSE_TIME, { |
| 56 | + name: CONST.TELEMETRY.SPAN_JS_PARSE_TIME, |
| 57 | + op: CONST.TELEMETRY.SPAN_JS_PARSE_TIME, |
| 58 | + startTime: jsParseStartMs / 1000, |
| 59 | + }); |
| 60 | + } |
| 61 | + if (entry.name === 'runJsBundleEnd' && jsParseStartMs !== undefined) { |
| 62 | + endSpan(CONST.TELEMETRY.SPAN_JS_PARSE_TIME, entry.startTime / 1000); |
| 63 | + observer.disconnect(); |
| 64 | + } |
71 | 65 | } |
72 | | - } |
| 66 | + }); |
| 67 | + observer.observe({type: 'react-native-mark', buffered: true}); |
73 | 68 | } |
0 commit comments