Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(transport): Fallback to fetch transport if native not available #2695

Merged
merged 22 commits into from
Dec 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
20a6984
ref(client): Remove dep on BrowserClient
krystofwoldrich Dec 13, 2022
3177853
fix formatting
krystofwoldrich Dec 13, 2022
b859da1
ref(client): Simplify client constructor
krystofwoldrich Dec 13, 2022
24c9cdd
ref: move exception to threads for messages
krystofwoldrich Dec 13, 2022
e4c64f6
only map stacktrace
krystofwoldrich Dec 13, 2022
3dc1b56
Merge branch 'refactor-client-event-from' into ref-client-constructor
krystofwoldrich Dec 13, 2022
eafdd0e
Remove unnecessary transport factory, rename ignore logs
krystofwoldrich Dec 13, 2022
15977d1
Merge branch 'main' into refactor-client-event-from
krystofwoldrich Dec 14, 2022
a89878b
Fix imports order
krystofwoldrich Dec 14, 2022
898da27
Add changelog
krystofwoldrich Dec 14, 2022
0f2f8cf
Merge branch '5.0.0' into refactor-client-event-from
krystofwoldrich Dec 14, 2022
f5fce5f
Merge branch 'refactor-client-event-from' into ref-client-constructor
krystofwoldrich Dec 14, 2022
61fda35
Fix fetch transport can be reached
krystofwoldrich Dec 14, 2022
bffe416
Formatting
krystofwoldrich Dec 14, 2022
3c2a41b
Add test to check message event threads
krystofwoldrich Dec 14, 2022
3cb00a9
Add attach stack trace default true
krystofwoldrich Dec 14, 2022
f6aa85d
Merge branch 'refactor-client-event-from' into ref-client-constructor
krystofwoldrich Dec 14, 2022
a692278
Add tests and changelog
krystofwoldrich Dec 14, 2022
6364cdc
Add pr id
krystofwoldrich Dec 14, 2022
f88bf07
Merge branch '5.0.0' into ref-client-constructor
krystofwoldrich Dec 20, 2022
e08e61c
Remove unnecessary stack parser fallback
krystofwoldrich Dec 20, 2022
fccee60
Fix unused defaultStackParser import
krystofwoldrich Dec 20, 2022
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
Expand Up @@ -8,6 +8,10 @@

