solidstart.tsx 16 KB

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