javascript.tsx 22 KB

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