Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## Unreleased

- Filter out app start with more than 60s ([#2303](https://github.com/getsentry/sentry-react-native/pull/2303))

## 4.0.0

- Bump Sentry Cocoa 7.18.0 ([#2303](https://github.com/getsentry/sentry-react-native/pull/2303))
Expand Down
9 changes: 9 additions & 0 deletions src/js/tracing/reactnativetracing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,8 @@ export class ReactNativeTracing implements Integration {
* @inheritDoc
*/
public static id: string = 'ReactNativeTracing';
/** We filter out App starts more than 60s */
private static _maxAppStart: number = 60000;
/**
* @inheritDoc
*/
Expand Down Expand Up @@ -294,6 +296,13 @@ export class ReactNativeTracing implements Integration {
const appStartDurationMilliseconds =
this._appStartFinishTimestamp * 1000 - appStart.appStartTime;

// we filter out app start more than 60s.
// this could be due to many different reasons.
// we've seen app starts with hours, days and even months.
if (appStartDurationMilliseconds >= ReactNativeTracing._maxAppStart) {
return;
}

transaction.setMeasurement(appStartMode, appStartDurationMilliseconds);
}

Expand Down
46 changes: 46 additions & 0 deletions test/tracing/reactnativetracing.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,52 @@ describe('ReactNativeTracing', () => {
});
});

it('Does not add app start measurement if more than 60s', (done) => {
const integration = new ReactNativeTracing();

const timeOriginMilliseconds = Date.now();
const appStartTimeMilliseconds = timeOriginMilliseconds - 65000;
const mockAppStartResponse: NativeAppStartResponse = {
isColdStart: false,
appStartTime: appStartTimeMilliseconds,
didFetchAppStart: false,
};

mockFunction(getTimeOriginMilliseconds).mockReturnValue(
timeOriginMilliseconds
);
// eslint-disable-next-line @typescript-eslint/unbound-method
mockFunction(NATIVE.fetchNativeAppStart).mockResolvedValue(
mockAppStartResponse
);

const mockHub = getMockHub();
integration.setupOnce(addGlobalEventProcessor, () => mockHub);

// use setImmediate as app start is handled inside a promise.
setImmediate(() => {
const transaction = mockHub.getScope()?.getTransaction();

expect(transaction).toBeDefined();

jest.runOnlyPendingTimers();

if (transaction) {
expect(
// @ts-ignore access private for test
transaction._measurements?.app_start_warm
).toBeUndefined();

expect(
// @ts-ignore access private for test
transaction._measurements?.app_start_cold
).toBeUndefined();

done();
}
});
});

it('Does not create app start transaction if didFetchAppStart == true', (done) => {
const integration = new ReactNativeTracing();

Expand Down