javascript.tsx 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  1. import {css} from '@emotion/react';
  2. import {IntegrationOptions} from 'sentry/components/events/featureFlags/utils';
  3. import ExternalLink from 'sentry/components/links/externalLink';
  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. BasePlatformOptions,
  10. Docs,
  11. DocsParams,
  12. OnboardingConfig,
  13. } from 'sentry/components/onboarding/gettingStartedDoc/types';
  14. import {getUploadSourceMapsStep} from 'sentry/components/onboarding/gettingStartedDoc/utils';
  15. import {
  16. getCrashReportJavaScriptInstallStep,
  17. getCrashReportModalConfigDescription,
  18. getCrashReportModalIntroduction,
  19. getFeedbackConfigOptions,
  20. getFeedbackConfigureDescription,
  21. } from 'sentry/components/onboarding/gettingStartedDoc/utils/feedbackOnboarding';
  22. import {getJSMetricsOnboarding} from 'sentry/components/onboarding/gettingStartedDoc/utils/metricsOnboarding';
  23. import {
  24. getProfilingDocumentHeaderConfigurationStep,
  25. MaybeBrowserProfilingBetaWarning,
  26. } from 'sentry/components/onboarding/gettingStartedDoc/utils/profilingOnboarding';
  27. import {
  28. getReplayConfigOptions,
  29. getReplayConfigureDescription,
  30. getReplayVerifyStep,
  31. } from 'sentry/components/onboarding/gettingStartedDoc/utils/replayOnboarding';
  32. import replayOnboardingJsLoader from 'sentry/gettingStartedDocs/javascript/jsLoader/jsLoader';
  33. import {t, tct} from 'sentry/locale';
  34. import {space} from 'sentry/styles/space';
  35. import {trackAnalytics} from 'sentry/utils/analytics';
  36. import TextBlock from 'sentry/views/settings/components/text/textBlock';
  37. import {updateDynamicSdkLoaderOptions} from './jsLoader/updateDynamicSdkLoaderOptions';
  38. export enum InstallationMode {
  39. AUTO = 'auto',
  40. MANUAL = 'manual',
  41. }
  42. const platformOptions = {
  43. installationMode: {
  44. label: t('Installation Mode'),
  45. items: [
  46. {
  47. label: t('Loader Script'),
  48. value: InstallationMode.AUTO,
  49. },
  50. {
  51. label: t('Npm/Yarn'),
  52. value: InstallationMode.MANUAL,
  53. },
  54. ],
  55. defaultValue: InstallationMode.AUTO,
  56. },
  57. } satisfies BasePlatformOptions;
  58. type PlatformOptions = typeof platformOptions;
  59. type Params = DocsParams<PlatformOptions>;
  60. type FlagOptions = {
  61. importStatement: string; // feature flag SDK import
  62. integration: string; // what's in the integrations array
  63. sdkInit: string; // code to register with feature flag SDK
  64. };
  65. const FLAG_OPTIONS: Record<IntegrationOptions, FlagOptions> = {
  66. [IntegrationOptions.LAUNCHDARKLY]: {
  67. importStatement: `import * as LaunchDarkly from 'launchdarkly-js-client-sdk';`,
  68. integration: 'launchDarklyIntegration()',
  69. sdkInit: `const ldClient = LaunchDarkly.initialize(
  70. 'my-client-ID',
  71. {kind: 'user', key: 'my-user-context-key'},
  72. {inspectors: [Sentry.buildLaunchDarklyFlagUsedHandler()]}
  73. );
  74. // Evaluates a flag
  75. const flagVal = ldClient.variation('my-flag', false);`,
  76. },
  77. [IntegrationOptions.OPENFEATURE]: {
  78. importStatement: `import { OpenFeature } from '@openfeature/web-sdk';`,
  79. integration: 'openFeatureIntegration()',
  80. sdkInit: `const client = OpenFeature.getClient();
  81. client.addHooks(new Sentry.OpenFeatureIntegrationHook());
  82. // Evaluating flags will record the result on the Sentry client.
  83. const result = client.getBooleanValue('my-flag', false);`,
  84. },
  85. };
  86. const isAutoInstall = (params: Params) =>
  87. params.platformOptions.installationMode === InstallationMode.AUTO;
  88. const getSdkSetupSnippet = (params: Params) => `
  89. import * as Sentry from "@sentry/browser";
  90. Sentry.init({
  91. dsn: "${params.dsn.public}",
  92. integrations: [${
  93. params.isPerformanceSelected
  94. ? `
  95. Sentry.browserTracingIntegration(),`
  96. : ''
  97. }${
  98. params.isProfilingSelected
  99. ? `
  100. Sentry.browserProfilingIntegration(),`
  101. : ''
  102. }${
  103. params.isFeedbackSelected
  104. ? `
  105. Sentry.feedbackIntegration({
  106. // Additional SDK configuration goes in here, for example:
  107. colorScheme: "system",
  108. ${getFeedbackConfigOptions(params.feedbackOptions)}}),`
  109. : ''
  110. }${
  111. params.isReplaySelected
  112. ? `
  113. Sentry.replayIntegration(${getReplayConfigOptions(params.replayOptions)}),`
  114. : ''
  115. }
  116. ],${
  117. params.isPerformanceSelected
  118. ? `
  119. // Tracing
  120. tracesSampleRate: 1.0, // Capture 100% of the transactions
  121. // Set 'tracePropagationTargets' to control for which URLs distributed tracing should be enabled
  122. tracePropagationTargets: ["localhost", /^https:\\/\\/yourserver\\.io\\/api/],`
  123. : ''
  124. }${
  125. params.isReplaySelected
  126. ? `
  127. // Session Replay
  128. 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.
  129. replaysOnErrorSampleRate: 1.0, // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur.`
  130. : ''
  131. }${
  132. params.isProfilingSelected
  133. ? `
  134. // Set profilesSampleRate to 1.0 to profile every transaction.
  135. // Since profilesSampleRate is relative to tracesSampleRate,
  136. // the final profiling rate can be computed as tracesSampleRate * profilesSampleRate
  137. // For example, a tracesSampleRate of 0.5 and profilesSampleRate of 0.5 would
  138. // results in 25% of transactions being profiled (0.5*0.5=0.25)
  139. profilesSampleRate: 1.0,`
  140. : ''
  141. }
  142. });
  143. `;
  144. const getVerifyJSSnippet = () => `
  145. myUndefinedFunction();`;
  146. const getInstallConfig = () => [
  147. {
  148. language: 'bash',
  149. code: [
  150. {
  151. label: 'npm',
  152. value: 'npm',
  153. language: 'bash',
  154. code: 'npm install --save @sentry/browser',
  155. },
  156. {
  157. label: 'yarn',
  158. value: 'yarn',
  159. language: 'bash',
  160. code: 'yarn add @sentry/browser',
  161. },
  162. ],
  163. },
  164. ];
  165. const getVerifyConfig = () => [
  166. {
  167. type: StepType.VERIFY,
  168. description: t(
  169. "This snippet contains an intentional error and can be used as a test to make sure that everything's working as expected."
  170. ),
  171. configurations: [
  172. {
  173. code: [
  174. {
  175. label: 'Javascript',
  176. value: 'javascript',
  177. language: 'javascript',
  178. code: getVerifyJSSnippet(),
  179. },
  180. ],
  181. },
  182. ],
  183. },
  184. ];
  185. const loaderScriptOnboarding: OnboardingConfig<PlatformOptions> = {
  186. introduction: () =>
  187. tct('In this quick guide you’ll use our [strong: Loader Script] to set up:', {
  188. strong: <strong />,
  189. }),
  190. install: params => [
  191. {
  192. type: StepType.INSTALL,
  193. description: t('Add this script tag to the top of the page:'),
  194. configurations: [
  195. {
  196. language: 'html',
  197. code: [
  198. {
  199. label: 'HTML',
  200. value: 'html',
  201. language: 'html',
  202. code: `
  203. <script
  204. src="${params.dsn.cdn}"
  205. crossorigin="anonymous"
  206. ></script>`,
  207. },
  208. ],
  209. },
  210. ],
  211. },
  212. ],
  213. configure: params => [
  214. {
  215. title: t('Configure SDK (Optional)'),
  216. description: t(
  217. "Initialize Sentry as early as possible in your application's lifecycle."
  218. ),
  219. collapsible: true,
  220. configurations: [
  221. {
  222. language: 'html',
  223. code: [
  224. {
  225. label: 'HTML',
  226. value: 'html',
  227. language: 'html',
  228. code: `
  229. <script>
  230. Sentry.onLoad(function() {
  231. Sentry.init({${
  232. !(params.isPerformanceSelected || params.isReplaySelected)
  233. ? `
  234. // You can add any additional configuration here`
  235. : ''
  236. }${
  237. params.isPerformanceSelected
  238. ? `
  239. // Tracing
  240. tracesSampleRate: 1.0, // Capture 100% of the transactions`
  241. : ''
  242. }${
  243. params.isReplaySelected
  244. ? `
  245. // Session Replay
  246. 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.
  247. replaysOnErrorSampleRate: 1.0, // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur.`
  248. : ''
  249. }
  250. });
  251. });
  252. </script>`,
  253. },
  254. ],
  255. },
  256. ],
  257. onOptionalToggleClick: showOptionalConfig => {
  258. if (showOptionalConfig) {
  259. trackAnalytics('onboarding.js_loader_npm_docs_optional_shown', {
  260. organization: params.organization,
  261. platform: params.platformKey,
  262. project_id: params.projectId,
  263. });
  264. }
  265. },
  266. },
  267. ],
  268. verify: getVerifyConfig,
  269. nextSteps: () => [
  270. {
  271. id: 'source-maps',
  272. name: t('Source Maps'),
  273. description: t('Learn how to enable readable stack traces in your Sentry errors.'),
  274. link: 'https://docs.sentry.io/platforms/javascript/sourcemaps/',
  275. },
  276. ],
  277. onPageLoad: params => {
  278. return () => {
  279. trackAnalytics('onboarding.setup_loader_docs_rendered', {
  280. organization: params.organization,
  281. platform: params.platformKey,
  282. project_id: params.projectId,
  283. });
  284. };
  285. },
  286. onPlatformOptionsChange: params => {
  287. return () => {
  288. trackAnalytics('onboarding.js_loader_npm_docs_shown', {
  289. organization: params.organization,
  290. platform: params.platformKey,
  291. project_id: params.projectId,
  292. });
  293. };
  294. },
  295. onProductSelectionChange: params => {
  296. return products => {
  297. updateDynamicSdkLoaderOptions({
  298. orgSlug: params.organization.slug,
  299. projectSlug: params.projectSlug,
  300. products,
  301. projectKey: params.projectKeyId,
  302. api: params.api,
  303. });
  304. };
  305. },
  306. onProductSelectionLoad: params => {
  307. return products => {
  308. updateDynamicSdkLoaderOptions({
  309. orgSlug: params.organization.slug,
  310. projectSlug: params.projectSlug,
  311. products,
  312. projectKey: params.projectKeyId,
  313. api: params.api,
  314. });
  315. };
  316. },
  317. };
  318. const packageManagerOnboarding: OnboardingConfig<PlatformOptions> = {
  319. introduction: () =>
  320. tct('In this quick guide you’ll use [strong:npm] or [strong:yarn] to set up:', {
  321. strong: <strong />,
  322. }),
  323. install: () => [
  324. {
  325. type: StepType.INSTALL,
  326. description: t(
  327. 'Sentry captures data by using an SDK within your application’s runtime.'
  328. ),
  329. configurations: getInstallConfig(),
  330. },
  331. ],
  332. configure: params => [
  333. {
  334. type: StepType.CONFIGURE,
  335. description: t(
  336. "Initialize Sentry as early as possible in your application's lifecycle."
  337. ),
  338. configurations: [
  339. {
  340. code: [
  341. {
  342. label: 'JavaScript',
  343. value: 'javascript',
  344. language: 'javascript',
  345. code: getSdkSetupSnippet(params),
  346. },
  347. ],
  348. },
  349. ...(params.isProfilingSelected
  350. ? [getProfilingDocumentHeaderConfigurationStep()]
  351. : []),
  352. ],
  353. },
  354. getUploadSourceMapsStep({
  355. guideLink: 'https://docs.sentry.io/platforms/javascript/sourcemaps/',
  356. ...params,
  357. }),
  358. ],
  359. verify: getVerifyConfig,
  360. nextSteps: () => [],
  361. onPageLoad: params => {
  362. return () => {
  363. trackAnalytics('onboarding.js_loader_npm_docs_shown', {
  364. organization: params.organization,
  365. platform: params.platformKey,
  366. project_id: params.projectId,
  367. });
  368. };
  369. },
  370. onPlatformOptionsChange: params => {
  371. return () => {
  372. trackAnalytics('onboarding.setup_loader_docs_rendered', {
  373. organization: params.organization,
  374. platform: params.platformKey,
  375. project_id: params.projectId,
  376. });
  377. };
  378. },
  379. };
  380. const onboarding: OnboardingConfig<PlatformOptions> = {
  381. introduction: params => (
  382. <div
  383. css={css`
  384. display: flex;
  385. flex-direction: column;
  386. gap: ${space(1)};
  387. `}
  388. >
  389. <MaybeBrowserProfilingBetaWarning {...params} />
  390. <TextBlock noMargin>
  391. {isAutoInstall(params)
  392. ? loaderScriptOnboarding.introduction?.(params)
  393. : packageManagerOnboarding.introduction?.(params)}
  394. </TextBlock>
  395. </div>
  396. ),
  397. install: params =>
  398. isAutoInstall(params)
  399. ? loaderScriptOnboarding.install(params)
  400. : packageManagerOnboarding.install(params),
  401. configure: (params: Params) =>
  402. isAutoInstall(params)
  403. ? loaderScriptOnboarding.configure(params)
  404. : packageManagerOnboarding.configure(params),
  405. verify: params =>
  406. isAutoInstall(params)
  407. ? loaderScriptOnboarding.verify(params)
  408. : packageManagerOnboarding.verify(params),
  409. nextSteps: params =>
  410. isAutoInstall(params)
  411. ? loaderScriptOnboarding.nextSteps?.(params)
  412. : packageManagerOnboarding.nextSteps?.(params),
  413. onPageLoad: params =>
  414. isAutoInstall(params)
  415. ? loaderScriptOnboarding.onPageLoad?.(params)
  416. : packageManagerOnboarding.onPageLoad?.(params),
  417. onProductSelectionChange: params =>
  418. isAutoInstall(params)
  419. ? loaderScriptOnboarding.onProductSelectionChange?.(params)
  420. : packageManagerOnboarding.onProductSelectionChange?.(params),
  421. onPlatformOptionsChange: params =>
  422. isAutoInstall(params)
  423. ? loaderScriptOnboarding.onPlatformOptionsChange?.(params)
  424. : packageManagerOnboarding.onPlatformOptionsChange?.(params),
  425. onProductSelectionLoad: params =>
  426. isAutoInstall(params)
  427. ? loaderScriptOnboarding.onProductSelectionLoad?.(params)
  428. : packageManagerOnboarding.onProductSelectionLoad?.(params),
  429. };
  430. const replayOnboarding: OnboardingConfig<PlatformOptions> = {
  431. install: () => [
  432. {
  433. type: StepType.INSTALL,
  434. description: tct(
  435. 'For the Session Replay to work, you must have the Sentry browser SDK package, or an equivalent framework SDK (e.g. [code:@sentry/react]) installed, minimum version 7.27.0.',
  436. {
  437. code: <code />,
  438. }
  439. ),
  440. configurations: getInstallConfig(),
  441. },
  442. ],
  443. configure: (params: Params) => [
  444. {
  445. type: StepType.CONFIGURE,
  446. description: getReplayConfigureDescription({
  447. link: 'https://docs.sentry.io/platforms/javascript/session-replay/',
  448. }),
  449. configurations: [
  450. {
  451. code: [
  452. {
  453. label: 'JavaScript',
  454. value: 'javascript',
  455. language: 'javascript',
  456. code: getSdkSetupSnippet(params),
  457. },
  458. ],
  459. },
  460. ],
  461. additionalInfo: <TracePropagationMessage />,
  462. },
  463. ],
  464. verify: getReplayVerifyStep(),
  465. nextSteps: () => [],
  466. };
  467. const feedbackOnboarding: OnboardingConfig<PlatformOptions> = {
  468. install: () => [
  469. {
  470. type: StepType.INSTALL,
  471. description: tct(
  472. '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.',
  473. {
  474. code: <code />,
  475. }
  476. ),
  477. configurations: getInstallConfig(),
  478. },
  479. ],
  480. configure: (params: Params) => [
  481. {
  482. type: StepType.CONFIGURE,
  483. description: getFeedbackConfigureDescription({
  484. linkConfig:
  485. 'https://docs.sentry.io/platforms/javascript/user-feedback/configuration/',
  486. linkButton:
  487. 'https://docs.sentry.io/platforms/javascript/user-feedback/configuration/#bring-your-own-button',
  488. }),
  489. configurations: [
  490. {
  491. code: [
  492. {
  493. label: 'JavaScript',
  494. value: 'javascript',
  495. language: 'javascript',
  496. code: getSdkSetupSnippet(params),
  497. },
  498. ],
  499. },
  500. ],
  501. additionalInfo: crashReportCallout({
  502. link: 'https://docs.sentry.io/platforms/javascript/user-feedback/#crash-report-modal',
  503. }),
  504. },
  505. ],
  506. verify: () => [],
  507. nextSteps: () => [],
  508. };
  509. const crashReportOnboarding: OnboardingConfig<PlatformOptions> = {
  510. introduction: () => getCrashReportModalIntroduction(),
  511. install: (params: Params) => getCrashReportJavaScriptInstallStep(params),
  512. configure: () => [
  513. {
  514. type: StepType.CONFIGURE,
  515. description: getCrashReportModalConfigDescription({
  516. link: 'https://docs.sentry.io/platforms/javascript/user-feedback/configuration/#crash-report-modal',
  517. }),
  518. additionalInfo: widgetCallout({
  519. link: 'https://docs.sentry.io/platforms/javascript/user-feedback/#user-feedback-widget',
  520. }),
  521. },
  522. ],
  523. verify: () => [],
  524. nextSteps: () => [],
  525. };
  526. const performanceOnboarding: OnboardingConfig<PlatformOptions> = {
  527. introduction: () =>
  528. t(
  529. "Adding Performance to your Browser JavaScript project is simple. Make sure you've got these basics down."
  530. ),
  531. install: () => [
  532. {
  533. type: StepType.INSTALL,
  534. description: tct(
  535. 'Install our JavaScript browser SDK using either [code:yarn] or [code:npm]:',
  536. {code: <code />}
  537. ),
  538. configurations: getInstallConfig(),
  539. },
  540. ],
  541. configure: params => [
  542. {
  543. type: StepType.CONFIGURE,
  544. description: t(
  545. "Configuration should happen as early as possible in your application's lifecycle."
  546. ),
  547. configurations: [
  548. {
  549. language: 'javascript',
  550. code: `
  551. import * as Sentry from "@sentry/browser";
  552. Sentry.init({
  553. dsn: "${params.dsn.public}",
  554. integrations: [Sentry.browserTracingIntegration()],
  555. // Set tracesSampleRate to 1.0 to capture 100%
  556. // of transactions for performance monitoring.
  557. // We recommend adjusting this value in production
  558. tracesSampleRate: 1.0,
  559. // Set \`tracePropagationTargets\` to control for which URLs distributed tracing should be enabled
  560. tracePropagationTargets: ["localhost", /^https:\/\/yourserver\.io\/api/],
  561. });
  562. `,
  563. additionalInfo: tct(
  564. '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 [linkSampleTransactions:sample transactions].',
  565. {
  566. code: <code />,
  567. linkTracingOptions: (
  568. <ExternalLink href="https://docs.sentry.io/platforms/javascript/configuration/options/#tracing-options" />
  569. ),
  570. linkTracesSampler: (
  571. <ExternalLink href="https://docs.sentry.io/platforms/javascript/configuration/sampling/" />
  572. ),
  573. linkSampleTransactions: (
  574. <ExternalLink href="https://docs.sentry.io/platforms/javascript/configuration/sampling/" />
  575. ),
  576. }
  577. ),
  578. },
  579. ],
  580. },
  581. ],
  582. verify: () => [
  583. {
  584. type: StepType.VERIFY,
  585. description: tct(
  586. 'Verify that performance monitoring is working correctly with our [link:automatic instrumentation] by simply using your JavaScript application.',
  587. {
  588. link: (
  589. <ExternalLink href="https://docs.sentry.io/platforms/javascript/tracing/instrumentation/automatic-instrumentation/" />
  590. ),
  591. }
  592. ),
  593. configurations: [
  594. {
  595. description: tct(
  596. 'You have the option to manually construct a transaction using [link:custom instrumentation].',
  597. {
  598. link: (
  599. <ExternalLink href="https://docs.sentry.io/platforms/javascript/tracing/instrumentation/custom-instrumentation/" />
  600. ),
  601. }
  602. ),
  603. language: 'javascript',
  604. code: `
  605. const transaction = Sentry.startTransaction({ name: "test-transaction" });
  606. const span = transaction.startChild({ op: "functionX" }); // This function returns a Span
  607. // exampleFunctionCall();
  608. span.finish(); // Remember that only finished spans will be sent with the transaction
  609. transaction.finish(); // Finishing the transaction will send it to Sentry`,
  610. },
  611. ],
  612. },
  613. ],
  614. nextSteps: () => [],
  615. };
  616. const profilingOnboarding: OnboardingConfig<PlatformOptions> = {
  617. ...onboarding,
  618. introduction: params => <MaybeBrowserProfilingBetaWarning {...params} />,
  619. };
  620. export const featureFlagOnboarding: OnboardingConfig = {
  621. install: () => [
  622. {
  623. type: StepType.INSTALL,
  624. description: tct(
  625. 'Install our JavaScript browser SDK using either [code:yarn] or [code:npm]:',
  626. {code: <code />}
  627. ),
  628. configurations: getInstallConfig(),
  629. },
  630. ],
  631. configure: ({featureFlagOptions = {integration: ''}, dsn}) => [
  632. {
  633. type: StepType.CONFIGURE,
  634. description: tct(
  635. 'Add [name] to your integrations list, and then register with your feature flag SDK.',
  636. {
  637. name: (
  638. <code>{`${FLAG_OPTIONS[featureFlagOptions.integration].integration}`}</code>
  639. ),
  640. }
  641. ),
  642. configurations: [
  643. {
  644. language: 'JavaScript',
  645. code: `
  646. import * as Sentry from '@sentry/browser';
  647. ${FLAG_OPTIONS[featureFlagOptions.integration].importStatement}
  648. // Register with Sentry
  649. Sentry.init({
  650. dsn: "${dsn.public}",
  651. integrations: [
  652. Sentry.${FLAG_OPTIONS[featureFlagOptions.integration].integration},
  653. ],
  654. });
  655. // Register with your feature flag SDK
  656. ${FLAG_OPTIONS[featureFlagOptions.integration].sdkInit}
  657. `,
  658. },
  659. ],
  660. },
  661. ],
  662. verify: () => [],
  663. nextSteps: () => [],
  664. };
  665. const docs: Docs<PlatformOptions> = {
  666. onboarding,
  667. feedbackOnboardingNpm: feedbackOnboarding,
  668. replayOnboarding,
  669. replayOnboardingJsLoader,
  670. performanceOnboarding,
  671. customMetricsOnboarding: getJSMetricsOnboarding({getInstallConfig}),
  672. crashReportOnboarding,
  673. platformOptions,
  674. profilingOnboarding,
  675. featureFlagOnboarding,
  676. };
  677. export default docs;