Browse Source

feat(onboarding): Add Solid onboarding (#72822)

Steven Eubank 8 months ago
parent
commit
fe275d7b6a

+ 3 - 2
static/app/components/onboarding/frameworkSuggestionModal.tsx

@@ -47,13 +47,14 @@ const topGoFrameworks: PlatformKey[] = [
 ];
 
 export const topJavascriptFrameworks: PlatformKey[] = [
-  'javascript-react',
   'javascript-nextjs',
+  'javascript-react',
   'javascript-vue',
   'javascript-angular',
+  'javascript-solid',
+  'javascript-remix',
   'javascript-svelte',
   'javascript-sveltekit',
-  'javascript-remix',
   'javascript-astro',
 ];
 

+ 4 - 0
static/app/components/onboarding/productSelection.tsx

@@ -127,6 +127,10 @@ export const platformProductAvailability = {
     ProductSolution.PERFORMANCE_MONITORING,
     ProductSolution.SESSION_REPLAY,
   ],
+  'javascript-solid': [
+    ProductSolution.PERFORMANCE_MONITORING,
+    ProductSolution.SESSION_REPLAY,
+  ],
   'javascript-svelte': [
     ProductSolution.PERFORMANCE_MONITORING,
     ProductSolution.SESSION_REPLAY,

+ 1 - 0
static/app/data/platformPickerCategories.tsx

@@ -40,6 +40,7 @@ const browser: Set<PlatformKey> = new Set([
   'javascript-nextjs',
   'javascript-react',
   'javascript-remix',
+  'javascript-solid',
   'javascript-svelte',
   'javascript-sveltekit',
   'javascript-vue',

+ 7 - 0
static/app/data/platforms.tsx

@@ -319,6 +319,13 @@ export const platforms: PlatformIntegration[] = [
     language: 'javascript',
     link: 'https://docs.sentry.io/platforms/javascript/guides/remix/',
   },
+  {
+    id: 'javascript-solid',
+    name: 'Solid',
+    type: 'framework',
+    language: 'javascript',
+    link: 'https://docs.sentry.io/platforms/javascript/guides/solid/',
+  },
   {
     id: 'javascript-svelte',
     name: 'Svelte',

+ 73 - 0
static/app/gettingStartedDocs/javascript/solid.spec.tsx

@@ -0,0 +1,73 @@
+import {renderWithOnboardingLayout} from 'sentry-test/onboarding/renderWithOnboardingLayout';
+import {screen} from 'sentry-test/reactTestingLibrary';
+import {textWithMarkupMatcher} from 'sentry-test/utils';
+
+import {ProductSolution} from 'sentry/components/onboarding/productSelection';
+
+import docs from './solid';
+
+describe('javascript-solid onboarding docs', function () {
+  it('renders onboarding docs correctly', () => {
+    renderWithOnboardingLayout(docs);
+
+    // Renders main headings
+    expect(screen.getByRole('heading', {name: 'Install'})).toBeInTheDocument();
+    expect(screen.getByRole('heading', {name: 'Configure SDK'})).toBeInTheDocument();
+    expect(screen.getByRole('heading', {name: 'Upload Source Maps'})).toBeInTheDocument();
+    expect(screen.getByRole('heading', {name: 'Verify'})).toBeInTheDocument();
+
+    // Includes import statement
+    expect(
+      screen.getByText(textWithMarkupMatcher(/import \* as Sentry from "@sentry\/solid"/))
+    ).toBeInTheDocument();
+  });
+
+  it('displays sample rates by default', () => {
+    renderWithOnboardingLayout(docs, {
+      selectedProducts: [
+        ProductSolution.ERROR_MONITORING,
+        ProductSolution.PERFORMANCE_MONITORING,
+        ProductSolution.SESSION_REPLAY,
+      ],
+    });
+
+    expect(
+      screen.queryByText(textWithMarkupMatcher(/tracesSampleRate/))
+    ).toBeInTheDocument();
+    expect(
+      screen.queryByText(textWithMarkupMatcher(/replaysSessionSampleRate/))
+    ).toBeInTheDocument();
+    expect(
+      screen.queryByText(textWithMarkupMatcher(/replaysOnErrorSampleRate/))
+    ).toBeInTheDocument();
+  });
+
+  it('enables performance setting the tracesSampleRate to 1', () => {
+    renderWithOnboardingLayout(docs, {
+      selectedProducts: [
+        ProductSolution.ERROR_MONITORING,
+        ProductSolution.PERFORMANCE_MONITORING,
+      ],
+    });
+
+    expect(
+      screen.getByText(textWithMarkupMatcher(/tracesSampleRate: 1\.0/))
+    ).toBeInTheDocument();
+  });
+
+  it('enables replay by setting replay samplerates', () => {
+    renderWithOnboardingLayout(docs, {
+      selectedProducts: [
+        ProductSolution.ERROR_MONITORING,
+        ProductSolution.SESSION_REPLAY,
+      ],
+    });
+
+    expect(
+      screen.getByText(textWithMarkupMatcher(/replaysSessionSampleRate: 0\.1/))
+    ).toBeInTheDocument();
+    expect(
+      screen.getByText(textWithMarkupMatcher(/replaysOnErrorSampleRate: 1\.0/))
+    ).toBeInTheDocument();
+  });
+});

+ 299 - 0
static/app/gettingStartedDocs/javascript/solid.tsx

@@ -0,0 +1,299 @@
+import crashReportCallout from 'sentry/components/onboarding/gettingStartedDoc/feedback/crashReportCallout';
+import widgetCallout from 'sentry/components/onboarding/gettingStartedDoc/feedback/widgetCallout';
+import TracePropagationMessage from 'sentry/components/onboarding/gettingStartedDoc/replay/tracePropagationMessage';
+import {StepType} from 'sentry/components/onboarding/gettingStartedDoc/step';
+import type {
+  Docs,
+  DocsParams,
+  OnboardingConfig,
+} from 'sentry/components/onboarding/gettingStartedDoc/types';
+import {getUploadSourceMapsStep} from 'sentry/components/onboarding/gettingStartedDoc/utils';
+import {
+  getCrashReportJavaScriptInstallStep,
+  getCrashReportModalConfigDescription,
+  getCrashReportModalIntroduction,
+  getFeedbackConfigOptions,
+  getFeedbackConfigureDescription,
+} from 'sentry/components/onboarding/gettingStartedDoc/utils/feedbackOnboarding';
+import {getJSMetricsOnboarding} from 'sentry/components/onboarding/gettingStartedDoc/utils/metricsOnboarding';
+import {
+  getReplayConfigOptions,
+  getReplayConfigureDescription,
+} from 'sentry/components/onboarding/gettingStartedDoc/utils/replayOnboarding';
+import {t, tct} from 'sentry/locale';
+
+type Params = DocsParams;
+
+const getSdkSetupSnippet = (params: Params) => `
+import * as Sentry from "@sentry/solid";
+import { render } from "solid-js/web";
+import App from "./app";
+
+Sentry.init({
+  dsn: "${params.dsn}",
+  integrations: [${
+    params.isPerformanceSelected
+      ? `
+        Sentry.browserTracingIntegration(),`
+      : ''
+  }${
+    params.isFeedbackSelected
+      ? `
+        Sentry.feedbackIntegration({
+// Additional SDK configuration goes in here, for example:
+colorScheme: "system",
+${getFeedbackConfigOptions(params.feedbackOptions)}}),`
+      : ''
+  }${
+    params.isReplaySelected
+      ? `
+        Sentry.replayIntegration(${getReplayConfigOptions(params.replayOptions)}),`
+      : ''
+  }
+],${
+  params.isPerformanceSelected
+    ? `
+      // Performance Monitoring
+      tracesSampleRate: 1.0, //  Capture 100% of the transactions
+      // Set 'tracePropagationTargets' to control for which URLs distributed tracing should be enabled
+      tracePropagationTargets: ["localhost", /^https:\\/\\/yourserver\\.io\\/api/],`
+    : ''
+}${
+  params.isReplaySelected
+    ? `
+      // Session Replay
+      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.
+      replaysOnErrorSampleRate: 1.0, // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur.`
+    : ''
+}
+});
+
+const app = document.getElementById("app");
+
+if (!app) throw new Error("No #app element found in the DOM.");
+
+render(() => <App />, app);
+`;
+
+const getVerifySolidSnippet = () => `
+<button
+  type="button"
+  onClick={() => {
+    throw new Error("Sentry Frontend Error");
+  }}
+>
+  Throw error
+</button>`;
+
+const getInstallConfig = () => [
+  {
+    language: 'bash',
+    code: [
+      {
+        label: 'npm',
+        value: 'npm',
+        language: 'bash',
+        code: 'npm install --save @sentry/solid',
+      },
+      {
+        label: 'yarn',
+        value: 'yarn',
+        language: 'bash',
+        code: 'yarn add @sentry/solid',
+      },
+    ],
+  },
+];
+
+const onboarding: OnboardingConfig = {
+  install: () => [
+    {
+      type: StepType.INSTALL,
+      description: tct(
+        'Add the Sentry SDK as a dependency using [codeNpm:npm] or [codeYarn:yarn]:',
+        {
+          codeYarn: <code />,
+          codeNpm: <code />,
+        }
+      ),
+      configurations: getInstallConfig(),
+    },
+  ],
+  configure: (params: Params) => [
+    {
+      type: StepType.CONFIGURE,
+      description: tct(
+        "Initialize Sentry as early as possible in your application's lifecycle, usually your solid app's entry point ([code:main.ts/js]):",
+        {code: <code />}
+      ),
+      configurations: [
+        {
+          code: [
+            {
+              label: 'JavaScript',
+              value: 'javascript',
+              language: 'javascript',
+              code: getSdkSetupSnippet(params),
+            },
+          ],
+        },
+      ],
+    },
+    getUploadSourceMapsStep({
+      guideLink: 'https://docs.sentry.io/platforms/javascript/guides/solid/sourcemaps/',
+    }),
+  ],
+  verify: () => [
+    {
+      type: StepType.VERIFY,
+      description: t(
+        "This snippet contains an intentional error and can be used as a test to make sure that everything's working as expected."
+      ),
+      configurations: [
+        {
+          code: [
+            {
+              label: 'JavaScript',
+              value: 'javascript',
+              language: 'javascript',
+              code: getVerifySolidSnippet(),
+            },
+          ],
+        },
+      ],
+    },
+  ],
+  nextSteps: () => [
+    {
+      id: 'solid-features',
+      name: t('Solid Features'),
+      description: t('Learn about our first class integration with the Solid framework.'),
+      link: 'https://docs.sentry.io/platforms/javascript/guides/solid/features/',
+    },
+    {
+      id: 'performance-monitoring',
+      name: t('Performance Monitoring'),
+      description: t(
+        'Track down transactions to connect the dots between 10-second page loads and poor-performing API calls or slow database queries.'
+      ),
+      link: 'https://docs.sentry.io/platforms/javascript/guides/solid/performance/',
+    },
+    {
+      id: 'session-replay',
+      name: t('Session Replay'),
+      description: t(
+        'Get to the root cause of an error or latency issue faster by seeing all the technical details related to that issue in one visual replay on your web application.'
+      ),
+      link: 'https://docs.sentry.io/platforms/javascript/guides/solid/session-replay/',
+    },
+  ],
+};
+
+const replayOnboarding: OnboardingConfig = {
+  install: () => [
+    {
+      type: StepType.INSTALL,
+      description: tct(
+        '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.',
+        {
+          code: <code />,
+        }
+      ),
+      configurations: getInstallConfig(),
+    },
+  ],
+  configure: (params: Params) => [
+    {
+      type: StepType.CONFIGURE,
+      description: getReplayConfigureDescription({
+        link: 'https://docs.sentry.io/platforms/javascript/guides/solid/session-replay/',
+      }),
+      configurations: [
+        {
+          code: [
+            {
+              label: 'JavaScript',
+              value: 'javascript',
+              language: 'javascript',
+              code: getSdkSetupSnippet(params),
+            },
+          ],
+          additionalInfo: <TracePropagationMessage />,
+        },
+      ],
+    },
+  ],
+  verify: () => [],
+  nextSteps: () => [],
+};
+
+const feedbackOnboarding: OnboardingConfig = {
+  install: () => [
+    {
+      type: StepType.INSTALL,
+      description: tct(
+        '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.',
+        {
+          code: <code />,
+        }
+      ),
+      configurations: getInstallConfig(),
+    },
+  ],
+  configure: (params: Params) => [
+    {
+      type: StepType.CONFIGURE,
+      description: getFeedbackConfigureDescription({
+        linkConfig:
+          'https://docs.sentry.io/platforms/javascript/guides/solid/user-feedback/configuration/',
+        linkButton:
+          'https://docs.sentry.io/platforms/javascript/guides/solid/user-feedback/configuration/#bring-your-own-button',
+      }),
+      configurations: [
+        {
+          code: [
+            {
+              label: 'JavaScript',
+              value: 'javascript',
+              language: 'javascript',
+              code: getSdkSetupSnippet(params),
+            },
+          ],
+        },
+      ],
+      additionalInfo: crashReportCallout({
+        link: 'https://docs.sentry.io/platforms/javascript/guides/solid/user-feedback/#crash-report-modal',
+      }),
+    },
+  ],
+  verify: () => [],
+  nextSteps: () => [],
+};
+
+const crashReportOnboarding: OnboardingConfig = {
+  introduction: () => getCrashReportModalIntroduction(),
+  install: (params: Params) => getCrashReportJavaScriptInstallStep(params),
+  configure: () => [
+    {
+      type: StepType.CONFIGURE,
+      description: getCrashReportModalConfigDescription({
+        link: 'https://docs.sentry.io/platforms/javascript/guides/solid/user-feedback/configuration/#crash-report-modal',
+      }),
+      additionalInfo: widgetCallout({
+        link: 'https://docs.sentry.io/platforms/javascript/guides/solid/user-feedback/#user-feedback-widget',
+      }),
+    },
+  ],
+  verify: () => [],
+  nextSteps: () => [],
+};
+
+const docs: Docs = {
+  onboarding,
+  feedbackOnboardingNpm: feedbackOnboarding,
+  replayOnboardingNpm: replayOnboarding,
+  customMetricsOnboarding: getJSMetricsOnboarding({getInstallConfig}),
+  crashReportOnboarding,
+};
+
+export default docs;

+ 1 - 0
static/app/types/project.tsx

@@ -211,6 +211,7 @@ export type PlatformKey =
   | 'javascript-nextjs'
   | 'javascript-react'
   | 'javascript-remix'
+  | 'javascript-solid'
   | 'javascript-svelte'
   | 'javascript-sveltekit'
   | 'javascript-vue'