react-native.tsx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. import {Fragment} from 'react';
  2. import ExternalLink from 'sentry/components/links/externalLink';
  3. import List from 'sentry/components/list/';
  4. import ListItem from 'sentry/components/list/listItem';
  5. import {StepType} from 'sentry/components/onboarding/gettingStartedDoc/step';
  6. import type {
  7. Docs,
  8. DocsParams,
  9. OnboardingConfig,
  10. } from 'sentry/components/onboarding/gettingStartedDoc/types';
  11. import {
  12. getCrashReportApiIntroduction,
  13. getCrashReportInstallDescription,
  14. } from 'sentry/components/onboarding/gettingStartedDoc/utils/feedbackOnboarding';
  15. import {getReactNativeMetricsOnboarding} from 'sentry/components/onboarding/gettingStartedDoc/utils/metricsOnboarding';
  16. import {t, tct} from 'sentry/locale';
  17. type Params = DocsParams;
  18. const getConfigureSnippet = (params: Params) => `
  19. import * as Sentry from "@sentry/react-native";
  20. Sentry.init({
  21. dsn: "${params.dsn}",${
  22. params.isPerformanceSelected
  23. ? `
  24. // Set tracesSampleRate to 1.0 to capture 100% of transactions for performance monitoring.
  25. // We recommend adjusting this value in production.
  26. tracesSampleRate: 1.0,`
  27. : ''
  28. }${
  29. params.isProfilingSelected
  30. ? `
  31. _experiments: {
  32. // profilesSampleRate is relative to tracesSampleRate.
  33. // Here, we'll capture profiles for 100% of transactions.
  34. profilesSampleRate: 1.0,
  35. },`
  36. : ''
  37. }
  38. });`;
  39. const getPerformanceSnippet = () => `
  40. // Let's say this function is invoked when a user clicks on the checkout button of your shop
  41. shopCheckout() {
  42. // This will create a new Transaction for you
  43. const transaction = Sentry.startTransaction({ name: "shopCheckout" });
  44. // Set transaction on scope to associate with errors and get included span instrumentation
  45. // If there's currently an unfinished transaction, it may be dropped
  46. Sentry.getCurrentHub().configureScope(scope => scope.setSpan(transaction));
  47. // Assume this function makes an xhr/fetch call
  48. const result = validateShoppingCartOnServer();
  49. const span = transaction.startChild({
  50. data: {
  51. result
  52. },
  53. op: 'task',
  54. description: "processing shopping cart result",
  55. });
  56. try {
  57. processAndValidateShoppingCart(result);
  58. span.setStatus(SpanStatus.Ok);
  59. } catch (err) {
  60. span.setStatus(SpanStatus.UnknownError);
  61. throw err;
  62. } finally {
  63. span.finish();
  64. transaction.finish();
  65. }
  66. }`;
  67. const onboarding: OnboardingConfig = {
  68. install: () => [
  69. {
  70. type: StepType.INSTALL,
  71. description: tct(
  72. 'Sentry captures data by using an SDK within your application’s runtime. If you are using Expo, see [expoLink:How to Add Sentry to Your Expo Project]. This SDK works for both managed and bare projects.',
  73. {expoLink: <ExternalLink href="https://docs.expo.dev/guides/using-sentry/" />}
  74. ),
  75. configurations: [
  76. {
  77. language: 'bash',
  78. description: <div>{tct('Run [code:@sentry/wizard]:', {code: <code />})}</div>,
  79. code: 'npx @sentry/wizard@latest -s -i reactNative',
  80. additionalInfo: (
  81. <Fragment>
  82. <p>
  83. {tct(
  84. '[wizardLink:Sentry Wizard] will patch your project accordingly, though you can [setupManuallyLink:setup manually] if you prefer.',
  85. {
  86. wizardLink: (
  87. <ExternalLink href="https://github.com/getsentry/sentry-wizard" />
  88. ),
  89. setupManuallyLink: (
  90. <ExternalLink href="https://docs.sentry.io/platforms/react-native/manual-setup/manual-setup/" />
  91. ),
  92. }
  93. )}
  94. </p>
  95. <List symbol="bullet">
  96. <ListItem>
  97. {t(
  98. 'iOS Specifics: When you use Xcode, you can hook directly into the build process to upload debug symbols and source maps.'
  99. )}
  100. </ListItem>
  101. <ListItem>
  102. {tct(
  103. "Android Specifics: We hook into Gradle for the source map build process. When you run [gradLewCode:./gradlew] assembleRelease, source maps are automatically built and uploaded to Sentry. If you have enabled Gradle's [orgGradleCode:org.gradle.configureondemand] feature, you'll need a clean build, or you'll need to disable this feature to upload the source map on every build by setting [orgGradleCodeConfigureCode:org.gradle.configureondemand=false] or remove it.",
  104. {
  105. gradLewCode: <code />,
  106. orgGradleCode: <code />,
  107. orgGradleCodeConfigureCode: <code />,
  108. }
  109. )}
  110. </ListItem>
  111. </List>
  112. </Fragment>
  113. ),
  114. },
  115. ],
  116. },
  117. ],
  118. configure: params => [
  119. {
  120. type: StepType.CONFIGURE,
  121. configurations: [
  122. ...(params.isProfilingSelected
  123. ? [
  124. {
  125. description: t(
  126. 'React Native Profiling beta is available since SDK version 5.8.0.'
  127. ),
  128. },
  129. ]
  130. : []),
  131. {
  132. language: 'javascript',
  133. code: getConfigureSnippet(params),
  134. additionalInfo: tct(
  135. 'The "sentry-wizard" will try to add it to your [code:App.tsx]',
  136. {
  137. code: <code />,
  138. }
  139. ),
  140. },
  141. {
  142. language: 'javascript',
  143. description: tct(
  144. 'Wrap your app with Sentry to automatically instrument it with [touchEventTrakingLink:touch event tracking] and [automaticPerformanceMonitoringLink:automatic performance monitoring]:',
  145. {
  146. touchEventTrakingLink: (
  147. <ExternalLink href="https://docs.sentry.io/platforms/react-native/touchevents/" />
  148. ),
  149. automaticPerformanceMonitoringLink: (
  150. <ExternalLink href="https://docs.sentry.io/platforms/react-native/performance/instrumentation/automatic-instrumentation/" />
  151. ),
  152. }
  153. ),
  154. code: 'export default Sentry.wrap(App);',
  155. additionalInfo: t(
  156. 'You do not need to do this for Sentry to work or if your app does not have a single parent "App" component.'
  157. ),
  158. },
  159. ],
  160. },
  161. ],
  162. verify: (params: Params) => [
  163. {
  164. type: StepType.VERIFY,
  165. description: t(
  166. 'Then create an intentional error, so you can test that everything is working:'
  167. ),
  168. configurations: [
  169. {
  170. language: 'javascript',
  171. code: "throw new Error('My first Sentry error!');",
  172. },
  173. {
  174. language: 'javascript',
  175. description: t('Or, try a native crash with:'),
  176. code: 'Sentry.nativeCrash();',
  177. additionalInfo: (
  178. <Fragment>
  179. {t(
  180. "If you're new to Sentry, use the email alert to access your account and complete a product tour."
  181. )}
  182. {t(
  183. "If you're an existing user and have disabled alerts, you won't receive this email."
  184. )}
  185. </Fragment>
  186. ),
  187. },
  188. ],
  189. },
  190. ...(params.isPerformanceSelected
  191. ? [
  192. {
  193. title: t('Performance'),
  194. description: (
  195. <Fragment>
  196. {t(
  197. 'Sentry can measure the performance of your app automatically when instrumented with the following routers:'
  198. )}
  199. <List symbol="bullet">
  200. <ListItem>
  201. <ExternalLink href="https://docs.sentry.io/platforms/react-native/performance/instrumentation/automatic-instrumentation/#react-navigation">
  202. {t('React Navigation')}
  203. </ExternalLink>
  204. </ListItem>
  205. <ListItem>
  206. <ExternalLink href="https://docs.sentry.io/platforms/react-native/performance/instrumentation/automatic-instrumentation/#react-navigation-v4">
  207. {t('React Navigation V4 and prior')}
  208. </ExternalLink>
  209. </ListItem>
  210. <ListItem>
  211. <ExternalLink href="https://docs.sentry.io/platforms/react-native/performance/instrumentation/automatic-instrumentation/#react-native-navigation">
  212. {t('React Native Navigation')}
  213. </ExternalLink>
  214. </ListItem>
  215. </List>
  216. {t(
  217. 'Additionally, you can create transactions and spans programatically:'
  218. )}
  219. </Fragment>
  220. ),
  221. configurations: [
  222. {
  223. description: t('For example:'),
  224. language: 'javascript',
  225. code: getPerformanceSnippet(),
  226. additionalInfo: tct(
  227. 'For more information, please refer to the [docLink: Sentry React Native documentation].',
  228. {
  229. docLink: (
  230. <ExternalLink href="https://docs.sentry.io/platforms/react-native/performance/instrumentation/" />
  231. ),
  232. }
  233. ),
  234. },
  235. ],
  236. },
  237. ]
  238. : []),
  239. {
  240. title: t('Debug Symbols'),
  241. description: (
  242. <Fragment>
  243. {t(
  244. 'We offer a range of methods to provide Sentry with debug symbols so that you can see symbolicated stack traces and triage issues faster.'
  245. )}
  246. <p>
  247. {tct(
  248. "Complete stack traces will be shown for React Native Javascript errors by default using Sentry's [automaticSourceMapsUploadLink:automatic source maps upload]. To set up manual source maps upload follow [guideLink:this guide].",
  249. {
  250. automaticSourceMapsUploadLink: (
  251. <ExternalLink href="https://docs.sentry.io/platforms/react-native/sourcemaps/" />
  252. ),
  253. guideLink: (
  254. <ExternalLink href="https://docs.sentry.io/platforms/react-native/sourcemaps/" />
  255. ),
  256. }
  257. )}
  258. </p>
  259. <p>
  260. {tct(
  261. "You'll also need to upload [debugSymbolsLink:Debug Symbols] generated by the native iOS and Android tooling for native crashes.",
  262. {
  263. debugSymbolsLink: (
  264. <ExternalLink href="https://docs.sentry.io/platforms/react-native/upload-debug/" />
  265. ),
  266. }
  267. )}
  268. </p>
  269. </Fragment>
  270. ),
  271. },
  272. {
  273. title: t('Source Context'),
  274. description: (
  275. <Fragment>
  276. <p>
  277. {tct(
  278. "If Sentry has access to your application's source code, it can show snippets of code [italic:(source context)] around the location of stack frames, which helps to quickly pinpoint problematic code.",
  279. {
  280. italic: <i />,
  281. }
  282. )}
  283. </p>
  284. <p>
  285. {tct(
  286. 'Source Context will be shown for React Native Javascript error by default if source maps are uploaded. To set up source maps upload, follow the [sourceMapsGuideLink:Source Maps guide].',
  287. {
  288. sourceMapsGuideLink: (
  289. <ExternalLink href="https://docs.sentry.io/platforms/react-native/sourcemaps/" />
  290. ),
  291. }
  292. )}
  293. </p>
  294. <p>
  295. {tct(
  296. "To enable source context for native errors, you'll need to upload native debug symbols to Sentry by following the instructions at [uploadWithGradleLink:Uploading Source Code Context With Sentry Gradle Plugin] and Uploading Source Context With Xcode.",
  297. {
  298. uploadWithGradleLink: (
  299. <ExternalLink href="https://docs.sentry.io/platforms/react-native/upload-debug/#uploading-source-context-with-sentry-gradle-plugin" />
  300. ),
  301. uploadWithXCodeLink: (
  302. <ExternalLink href="https://docs.sentry.io/platforms/react-native/upload-debug/#uploading-source-context-with-xcode" />
  303. ),
  304. }
  305. )}
  306. </p>
  307. </Fragment>
  308. ),
  309. },
  310. ],
  311. };
  312. const feedbackOnboardingCrashApi: OnboardingConfig = {
  313. introduction: () => getCrashReportApiIntroduction(),
  314. install: () => [
  315. {
  316. type: StepType.INSTALL,
  317. description: getCrashReportInstallDescription(),
  318. configurations: [
  319. {
  320. code: [
  321. {
  322. label: 'TypeScript',
  323. value: 'typescript',
  324. language: 'typescript',
  325. code: `import * as Sentry from "@sentry/react-native";
  326. import { UserFeedback } from "@sentry/react-native";
  327. const sentryId = Sentry.captureMessage("My Message");
  328. // OR: const sentryId = Sentry.lastEventId();
  329. const userFeedback: UserFeedback = {
  330. event_id: sentryId,
  331. name: "John Doe",
  332. email: "john@doe.com",
  333. comments: "Hello World!",
  334. };
  335. Sentry.captureUserFeedback(userFeedback);`,
  336. },
  337. ],
  338. },
  339. ],
  340. },
  341. ],
  342. configure: () => [],
  343. verify: () => [],
  344. nextSteps: () => [],
  345. };
  346. const getInstallConfig = () => [
  347. {
  348. language: 'bash',
  349. code: [
  350. {
  351. label: 'npm',
  352. value: 'npm',
  353. language: 'bash',
  354. code: 'npm install --save @sentry/react-native',
  355. },
  356. {
  357. label: 'yarn',
  358. value: 'yarn',
  359. language: 'bash',
  360. code: 'yarn add @sentry/react-native',
  361. },
  362. ],
  363. },
  364. ];
  365. const docs: Docs = {
  366. onboarding,
  367. feedbackOnboardingCrashApi,
  368. crashReportOnboarding: feedbackOnboardingCrashApi,
  369. customMetricsOnboarding: getReactNativeMetricsOnboarding({getInstallConfig}),
  370. };
  371. export default docs;