react.tsx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. import {Fragment} from 'react';
  2. import ExternalLink from 'sentry/components/links/externalLink';
  3. import {buildSdkConfig} from 'sentry/components/onboarding/gettingStartedDoc/buildSdkConfig';
  4. import crashReportCallout from 'sentry/components/onboarding/gettingStartedDoc/feedback/crashReportCallout';
  5. import widgetCallout from 'sentry/components/onboarding/gettingStartedDoc/feedback/widgetCallout';
  6. import TracePropagationMessage from 'sentry/components/onboarding/gettingStartedDoc/replay/tracePropagationMessage';
  7. import {StepType} from 'sentry/components/onboarding/gettingStartedDoc/step';
  8. import type {
  9. Docs,
  10. DocsParams,
  11. OnboardingConfig,
  12. } from 'sentry/components/onboarding/gettingStartedDoc/types';
  13. import {getUploadSourceMapsStep} from 'sentry/components/onboarding/gettingStartedDoc/utils';
  14. import {
  15. getCrashReportJavaScriptInstallStep,
  16. getCrashReportModalConfigDescription,
  17. getCrashReportModalIntroduction,
  18. getFeedbackConfigOptions,
  19. getFeedbackConfigureDescription,
  20. } from 'sentry/components/onboarding/gettingStartedDoc/utils/feedbackOnboarding';
  21. import {
  22. getProfilingDocumentHeaderConfigurationStep,
  23. MaybeBrowserProfilingBetaWarning,
  24. } from 'sentry/components/onboarding/gettingStartedDoc/utils/profilingOnboarding';
  25. import {
  26. getReplayConfigOptions,
  27. getReplayConfigureDescription,
  28. getReplayVerifyStep,
  29. } from 'sentry/components/onboarding/gettingStartedDoc/utils/replayOnboarding';
  30. import {featureFlagOnboarding} from 'sentry/gettingStartedDocs/javascript/javascript';
  31. import {t, tct} from 'sentry/locale';
  32. type Params = DocsParams;
  33. const getDynamicParts = (params: Params): string[] => {
  34. const dynamicParts: string[] = [];
  35. if (params.isPerformanceSelected) {
  36. dynamicParts.push(`
  37. // Tracing
  38. tracesSampleRate: 1.0, // Capture 100% of the transactions
  39. // Set 'tracePropagationTargets' to control for which URLs distributed tracing should be enabled
  40. tracePropagationTargets: ["localhost", /^https:\\/\\/yourserver\\.io\\/api/]`);
  41. }
  42. if (params.isReplaySelected) {
  43. dynamicParts.push(`
  44. // Session Replay
  45. replaysSessionSampleRate: 0.1, // This sets the sample rate at 10%. You may want to change it to 100% while in development and then sample at a lower rate in production.
  46. replaysOnErrorSampleRate: 1.0 // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur.`);
  47. }
  48. if (params.isProfilingSelected) {
  49. dynamicParts.push(`
  50. // Set profilesSampleRate to 1.0 to profile every transaction.
  51. // Since profilesSampleRate is relative to tracesSampleRate,
  52. // the final profiling rate can be computed as tracesSampleRate * profilesSampleRate
  53. // For example, a tracesSampleRate of 0.5 and profilesSampleRate of 0.5 would
  54. // results in 25% of transactions being profiled (0.5*0.5=0.25)
  55. profilesSampleRate: 1.0`);
  56. }
  57. return dynamicParts;
  58. };
  59. const getIntegrations = (params: Params): string[] => {
  60. const integrations = [];
  61. if (params.isPerformanceSelected) {
  62. integrations.push(`Sentry.browserTracingIntegration()`);
  63. }
  64. if (params.isProfilingSelected) {
  65. integrations.push(`Sentry.browserProfilingIntegration()`);
  66. }
  67. if (params.isReplaySelected) {
  68. integrations.push(
  69. `Sentry.replayIntegration(${getReplayConfigOptions(params.replayOptions)})`
  70. );
  71. }
  72. if (params.isFeedbackSelected) {
  73. integrations.push(`
  74. Sentry.feedbackIntegration({
  75. colorScheme: "system",
  76. ${getFeedbackConfigOptions(params.feedbackOptions)}
  77. }),`);
  78. }
  79. return integrations;
  80. };
  81. const getSdkSetupSnippet = (params: Params) => {
  82. const config = buildSdkConfig({
  83. params,
  84. staticParts: [`dsn: "${params.dsn.public}"`],
  85. getIntegrations,
  86. getDynamicParts,
  87. });
  88. return `
  89. import * as Sentry from "@sentry/react";
  90. Sentry.init({
  91. ${config}
  92. });
  93. const container = document.getElementById(“app”);
  94. const root = createRoot(container);
  95. root.render(<App />);
  96. `;
  97. };
  98. const getVerifySnippet = () => `
  99. return <button onClick={() => {throw new Error("This is your first error!");}}>Break the world</button>;
  100. `;
  101. const getInstallConfig = () => [
  102. {
  103. language: 'bash',
  104. code: [
  105. {
  106. label: 'npm',
  107. value: 'npm',
  108. language: 'bash',
  109. code: 'npm install --save @sentry/react',
  110. },
  111. {
  112. label: 'yarn',
  113. value: 'yarn',
  114. language: 'bash',
  115. code: 'yarn add @sentry/react',
  116. },
  117. ],
  118. },
  119. ];
  120. const onboarding: OnboardingConfig = {
  121. introduction: params => (
  122. <Fragment>
  123. <MaybeBrowserProfilingBetaWarning {...params} />
  124. <p>
  125. {tct('In this quick guide you’ll use [strong:npm] or [strong:yarn] to set up:', {
  126. strong: <strong />,
  127. })}
  128. </p>
  129. </Fragment>
  130. ),
  131. install: () => [
  132. {
  133. type: StepType.INSTALL,
  134. description: tct(
  135. 'Add the Sentry SDK as a dependency using [code:npm] or [code:yarn]:',
  136. {code: <code />}
  137. ),
  138. configurations: getInstallConfig(),
  139. },
  140. ],
  141. configure: (params: Params) => [
  142. {
  143. type: StepType.CONFIGURE,
  144. description: t(
  145. "Initialize Sentry as early as possible in your application's lifecycle."
  146. ),
  147. configurations: [
  148. {
  149. code: [
  150. {
  151. label: 'JavaScript',
  152. value: 'javascript',
  153. language: 'javascript',
  154. code: getSdkSetupSnippet(params),
  155. },
  156. ],
  157. },
  158. ...(params.isProfilingSelected
  159. ? [getProfilingDocumentHeaderConfigurationStep()]
  160. : []),
  161. ],
  162. },
  163. getUploadSourceMapsStep({
  164. guideLink: 'https://docs.sentry.io/platforms/javascript/guides/react/sourcemaps/',
  165. ...params,
  166. }),
  167. ],
  168. verify: () => [
  169. {
  170. type: StepType.VERIFY,
  171. description: t(
  172. "This snippet contains an intentional error and can be used as a test to make sure that everything's working as expected."
  173. ),
  174. configurations: [
  175. {
  176. code: [
  177. {
  178. label: 'React',
  179. value: 'react',
  180. language: 'javascript',
  181. code: getVerifySnippet(),
  182. },
  183. ],
  184. },
  185. ],
  186. },
  187. ],
  188. nextSteps: () => [
  189. {
  190. id: 'react-features',
  191. name: t('React Features'),
  192. description: t('Learn about our first class integration with the React framework.'),
  193. link: 'https://docs.sentry.io/platforms/javascript/guides/react/features/',
  194. },
  195. {
  196. id: 'react-router',
  197. name: t('React Router'),
  198. description: t(
  199. 'Configure routing, so Sentry can generate parameterized transaction names for a better overview on the Performance page.'
  200. ),
  201. link: 'https://docs.sentry.io/platforms/javascript/guides/react/configuration/integrations/react-router/',
  202. },
  203. ],
  204. };
  205. const replayOnboarding: OnboardingConfig = {
  206. install: () => [
  207. {
  208. type: StepType.INSTALL,
  209. description: tct(
  210. 'Add the Sentry SDK as a dependency using [code:npm] or [code:yarn]. You need a minimum version 7.27.0 of [code:@sentry/react] in order to use Session Replay. You do not need to install any additional packages.',
  211. {code: <code />}
  212. ),
  213. configurations: getInstallConfig(),
  214. },
  215. ],
  216. configure: (params: Params) => [
  217. {
  218. type: StepType.CONFIGURE,
  219. description: getReplayConfigureDescription({
  220. link: 'https://docs.sentry.io/platforms/javascript/guides/react/session-replay/',
  221. }),
  222. configurations: [
  223. {
  224. code: [
  225. {
  226. label: 'JavaScript',
  227. value: 'javascript',
  228. language: 'javascript',
  229. code: getSdkSetupSnippet(params),
  230. },
  231. ],
  232. additionalInfo: <TracePropagationMessage />,
  233. },
  234. ],
  235. },
  236. ],
  237. verify: getReplayVerifyStep(),
  238. nextSteps: () => [],
  239. };
  240. const feedbackOnboarding: OnboardingConfig = {
  241. install: () => [
  242. {
  243. type: StepType.INSTALL,
  244. description: tct(
  245. 'For the User Feedback integration to work, you must have the Sentry browser SDK package, or an equivalent framework SDK (e.g. [code:@sentry/react]) installed, minimum version 7.85.0.',
  246. {
  247. code: <code />,
  248. }
  249. ),
  250. configurations: getInstallConfig(),
  251. },
  252. ],
  253. configure: (params: Params) => [
  254. {
  255. type: StepType.CONFIGURE,
  256. description: getFeedbackConfigureDescription({
  257. linkConfig:
  258. 'https://docs.sentry.io/platforms/javascript/guides/react/user-feedback/configuration/',
  259. linkButton:
  260. 'https://docs.sentry.io/platforms/javascript/guides/react/user-feedback/configuration/#bring-your-own-button',
  261. }),
  262. configurations: [
  263. {
  264. code: [
  265. {
  266. label: 'JavaScript',
  267. value: 'javascript',
  268. language: 'javascript',
  269. code: getSdkSetupSnippet(params),
  270. },
  271. ],
  272. },
  273. ],
  274. additionalInfo: crashReportCallout({
  275. link: 'https://docs.sentry.io/platforms/javascript/guides/react/user-feedback/#crash-report-modal',
  276. }),
  277. },
  278. ],
  279. verify: () => [],
  280. nextSteps: () => [],
  281. };
  282. const crashReportOnboarding: OnboardingConfig = {
  283. introduction: () => getCrashReportModalIntroduction(),
  284. install: (params: Params) => getCrashReportJavaScriptInstallStep(params),
  285. configure: () => [
  286. {
  287. type: StepType.CONFIGURE,
  288. description: getCrashReportModalConfigDescription({
  289. link: 'https://docs.sentry.io/platforms/javascript/guides/react/user-feedback/configuration/#crash-report-modal',
  290. }),
  291. additionalInfo: widgetCallout({
  292. link: 'https://docs.sentry.io/platforms/javascript/guides/react/user-feedback/#user-feedback-widget',
  293. }),
  294. },
  295. ],
  296. verify: () => [],
  297. nextSteps: () => [],
  298. };
  299. const performanceOnboarding: OnboardingConfig = {
  300. introduction: () =>
  301. t(
  302. "Adding Performance to your React project is simple. Make sure you've got these basics down."
  303. ),
  304. install: onboarding.install,
  305. configure: params => [
  306. {
  307. type: StepType.CONFIGURE,
  308. configurations: [
  309. {
  310. language: 'javascript',
  311. description: t(
  312. "Configuration should happen as early as possible in your application's lifecycle."
  313. ),
  314. code: `
  315. import React from "react";
  316. import ReactDOM from "react-dom";
  317. import * as Sentry from "@sentry/react";
  318. import App from "./App";
  319. Sentry.init({
  320. dsn: "${params.dsn.public}",
  321. integrations: [Sentry.browserTracingIntegration()],
  322. // Set tracesSampleRate to 1.0 to capture 100%
  323. // of transactions for performance monitoring.
  324. // We recommend adjusting this value in production
  325. tracesSampleRate: 1.0,
  326. // Set \`tracePropagationTargets\` to control for which URLs distributed tracing should be enabled
  327. tracePropagationTargets: ["localhost", /^https:\/\/yourserver\.io\/api/],
  328. });
  329. ReactDOM.render(<App />, document.getElementById("root"));
  330. // Can also use with React Concurrent Mode
  331. // ReactDOM.createRoot(document.getElementById('root')).render(<App />);
  332. `,
  333. additionalInfo: tct(
  334. 'We recommend adjusting the value of [code:tracesSampleRate] in production. Learn more about tracing [linkTracingOptions:options], how to use the [linkTracesSampler:traces_sampler] function, or how to do [linkSampleTransactions:sampling].',
  335. {
  336. code: <code />,
  337. linkTracingOptions: (
  338. <ExternalLink href="https://docs.sentry.io/platforms/javascript/guides/react/configuration/options/#tracing-options" />
  339. ),
  340. linkTracesSampler: (
  341. <ExternalLink href="https://docs.sentry.io/platforms/javascript/guides/react/configuration/sampling/" />
  342. ),
  343. linkSampleTransactions: (
  344. <ExternalLink href="https://docs.sentry.io/platforms/javascript/guides/react/configuration/sampling/" />
  345. ),
  346. }
  347. ),
  348. },
  349. {
  350. language: 'javascript',
  351. description: tct(
  352. "If you're using the current version of our JavaScript SDK and have enabled the [code: BrowserTracing] integration, distributed tracing will work out of the box. To get around possible [link:Browser CORS] issues, define your [code:tracePropagationTargets].",
  353. {
  354. code: <code />,
  355. link: (
  356. <ExternalLink href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" />
  357. ),
  358. }
  359. ),
  360. code: `
  361. Sentry.init({
  362. dsn: "${params.dsn.public}",
  363. integrations: [Sentry.browserTracingIntegration()],
  364. tracePropagationTargets: ["https://myproject.org", /^\/api\//],
  365. });
  366. `,
  367. },
  368. ],
  369. },
  370. ],
  371. verify: () => [
  372. {
  373. type: StepType.VERIFY,
  374. description: tct(
  375. 'Verify that performance monitoring is working correctly with our [link:automatic instrumentation] by simply using your React application.',
  376. {
  377. link: (
  378. <ExternalLink href="https://docs.sentry.io/platforms/javascript/guides/react/tracing/instrumentation/automatic-instrumentation/" />
  379. ),
  380. }
  381. ),
  382. },
  383. ],
  384. nextSteps: () => [],
  385. };
  386. const profilingOnboarding: OnboardingConfig = {
  387. ...onboarding,
  388. introduction: params => <MaybeBrowserProfilingBetaWarning {...params} />,
  389. };
  390. const docs: Docs = {
  391. onboarding,
  392. feedbackOnboardingNpm: feedbackOnboarding,
  393. replayOnboarding,
  394. performanceOnboarding,
  395. crashReportOnboarding,
  396. profilingOnboarding,
  397. featureFlagOnboarding,
  398. };
  399. export default docs;