Skip to content

Commit 95cfe1f

Browse files
fix(performance): app start frames can start with zeroed values (#3881)
1 parent d6c1900 commit 95cfe1f

File tree

5 files changed

+91
-11
lines changed

5 files changed

+91
-11
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
### Fixes
6+
7+
- App Start Native Frames can start with zeroed values ([#3881](https://github.com/getsentry/sentry-react-native/pull/3881))
8+
39
## 5.24.0
410

511
### Features

android/src/main/java/io/sentry/react/RNSentryModuleImpl.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -381,11 +381,6 @@ public void fetchNativeFrames(Promise promise) {
381381
}
382382
}
383383

384-
if (totalFrames == 0 && slowFrames == 0 && frozenFrames == 0) {
385-
promise.resolve(null);
386-
return;
387-
}
388-
389384
WritableMap map = Arguments.createMap();
390385
map.putInt("totalFrames", totalFrames);
391386
map.putInt("slowFrames", slowFrames);

ios/RNSentry.mm

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -415,12 +415,6 @@ - (NSDictionary*) fetchNativeStackFramesBy: (NSArray<NSNumber*>*)instructionsAdd
415415
NSNumber *total = [NSNumber numberWithLong:frames.total];
416416
NSNumber *frozen = [NSNumber numberWithLong:frames.frozen];
417417
NSNumber *slow = [NSNumber numberWithLong:frames.slow];
418-
NSNumber *zero = [NSNumber numberWithLong:0L];
419-
420-
if ([total isEqualToNumber:zero] && [frozen isEqualToNumber:zero] && [slow isEqualToNumber:zero]) {
421-
resolve(nil);
422-
return;
423-
}
424418

425419
resolve(@{
426420
@"totalFrames": total,

src/js/tracing/nativeframes.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,17 @@ export class NativeFramesInstrumentation {
192192
},
193193
};
194194

195+
if (
196+
measurements.frames_frozen.value <= 0 &&
197+
measurements.frames_slow.value <= 0 &&
198+
measurements.frames_total.value <= 0
199+
) {
200+
logger.warn(
201+
`[NativeFrames] Detected zero slow or frozen frames. Not adding measurements to traceId (${traceId}).`,
202+
);
203+
return null;
204+
}
205+
195206
return measurements;
196207
}
197208

test/tracing/nativeframes.test.ts

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,80 @@ describe('NativeFramesInstrumentation', () => {
9898
);
9999
});
100100

101+
it('sets native frames measurements on a transaction event (start frames zero)', async () => {
102+
const startFrames = {
103+
totalFrames: 0,
104+
slowFrames: 0,
105+
frozenFrames: 0,
106+
};
107+
const finishFrames = {
108+
totalFrames: 100,
109+
slowFrames: 20,
110+
frozenFrames: 5,
111+
};
112+
mockFunction(NATIVE.fetchNativeFrames).mockResolvedValueOnce(startFrames).mockResolvedValueOnce(finishFrames);
113+
114+
await startSpan({ name: 'test' }, async () => {
115+
await Promise.resolve(); // native frames fetch is async call this will flush the start frames fetch promise
116+
});
117+
118+
await jest.runOnlyPendingTimersAsync();
119+
await client.flush();
120+
121+
expect(client.event!).toEqual(
122+
expect.objectContaining<Partial<Event>>({
123+
measurements: expect.objectContaining<Measurements>({
124+
frames_total: {
125+
value: 100,
126+
unit: 'none',
127+
},
128+
frames_slow: {
129+
value: 20,
130+
unit: 'none',
131+
},
132+
frames_frozen: {
133+
value: 5,
134+
unit: 'none',
135+
},
136+
}),
137+
}),
138+
);
139+
});
140+
141+
it('does not sent zero value native frames measurements', async () => {
142+
const startFrames = {
143+
totalFrames: 100,
144+
slowFrames: 20,
145+
frozenFrames: 5,
146+
};
147+
const finishFrames = {
148+
totalFrames: 100,
149+
slowFrames: 20,
150+
frozenFrames: 5,
151+
};
152+
mockFunction(NATIVE.fetchNativeFrames).mockResolvedValueOnce(startFrames).mockResolvedValueOnce(finishFrames);
153+
154+
await startSpan({ name: 'test' }, async () => {
155+
await Promise.resolve(); // native frames fetch is async call this will flush the start frames fetch promise
156+
});
157+
158+
await jest.runOnlyPendingTimersAsync();
159+
await client.flush();
160+
161+
expect(client.event!).toEqual(
162+
expect.objectContaining<Partial<Event>>({
163+
measurements: expect.toBeOneOf([
164+
expect.not.objectContaining<Measurements>({
165+
frames_total: expect.any(Object),
166+
frames_slow: expect.any(Object),
167+
frames_frozen: expect.any(Object),
168+
}),
169+
undefined,
170+
]),
171+
}),
172+
);
173+
});
174+
101175
it('does not set measurements on transactions without startFrames', async () => {
102176
const startFrames = null;
103177
const finishFrames = {

0 commit comments

Comments
 (0)