- Message event current stack trace moved from exception to threads ([#2694](https://github.com/getsentry/sentry-react-native/pull/2694))

### Fixes

- Unreachable fallback to fetch transport if native is not available ([#2695](https://github.com/getsentry/sentry-react-native/pull/2695))

## 4.12.0

### Features
Expand Down
32 changes: 5 additions & 27 deletions src/js/client.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { eventFromException, eventFromMessage,makeFetchTransport } from '@sentry/browser';
import { FetchImpl } from '@sentry/browser/types/transports/utils';
import { eventFromException, eventFromMessage } from '@sentry/browser';
import { BaseClient } from '@sentry/core';
import {
ClientReportEnvelope,
Expand All @@ -11,18 +10,16 @@ import {
Outcome,
SeverityLevel,
Thread,
Transport,
UserFeedback,
} from '@sentry/types';
import { dateTimestampInSeconds, logger, SentryError } from '@sentry/utils';
// @ts-ignore LogBox introduced in RN 0.63
import { Alert, LogBox, YellowBox } from 'react-native';
import { Alert } from 'react-native';

import { Screenshot } from './integrations/screenshot';
import { defaultSdkInfo } from './integrations/sdkinfo';
import { ReactNativeClientOptions, ReactNativeTransportOptions } from './options';
import { makeReactNativeTransport } from './transports/native';
import { ReactNativeClientOptions } from './options';
import { createUserFeedbackEnvelope, items } from './utils/envelope';
import { ignoreRequireCycleLogs } from './utils/ignorerequirecyclelogs';
import { mergeOutcomes } from './utils/outcome';
import { NATIVE } from './wrapper';

Expand All @@ -41,34 +38,15 @@ export class ReactNativeClient extends BaseClient<ReactNativeClientOptions> {
* @param options Configuration options for this SDK.
*/
public constructor(options: ReactNativeClientOptions) {
if (!options.transport) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

option.transport is required and has a fallback in sdk.tsx, so this if statement wasn't working

options.transport = (options: ReactNativeTransportOptions, nativeFetch?: FetchImpl): Transport => {
if (NATIVE.isNativeTransportAvailable()) {
return makeReactNativeTransport(options);
}
return makeFetchTransport(options, nativeFetch);
};
}
ignoreRequireCycleLogs();
options._metadata = options._metadata || {};
options._metadata.sdk = options._metadata.sdk || defaultSdkInfo;
super(options);

this._outcomesBuffer = [];

// This is a workaround for now using fetch on RN, this is a known issue in react-native and only generates a warning
// YellowBox deprecated and replaced with with LogBox in RN 0.63
if (LogBox) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
LogBox.ignoreLogs(['Require cycle:']);
} else {
// eslint-disable-next-line deprecation/deprecation
YellowBox.ignoreWarnings(['Require cycle:']);
}

void this._initNativeSdk();
}


/**
* @inheritDoc
*/
Expand Down
5 changes: 3 additions & 2 deletions src/js/sdk.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
defaultIntegrations as reactDefaultIntegrations,
defaultStackParser,
getCurrentHub,
makeFetchTransport,
} from '@sentry/react';
import { Integration, StackFrame, UserFeedback } from '@sentry/types';
import { logger, stackParserFromStackParserOptions } from '@sentry/utils';
Expand All @@ -25,7 +26,7 @@ import { ReactNativeClientOptions, ReactNativeOptions, ReactNativeWrapperOptions
import { ReactNativeScope } from './scope';
import { TouchEventBoundary } from './touchevents';
import { ReactNativeProfiler, ReactNativeTracing } from './tracing';
import { DEFAULT_BUFFER_SIZE, makeReactNativeTransport } from './transports/native';
import { DEFAULT_BUFFER_SIZE, makeNativeTransportFactory } from './transports/native';
import { makeUtf8TextEncoder } from './transports/TextEncoder';
import { safeFactory, safeTracesSampler } from './utils/safe';

Expand Down Expand Up @@ -64,7 +65,7 @@ export function init(passedOptions: ReactNativeOptions): void {
...DEFAULT_OPTIONS,
...passedOptions,
// If custom transport factory fails the SDK won't initialize
transport: passedOptions.transport || makeReactNativeTransport,
transport: passedOptions.transport || makeNativeTransportFactory() || makeFetchTransport,
transportOptions: {
...DEFAULT_OPTIONS.transportOptions,
...(passedOptions.transportOptions ?? {}),
Expand Down
12 changes: 11 additions & 1 deletion src/js/transports/native.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,16 @@ export class NativeTransport implements Transport {
/**
* Creates a Native Transport.
*/
export function makeReactNativeTransport(options: BaseNativeTransportOptions = {}): NativeTransport {
export function makeNativeTransport(options: BaseNativeTransportOptions = {}): NativeTransport {
return new NativeTransport(options);
}

/**
* Creates a Native Transport factory if the native transport is available.
*/
export function makeNativeTransportFactory(): typeof makeNativeTransport | null {
if (NATIVE.isNativeTransportAvailable()) {
return makeNativeTransport;
}
return null;
}
14 changes: 14 additions & 0 deletions src/js/utils/ignorerequirecyclelogs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/* eslint-disable deprecation/deprecation */
import { LogBox, YellowBox } from 'react-native';

/**
* This is a workaround for now using fetch on RN, this is a known issue in react-native and only generates a warning
* YellowBox deprecated and replaced with with LogBox in RN 0.63
*/
export function ignoreRequireCycleLogs(): void {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with the refactoring here and separating the concerns.

if (LogBox) {
LogBox.ignoreLogs(['Require cycle:']);
} else {
YellowBox.ignoreWarnings(['Require cycle:']);
}
}
36 changes: 31 additions & 5 deletions test/sdk.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
*/
import { logger } from '@sentry/utils';

import { NATIVE } from '../src/js/wrapper';

interface MockedClient {
flush: jest.Mock;
}
Expand Down Expand Up @@ -61,18 +63,24 @@ jest.mock('../src/js/client', () => {
};
});

jest.mock('../src/js/wrapper');

jest.spyOn(logger, 'error');

import { initAndBind } from '@sentry/core';
import { getCurrentHub } from '@sentry/react';
import { getCurrentHub, makeFetchTransport } from '@sentry/react';
import { BaseTransportOptions,ClientOptions, Integration, Scope } from '@sentry/types';

import { ReactNativeClientOptions } from '../src/js/options';
import { configureScope,flush, init, withScope } from '../src/js/sdk';
import { ReactNativeTracing, ReactNavigationInstrumentation } from '../src/js/tracing';
import { makeNativeTransport } from '../src/js/transports/native';
import { firstArg, secondArg } from './testutils';

const mockedInitAndBind = initAndBind as jest.MockedFunction<typeof initAndBind>;
const usedOptions = (): ClientOptions<BaseTransportOptions> | undefined => {
return mockedInitAndBind.mock.calls[0]?.[1];
}

afterEach(() => {
jest.clearAllMocks();
Expand Down Expand Up @@ -184,10 +192,6 @@ describe('Tests the SDK functionality', () => {
});

describe('transport options buffer size', () => {
const usedOptions = (): ClientOptions<BaseTransportOptions> | undefined => {
return mockedInitAndBind.mock.calls[0]?.[1];
}

it('uses default transport options buffer size', () => {
init({
tracesSampleRate: 0.5,
Expand All @@ -214,6 +218,28 @@ describe('Tests the SDK functionality', () => {
});
});

describe('transport initialization', () => {
it('uses transport from the options', () => {
const mockTransport = jest.fn();
init({
transport: mockTransport,
});
expect(usedOptions()?.transport).toEqual(mockTransport);
});

it('uses native transport', () => {
(NATIVE.isNativeTransportAvailable as jest.Mock).mockImplementation(() => true);
init({});
expect(usedOptions()?.transport).toEqual(makeNativeTransport);
});

it('uses fallback fetch transport', () => {
(NATIVE.isNativeTransportAvailable as jest.Mock).mockImplementation(() => false);
init({});
expect(usedOptions()?.transport).toEqual(makeFetchTransport);
});
});

describe('initIsSafe', () => {
test('initialScope callback is safe after init', () => {
const mockInitialScope = jest.fn(() => { throw 'Test error' });
Expand Down