solidstart.tsx 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. import {Fragment} from 'react';
  2. import ExternalLink from 'sentry/components/links/externalLink';
  3. import crashReportCallout from 'sentry/components/onboarding/gettingStartedDoc/feedback/crashReportCallout';
  4. import widgetCallout from 'sentry/components/onboarding/gettingStartedDoc/feedback/widgetCallout';
  5. import TracePropagationMessage from 'sentry/components/onboarding/gettingStartedDoc/replay/tracePropagationMessage';
  6. import {StepType} from 'sentry/components/onboarding/gettingStartedDoc/step';
  7. import type {
  8. Docs,
  9. DocsParams,
  10. OnboardingConfig,
  11. } from 'sentry/components/onboarding/gettingStartedDoc/types';
  12. import {
  13. getCrashReportJavaScriptInstallStep,
  14. getCrashReportModalConfigDescription,
  15. getCrashReportModalIntroduction,
  16. getFeedbackConfigOptions,
  17. getFeedbackConfigureDescription,
  18. } from 'sentry/components/onboarding/gettingStartedDoc/utils/feedbackOnboarding';
  19. import {getJSMetricsOnboarding} from 'sentry/components/onboarding/gettingStartedDoc/utils/metricsOnboarding';
  20. import {
  21. getProfilingDocumentHeaderConfigurationStep,
  22. MaybeBrowserProfilingBetaWarning,
  23. } from 'sentry/components/onboarding/gettingStartedDoc/utils/profilingOnboarding';
  24. import {
  25. getReplayConfigOptions,
  26. getReplayConfigureDescription,
  27. getReplayVerifyStep,
  28. } from 'sentry/components/onboarding/gettingStartedDoc/utils/replayOnboarding';
  29. import {featureFlagOnboarding} from 'sentry/gettingStartedDocs/javascript/javascript';
  30. import {t, tct} from 'sentry/locale';
  31. type Params = DocsParams;
  32. const getSdkClientSetupSnippet = (params: Params) => `
  33. import * as Sentry from "@sentry/solidstart";
  34. ${params.isPerformanceSelected ? 'import { solidRouterBrowserTracingIntegration } from "@sentry/solidstart/solidrouter";' : ''}
  35. import { mount, StartClient } from "@solidjs/start/client";
  36. Sentry.init({
  37. dsn: "${params.dsn.public}",
  38. integrations: [${
  39. params.isPerformanceSelected
  40. ? `
  41. solidRouterBrowserTracingIntegration(),`
  42. : ''
  43. }${
  44. params.isProfilingSelected
  45. ? `
  46. Sentry.browserProfilingIntegration(),`
  47. : ''
  48. }${
  49. params.isFeedbackSelected
  50. ? `
  51. Sentry.feedbackIntegration({
  52. // Additional SDK configuration goes in here, for example:
  53. colorScheme: "system",
  54. ${getFeedbackConfigOptions(params.feedbackOptions)}}),`
  55. : ''
  56. }${
  57. params.isReplaySelected
  58. ? `
  59. Sentry.replayIntegration(${getReplayConfigOptions(params.replayOptions)}),`
  60. : ''
  61. }
  62. ],${
  63. params.isPerformanceSelected
  64. ? `
  65. // Performance Monitoring
  66. tracesSampleRate: 1.0, // Capture 100% of the transactions
  67. // Set 'tracePropagationTargets' to control for which URLs distributed tracing should be enabled
  68. tracePropagationTargets: ["localhost", /^https:\\/\\/yourserver\\.io\\/api/],`
  69. : ''
  70. }${
  71. params.isReplaySelected
  72. ? `
  73. // Session Replay
  74. 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.
  75. replaysOnErrorSampleRate: 1.0, // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur.`
  76. : ''
  77. }${
  78. params.isProfilingSelected
  79. ? `
  80. // Set profilesSampleRate to 1.0 to profile every transaction.
  81. // Since profilesSampleRate is relative to tracesSampleRate,
  82. // the final profiling rate can be computed as tracesSampleRate * profilesSampleRate
  83. // For example, a tracesSampleRate of 0.5 and profilesSampleRate of 0.5 would
  84. // results in 25% of transactions being profiled (0.5*0.5=0.25)
  85. profilesSampleRate: 1.0,`
  86. : ''
  87. }
  88. });
  89. mount(() => <StartClient />, document.getElementById("app"));
  90. `;
  91. const getSdkServerSetupSnippet = (params: Params) => `
  92. import * as Sentry from "@sentry/solidstart";
  93. Sentry.init({
  94. dsn: "${params.dsn.public}",
  95. ${
  96. params.isPerformanceSelected
  97. ? `
  98. // Performance Monitoring
  99. tracesSampleRate: 1.0, // Capture 100% of the transactions
  100. // Set 'tracePropagationTargets' to control for which URLs distributed tracing should be enabled
  101. tracePropagationTargets: ["localhost", /^https:\\/\\/yourserver\\.io\\/api/],`
  102. : ''
  103. }${
  104. params.isProfilingSelected
  105. ? `
  106. // Set profilesSampleRate to 1.0 to profile every transaction.
  107. // Since profilesSampleRate is relative to tracesSampleRate,
  108. // the final profiling rate can be computed as tracesSampleRate * profilesSampleRate
  109. // For example, a tracesSampleRate of 0.5 and profilesSampleRate of 0.5 would
  110. // results in 25% of transactions being profiled (0.5*0.5=0.25)
  111. profilesSampleRate: 1.0,`
  112. : ''
  113. }
  114. });
  115. `;
  116. const getSdkMiddlewareSetup = () => `
  117. import { sentryBeforeResponseMiddleware } from '@sentry/solidstart/middleware';
  118. import { createMiddleware } from '@solidjs/start/middleware';
  119. export default createMiddleware({
  120. onBeforeResponse: [
  121. sentryBeforeResponseMiddleware(),
  122. // Add your other middleware handlers after \`sentryBeforeResponseMiddleware\`
  123. ],
  124. });
  125. `;
  126. const getSdkMiddlewareLinkSetup = () => `
  127. import { defineConfig } from "@solidjs/start/config";
  128. export default defineConfig({
  129. middleware: "./src/middleware.ts"
  130. // Other configuration options
  131. // ...
  132. });
  133. `;
  134. const getSdkRouterWrappingSetup = () => `
  135. import { Router } from "@solidjs/router";
  136. import { FileRoutes } from "@solidjs/start/router";
  137. import { withSentryRouterRouting } from "@sentry/solidstart/solidrouter";
  138. const SentryRouter = withSentryRouterRouting(Router);
  139. export default function App() {
  140. return (
  141. <SentryRouter>
  142. <FileRoutes />
  143. </SentryRouter>
  144. );
  145. }
  146. `;
  147. const getSdkRun = () => `
  148. {
  149. "scripts": {
  150. "start": "NODE_OPTIONS='--import ./public/instrument.server.mjs' vinxi start"
  151. }
  152. }
  153. `;
  154. const getVerifySnippet = () => `
  155. <button
  156. type="button"
  157. onClick={() => {
  158. throw new Error("Sentry Frontend Error");
  159. }}
  160. >
  161. Throw error
  162. </button>`;
  163. const getInstallConfig = () => [
  164. {
  165. language: 'bash',
  166. code: [
  167. {
  168. label: 'npm',
  169. value: 'npm',
  170. language: 'bash',
  171. code: 'npm install --save @sentry/solidstart',
  172. },
  173. {
  174. label: 'yarn',
  175. value: 'yarn',
  176. language: 'bash',
  177. code: 'yarn add @sentry/solidstart',
  178. },
  179. {
  180. label: 'pnpm',
  181. value: 'pnpm',
  182. language: 'bash',
  183. code: `pnpm add @sentry/solidstart`,
  184. },
  185. ],
  186. },
  187. ];
  188. const onboarding: OnboardingConfig = {
  189. introduction: params => (
  190. <Fragment>
  191. <MaybeBrowserProfilingBetaWarning {...params} />
  192. <p>
  193. {tct(
  194. 'In this quick guide you’ll use [strong:npm], [strong:yarn] or [strong:pnpm] to set up:',
  195. {
  196. strong: <strong />,
  197. }
  198. )}
  199. </p>
  200. </Fragment>
  201. ),
  202. install: () => [
  203. {
  204. type: StepType.INSTALL,
  205. description: tct(
  206. 'Add the Sentry SDK as a dependency using [code:npm], [code:yarn] or [code:pnpm]:',
  207. {
  208. code: <code />,
  209. }
  210. ),
  211. configurations: getInstallConfig(),
  212. },
  213. ],
  214. configure: (params: Params) => [
  215. {
  216. type: StepType.CONFIGURE,
  217. description: t(
  218. "Initialize Sentry as early as possible in your application's lifecycle."
  219. ),
  220. configurations: [
  221. {
  222. description: tct(
  223. 'For the client, initialize the Sentry SDK in your [code:src/entry-client.tsx] file',
  224. {code: <code />}
  225. ),
  226. code: [
  227. {
  228. label: 'TypeScript',
  229. // value and language are in JS to get consistent syntax highlighting
  230. // we aren't using any Typescript specific code in these snippets but
  231. // want a typescript ending.
  232. value: 'javascript',
  233. language: 'javascript',
  234. code: getSdkClientSetupSnippet(params),
  235. },
  236. ],
  237. },
  238. {
  239. description: tct(
  240. 'For the server, create an instrument file [code:instrument.server.mjs], initialize the Sentry SDK and deploy it alongside your application. For example by placing it in the [code:public] folder.',
  241. {code: <code />}
  242. ),
  243. code: [
  244. {
  245. label: 'JavaScript',
  246. value: 'javascript',
  247. language: 'javascript',
  248. code: getSdkServerSetupSnippet(params),
  249. },
  250. ],
  251. additionalInfo: tct(
  252. 'Note: Placing [code:instrument.server.mjs] inside the [code:public] folder makes it accessible to the outside world. Consider blocking requests to this file or finding a more appropriate location which your backend can access.',
  253. {code: <code />}
  254. ),
  255. },
  256. ...(params.isPerformanceSelected
  257. ? [
  258. {
  259. description: tct(
  260. 'Complete the setup by adding the Sentry [solidStartMiddlewareLink: middleware] to your [code:src/middleware.ts] file',
  261. {
  262. code: <code />,
  263. solidStartMiddlewareLink: (
  264. <ExternalLink href="https://docs.solidjs.com/solid-start/advanced/middleware" />
  265. ),
  266. }
  267. ),
  268. code: [
  269. {
  270. label: 'TypeScript',
  271. // value and language are in JS to get consistent syntax highlighting
  272. // we aren't using any Typescript specific code in these snippets but
  273. // want a typescript ending.
  274. value: 'javascript',
  275. language: 'javascript',
  276. code: getSdkMiddlewareSetup(),
  277. },
  278. ],
  279. },
  280. {
  281. description: tct('And including it in the [code:app.config.ts] file', {
  282. code: <code />,
  283. }),
  284. code: [
  285. {
  286. label: 'TypeScript',
  287. value: 'javascript',
  288. language: 'javascript',
  289. code: getSdkMiddlewareLinkSetup(),
  290. },
  291. ],
  292. },
  293. {
  294. description: tct(
  295. "If you're using [solidRouterLink:Solid Router], wrap your [code:Router] with [code:withSentryRouterRouting]. This creates a higher order component, which will enable Sentry to collect navigation spans.",
  296. {
  297. code: <code />,
  298. solidRouterLink: (
  299. <ExternalLink href="https://docs.solidjs.com/solid-router" />
  300. ),
  301. }
  302. ),
  303. code: [
  304. {
  305. label: 'TypeScript',
  306. value: 'typescript',
  307. language: 'typescript',
  308. code: getSdkRouterWrappingSetup(),
  309. },
  310. ],
  311. },
  312. ]
  313. : []),
  314. ...(params.isProfilingSelected
  315. ? [getProfilingDocumentHeaderConfigurationStep()]
  316. : []),
  317. {
  318. description: tct(
  319. 'Add an [code:--import] flag to the [code:NODE_OPTIONS] environment variable wherever you run your application to import [code:public/instrument.server.mjs]. For example, update your [code:scripts] entry in [code:package.json]',
  320. {
  321. code: <code />,
  322. }
  323. ),
  324. code: [
  325. {
  326. label: 'JSON',
  327. value: 'json',
  328. language: 'json',
  329. code: getSdkRun(),
  330. },
  331. ],
  332. },
  333. ],
  334. },
  335. {
  336. title: t('Upload Source Maps'),
  337. description: tct(
  338. 'To upload source maps to Sentry, follow the [link:instructions in our documentation].',
  339. {
  340. link: (
  341. <ExternalLink href="https://docs.sentry.io/platforms/javascript/guides/solidstart/#add-readable-stack-traces-to-errors" />
  342. ),
  343. }
  344. ),
  345. },
  346. ],
  347. verify: () => [
  348. {
  349. type: StepType.VERIFY,
  350. description: t(
  351. "This snippet contains an intentional error and can be used as a test to make sure that everything's working as expected."
  352. ),
  353. configurations: [
  354. {
  355. code: [
  356. {
  357. label: 'JavaScript',
  358. value: 'javascript',
  359. language: 'javascript',
  360. code: getVerifySnippet(),
  361. },
  362. ],
  363. },
  364. ],
  365. },
  366. ],
  367. nextSteps: () => [
  368. {
  369. id: 'solid-features',
  370. name: t('Solid Features'),
  371. description: t('Learn about our first class integration with the Solid framework.'),
  372. link: 'https://docs.sentry.io/platforms/javascript/guides/solid/features/',
  373. },
  374. ],
  375. };
  376. const replayOnboarding: OnboardingConfig = {
  377. install: () => [
  378. {
  379. type: StepType.INSTALL,
  380. description: tct(
  381. 'You need a minimum version 8.9.1 of [code:@sentry/solid] in order to use Session Replay. You do not need to install any additional packages.',
  382. {
  383. code: <code />,
  384. }
  385. ),
  386. configurations: getInstallConfig(),
  387. },
  388. ],
  389. configure: (params: Params) => [
  390. {
  391. type: StepType.CONFIGURE,
  392. description: getReplayConfigureDescription({
  393. link: 'https://docs.sentry.io/platforms/javascript/guides/solid/session-replay/',
  394. }),
  395. configurations: [
  396. {
  397. code: [
  398. {
  399. label: 'JavaScript',
  400. value: 'javascript',
  401. language: 'javascript',
  402. code: getSdkClientSetupSnippet(params),
  403. },
  404. ],
  405. additionalInfo: <TracePropagationMessage />,
  406. },
  407. ],
  408. },
  409. ],
  410. verify: getReplayVerifyStep(),
  411. nextSteps: () => [],
  412. };
  413. const feedbackOnboarding: OnboardingConfig = {
  414. install: () => [
  415. {
  416. type: StepType.INSTALL,
  417. description: tct(
  418. 'For the User Feedback integration to work, you must have the Sentry browser SDK package, or an equivalent framework SDK (e.g. [code:@sentry/solid]) installed, minimum version 7.85.0.',
  419. {
  420. code: <code />,
  421. }
  422. ),
  423. configurations: getInstallConfig(),
  424. },
  425. ],
  426. configure: (params: Params) => [
  427. {
  428. type: StepType.CONFIGURE,
  429. description: getFeedbackConfigureDescription({
  430. linkConfig:
  431. 'https://docs.sentry.io/platforms/javascript/guides/solid/user-feedback/configuration/',
  432. linkButton:
  433. 'https://docs.sentry.io/platforms/javascript/guides/solid/user-feedback/configuration/#bring-your-own-button',
  434. }),
  435. configurations: [
  436. {
  437. code: [
  438. {
  439. label: 'JavaScript',
  440. value: 'javascript',
  441. language: 'javascript',
  442. code: getSdkClientSetupSnippet(params),
  443. },
  444. ],
  445. },
  446. ],
  447. additionalInfo: crashReportCallout({
  448. link: 'https://docs.sentry.io/platforms/javascript/guides/solid/user-feedback/#crash-report-modal',
  449. }),
  450. },
  451. ],
  452. verify: () => [],
  453. nextSteps: () => [],
  454. };
  455. const crashReportOnboarding: OnboardingConfig = {
  456. introduction: () => getCrashReportModalIntroduction(),
  457. install: (params: Params) => getCrashReportJavaScriptInstallStep(params),
  458. configure: () => [
  459. {
  460. type: StepType.CONFIGURE,
  461. description: getCrashReportModalConfigDescription({
  462. link: 'https://docs.sentry.io/platforms/javascript/guides/solid/user-feedback/configuration/#crash-report-modal',
  463. }),
  464. additionalInfo: widgetCallout({
  465. link: 'https://docs.sentry.io/platforms/javascript/guides/solid/user-feedback/#user-feedback-widget',
  466. }),
  467. },
  468. ],
  469. verify: () => [],
  470. nextSteps: () => [],
  471. };
  472. const profilingOnboarding: OnboardingConfig = {
  473. ...onboarding,
  474. introduction: params => <MaybeBrowserProfilingBetaWarning {...params} />,
  475. };
  476. const docs: Docs = {
  477. onboarding,
  478. feedbackOnboardingNpm: feedbackOnboarding,
  479. replayOnboarding,
  480. customMetricsOnboarding: getJSMetricsOnboarding({getInstallConfig}),
  481. crashReportOnboarding,
  482. profilingOnboarding,
  483. featureFlagOnboarding: featureFlagOnboarding,
  484. };
  485. export default docs;