@@ -6,6 +6,13 @@ import type { NativeFramesResponse } from '../NativeRNSentry';
66import { NATIVE } from '../wrapper' ;
77import { instrumentChildSpanFinish } from './utils' ;
88
9+ /**
10+ * Timeout from the final native frames fetch to processing the associated transaction.
11+ * If the transaction is not processed by this time, the native frames will be dropped
12+ * and not added to the event.
13+ */
14+ const FINAL_FRAMES_TIMEOUT_MS = 2000 ;
15+
916export interface FramesMeasurements extends Measurements {
1017 frames_total : { value : number ; unit : MeasurementUnit } ;
1118 frames_slow : { value : number ; unit : MeasurementUnit } ;
@@ -45,14 +52,24 @@ export class NativeFramesInstrumentation {
4552 * Logs the native frames at this start point and instruments child span finishes.
4653 */
4754 public onTransactionStart ( transaction : Transaction ) : void {
55+ logger . debug ( `[NativeFrames] Fetching frames for root span start (${ transaction . spanContext ( ) . spanId } ).` ) ;
4856 void NATIVE . fetchNativeFrames ( )
4957 . then ( framesMetrics => {
5058 if ( framesMetrics ) {
5159 transaction . setData ( '__startFrames' , framesMetrics ) ;
60+ } else {
61+ logger . warn (
62+ `[NativeFrames] Fetched frames for root span start (${
63+ transaction . spanContext ( ) . spanId
64+ } ), but no frames were returned.`,
65+ ) ;
5266 }
5367 } )
5468 . then ( undefined , error => {
55- logger . error ( `[ReactNativeTracing] Error while fetching native frames: ${ error } ` ) ;
69+ logger . error (
70+ `[NativeFrames] Error while fetching frames for root span start (${ transaction . spanContext ( ) . spanId } )` ,
71+ error ,
72+ ) ;
5673 } ) ;
5774
5875 instrumentChildSpanFinish ( transaction , ( _ : Span , endTimestamp ?: number ) => {
@@ -66,8 +83,11 @@ export class NativeFramesInstrumentation {
6683 * To be called when a transaction is finished
6784 */
6885 public onTransactionFinish ( transaction : Transaction ) : void {
69- this . _fetchFramesForTransaction ( transaction ) . then ( undefined , ( reason : unknown ) => {
70- logger . error ( `[ReactNativeTracing] Error while fetching native frames:` , reason ) ;
86+ this . _fetchEndFramesForTransaction ( transaction ) . then ( undefined , ( reason : unknown ) => {
87+ logger . error (
88+ `[NativeFrames] Error while fetching frames for root span start (${ transaction . spanContext ( ) . spanId } )` ,
89+ reason ,
90+ ) ;
7191 } ) ;
7292 }
7393
@@ -88,7 +108,7 @@ export class NativeFramesInstrumentation {
88108 }
89109 } )
90110 . then ( undefined , error => {
91- logger . error ( `[ReactNativeTracing ] Error while fetching native frames: ${ error } ` ) ;
111+ logger . error ( `[NativeFrames ] Error while fetching frames for child span end.` , error ) ;
92112 } ) ;
93113 }
94114
@@ -101,17 +121,20 @@ export class NativeFramesInstrumentation {
101121 startFrames : NativeFramesResponse ,
102122 ) : Promise < FramesMeasurements | null > {
103123 if ( _finishFrames . has ( traceId ) ) {
124+ logger . debug ( `[NativeFrames] Native end frames already fetched for trace id (${ traceId } ).` ) ;
104125 return this . _prepareMeasurements ( traceId , finalEndTimestamp , startFrames ) ;
105126 }
106127
107128 return new Promise ( resolve => {
108129 const timeout = setTimeout ( ( ) => {
130+ logger . debug ( `[NativeFrames] Native end frames listener removed by timeout for trace id (${ traceId } ).` ) ;
109131 _framesListeners . delete ( traceId ) ;
110132
111133 resolve ( null ) ;
112134 } , 2000 ) ;
113135
114136 _framesListeners . set ( traceId , ( ) => {
137+ logger . debug ( `[NativeFrames] Native end frames listener called for trace id (${ traceId } ).` ) ;
115138 resolve ( this . _prepareMeasurements ( traceId , finalEndTimestamp , startFrames ) ) ;
116139
117140 clearTimeout ( timeout ) ;
@@ -137,15 +160,20 @@ export class NativeFramesInstrumentation {
137160 // Must be in the margin of error of the actual transaction finish time (finalEndTimestamp)
138161 Math . abs ( finish . timestamp - finalEndTimestamp ) < MARGIN_OF_ERROR_SECONDS
139162 ) {
163+ logger . debug ( `[NativeFrames] Using frames from root span end (traceId, ${ traceId } ).` ) ;
140164 finalFinishFrames = finish . nativeFrames ;
141165 } else if (
142166 this . _lastSpanFinishFrames &&
143167 Math . abs ( this . _lastSpanFinishFrames . timestamp - finalEndTimestamp ) < MARGIN_OF_ERROR_SECONDS
144168 ) {
145169 // Fallback to the last span finish if it is within the margin of error of the actual finish timestamp.
146170 // This should be the case for trimEnd.
171+ logger . debug ( `[NativeFrames] Using native frames from last span end (traceId, ${ traceId } ).` ) ;
147172 finalFinishFrames = this . _lastSpanFinishFrames . nativeFrames ;
148173 } else {
174+ logger . warn (
175+ `[NativeFrames] Frames were collected within larger than margin of error delay for traceId (${ traceId } ). Dropping the inaccurate values.` ,
176+ ) ;
149177 return null ;
150178 }
151179
@@ -170,7 +198,7 @@ export class NativeFramesInstrumentation {
170198 /**
171199 * Fetch finish frames for a transaction at the current time. Calls any awaiting listeners.
172200 */
173- private async _fetchFramesForTransaction ( transaction : Transaction ) : Promise < void > {
201+ private async _fetchEndFramesForTransaction ( transaction : Transaction ) : Promise < void > {
174202 const startFrames = transaction . data . __startFrames as NativeFramesResponse | undefined ;
175203
176204 // This timestamp marks when the finish frames were retrieved. It should be pretty close to the transaction finish.
@@ -187,13 +215,13 @@ export class NativeFramesInstrumentation {
187215
188216 _framesListeners . get ( transaction . traceId ) ?.( ) ;
189217
190- setTimeout ( ( ) => this . _cancelFinishFrames ( transaction ) , 2000 ) ;
218+ setTimeout ( ( ) => this . _cancelEndFrames ( transaction ) , FINAL_FRAMES_TIMEOUT_MS ) ;
191219 }
192220
193221 /**
194222 * On a finish frames failure, we cancel the await.
195223 */
196- private _cancelFinishFrames ( transaction : Transaction ) : void {
224+ private _cancelEndFrames ( transaction : Transaction ) : void {
197225 if ( _finishFrames . has ( transaction . traceId ) ) {
198226 _finishFrames . delete ( transaction . traceId ) ;
199227
@@ -222,18 +250,20 @@ export class NativeFramesInstrumentation {
222250
223251 const traceId = traceContext . trace_id ;
224252
253+ if ( ! traceContext . data ?. __startFrames ) {
254+ logger . warn (
255+ `[NativeFrames] Start frames of transaction ${ event . transaction } (eventId, ${ event . event_id } ) are missing, but it already ended.` ,
256+ ) ;
257+ }
258+
225259 if ( traceId && traceContext . data ?. __startFrames && event . timestamp ) {
226260 const measurements = await this . _getFramesMeasurements (
227261 traceId ,
228262 event . timestamp ,
229263 traceContext . data . __startFrames as NativeFramesResponse ,
230264 ) ;
231265
232- if ( ! measurements ) {
233- logger . log (
234- `[NativeFrames] Could not fetch native frames for ${ traceContext . op } transaction ${ event . transaction } . Not adding native frames measurements.` ,
235- ) ;
236- } else {
266+ if ( measurements ) {
237267 logger . log (
238268 `[Measurements] Adding measurements to ${ traceContext . op } transaction ${
239269 event . transaction
0 commit comments