Browse Source

ref(replay onboarding): integrate react into onboarding docs (#61379)

This is the third step of our onboarding docs migration efforts.
Previously, we have done:

1. Move the replay onboarding docs out of the `sentry-docs` repo and
into the main `sentry` repo. We created a new set of files under
`gettingStartedDocs/replay-onboarding/` for each of the 13 platforms.
- See https://github.com/getsentry/sentry/issues/61001
3. Now we are trying to move away from having unique files for each of
the platforms specific to replay onboarding. We want to integrate with
existing onboarding docs (which exist for project install etc). But
before we could do this, we had to migrate all "old" onboarding docs
structures to the "new" structure. [The old structure was incompatible
with our goal of integrating replay onboarding]
- See https://github.com/getsentry/sentry/issues/61266

Now that all the onboarding doc structures are converted, the next step
is to start integrating replay onboarding configurations directly into
them. Relates to https://github.com/getsentry/sentry/issues/61267
Michelle Zhang 1 year ago
parent
commit
b57da2b636

+ 20 - 11
static/app/components/onboarding/gettingStartedDoc/onboardingLayout.tsx

@@ -7,7 +7,11 @@ import List from 'sentry/components/list';
 import ListItem from 'sentry/components/list/listItem';
 import {AuthTokenGeneratorProvider} from 'sentry/components/onboarding/gettingStartedDoc/authTokenGenerator';
 import {Step} from 'sentry/components/onboarding/gettingStartedDoc/step';
-import {Docs, DocsParams} from 'sentry/components/onboarding/gettingStartedDoc/types';
+import {
+  ConfigType,
+  Docs,
+  DocsParams,
+} from 'sentry/components/onboarding/gettingStartedDoc/types';
 import {useSourcePackageRegistries} from 'sentry/components/onboarding/gettingStartedDoc/useSourcePackageRegistries';
 import {
   PlatformOptionsControl,
@@ -34,6 +38,7 @@ export type OnboardingLayoutProps = {
   projectId: Project['id'];
   projectSlug: Project['slug'];
   activeProductSelection?: ProductSolution[];
+  configType?: ConfigType;
   newOrg?: boolean;
 };
 
@@ -47,6 +52,7 @@ export function OnboardingLayout({
   projectSlug,
   activeProductSelection = EMPTY_ARRAY,
   newOrg,
+  configType = 'onboarding',
 }: OnboardingLayoutProps) {
   const organization = useOrganization();
   const {isLoading: isLoadingRegistry, data: registryData} =
@@ -56,7 +62,7 @@ export function OnboardingLayout({
   const {platformOptions} = docsConfig;
 
   const {introduction, steps, nextSteps} = useMemo(() => {
-    const {onboarding} = docsConfig;
+    const doc = docsConfig[configType] ?? docsConfig.onboarding;
 
     const docParams: DocsParams<any> = {
       dsn,
@@ -78,13 +84,13 @@ export function OnboardingLayout({
     };
 
     return {
-      introduction: onboarding.introduction?.(docParams),
+      introduction: doc.introduction?.(docParams),
       steps: [
-        ...onboarding.install(docParams),
-        ...onboarding.configure(docParams),
-        ...onboarding.verify(docParams),
+        ...doc.install(docParams),
+        ...doc.configure(docParams),
+        ...doc.verify(docParams),
       ],
-      nextSteps: onboarding.nextSteps?.(docParams) || [],
+      nextSteps: doc.nextSteps?.(docParams) || [],
     };
   }, [
     activeProductSelection,
@@ -98,6 +104,7 @@ export function OnboardingLayout({
     projectSlug,
     registryData,
     selectedOptions,
+    configType,
   ]);
 
   return (
@@ -105,10 +112,12 @@ export function OnboardingLayout({
       <Wrapper>
         <Header>
           {introduction && <div>{introduction}</div>}
-          <ProductSelectionAvailabilityHook
-            organization={organization}
-            platform={platformKey}
-          />
+          {configType === 'onboarding' && (
+            <ProductSelectionAvailabilityHook
+              organization={organization}
+              platform={platformKey}
+            />
+          )}
           {platformOptions ? (
             <PlatformOptionsControl platformOptions={platformOptions} />
           ) : null}

+ 9 - 13
static/app/components/onboarding/gettingStartedDoc/sdkDocumentation.tsx

@@ -3,7 +3,7 @@ import {useEffect, useState} from 'react';
 import LoadingError from 'sentry/components/loadingError';
 import LoadingIndicator from 'sentry/components/loadingIndicator';
 import {OnboardingLayout} from 'sentry/components/onboarding/gettingStartedDoc/onboardingLayout';
-import {Docs} from 'sentry/components/onboarding/gettingStartedDoc/types';
+import {ConfigType, Docs} from 'sentry/components/onboarding/gettingStartedDoc/types';
 import {useSourcePackageRegistries} from 'sentry/components/onboarding/gettingStartedDoc/useSourcePackageRegistries';
 import {ProductSolution} from 'sentry/components/onboarding/productSelection';
 import type {
@@ -21,7 +21,7 @@ type SdkDocumentationProps = {
   platform: PlatformIntegration;
   projectId: Project['id'];
   projectSlug: Project['slug'];
-  isReplayOnboarding?: boolean;
+  configType?: ConfigType;
   newOrg?: boolean;
 };
 
@@ -50,7 +50,7 @@ export function SdkDocumentation({
   newOrg,
   organization,
   projectId,
-  isReplayOnboarding,
+  configType,
 }: SdkDocumentationProps) {
   const sourcePackageRegistries = useSourcePackageRegistries(organization);
 
@@ -99,22 +99,17 @@ export function SdkDocumentation({
 
   useEffect(() => {
     async function getGettingStartedDoc() {
-      const mod = isReplayOnboarding
-        ? await import(
-            /* webpackExclude: /.spec/ */
-            `sentry/gettingStartedDocs/replay-onboarding/${platformPath}`
-          )
-        : await import(
-            /* webpackExclude: /.spec/ */
-            `sentry/gettingStartedDocs/${platformPath}`
-          );
+      const mod = await import(
+        /* webpackExclude: /.spec/ */
+        `sentry/gettingStartedDocs/${platformPath}`
+      );
       setModule(mod);
     }
     getGettingStartedDoc();
     return () => {
       setModule(null);
     };
-  }, [platformPath, isReplayOnboarding]);
+  }, [platformPath]);
 
   if (!module || projectKeysIsLoading) {
     return <LoadingIndicator />;
@@ -151,6 +146,7 @@ export function SdkDocumentation({
       platformKey={platform.id}
       projectId={projectId}
       projectSlug={projectSlug}
+      configType={configType}
     />
   );
 }

+ 3 - 0
static/app/components/onboarding/gettingStartedDoc/types.ts

@@ -71,4 +71,7 @@ export interface OnboardingConfig<
 export interface Docs<PlatformOptions extends BasePlatformOptions = BasePlatformOptions> {
   onboarding: OnboardingConfig<PlatformOptions>;
   platformOptions?: PlatformOptions;
+  replayOnboarding?: OnboardingConfig<PlatformOptions>;
 }
+
+export type ConfigType = 'onboarding' | 'replayOnboarding';

+ 9 - 0
static/app/components/onboarding/gettingStartedDoc/utils.tsx

@@ -68,3 +68,12 @@ export function getUploadSourceMapsStep({
     ],
   };
 }
+
+export const getReplayConfigureDescription = ({link}: {link: string}) =>
+  tct(
+    'Add the following to your SDK config. There are several privacy and sampling options available, all of which can be set using the [code:integrations] constructor. Learn more about configuring Session Replay by reading the [link:configuration docs].',
+    {
+      code: <code />,
+      link: <ExternalLink href={link} />,
+    }
+  );

+ 4 - 2
static/app/components/replaysOnboarding/sidebar.tsx

@@ -219,6 +219,8 @@ function OnboardingContent({currentProject}: {currentProject: Project}) {
     );
   }
 
+  const migrated = ['javascript-react'];
+
   return (
     <Fragment>
       <IntroText>
@@ -227,14 +229,14 @@ function OnboardingContent({currentProject}: {currentProject: Project}) {
           {platform: currentPlatform?.name || currentProject.slug}
         )}
       </IntroText>
-      {newOnboarding ? (
+      {newOnboarding && migrated.includes(currentPlatform.id) ? (
         <SdkDocumentation
           platform={currentPlatform}
           organization={organization}
           projectSlug={currentProject.slug}
           projectId={currentProject.id}
           activeProductSelection={[]}
-          isReplayOnboarding
+          configType="replayOnboarding"
         />
       ) : (
         docKeys.map((docKey, index) => {

+ 71 - 26
static/app/gettingStartedDocs/javascript/react.tsx

@@ -4,7 +4,10 @@ import {
   DocsParams,
   OnboardingConfig,
 } from 'sentry/components/onboarding/gettingStartedDoc/types';
-import {getUploadSourceMapsStep} from 'sentry/components/onboarding/gettingStartedDoc/utils';
+import {
+  getReplayConfigureDescription,
+  getUploadSourceMapsStep,
+} from 'sentry/components/onboarding/gettingStartedDoc/utils';
 import {t, tct} from 'sentry/locale';
 
 type Params = DocsParams;
@@ -54,36 +57,38 @@ const getVerifyReactSnippet = () => `
 return <button onClick={() => methodDoesNotExist()}>Break the world</button>;
         `;
 
+const getInstallConfig = () => [
+  {
+    language: 'bash',
+    code: [
+      {
+        label: 'npm',
+        value: 'npm',
+        language: 'bash',
+        code: 'npm install --save @sentry/react',
+      },
+      {
+        label: 'yarn',
+        value: 'yarn',
+        language: 'bash',
+        code: 'yarn add @sentry/react',
+      },
+    ],
+  },
+];
+
 const onboarding: OnboardingConfig = {
   install: () => [
     {
       type: StepType.INSTALL,
-      configurations: [
+      description: tct(
+        'Add the Sentry SDK as a dependency using [codeNpm:npm] or [codeYarn:yarn]:',
         {
-          description: tct(
-            'Add the Sentry SDK as a dependency using [codeNpm:npm] or [codeYarn:yarn]:',
-            {
-              codeYarn: <code />,
-              codeNpm: <code />,
-            }
-          ),
-          language: 'bash',
-          code: [
-            {
-              label: 'npm',
-              value: 'npm',
-              language: 'bash',
-              code: 'npm install --save @sentry/react',
-            },
-            {
-              label: 'yarn',
-              value: 'yarn',
-              language: 'bash',
-              code: 'yarn add @sentry/react',
-            },
-          ],
-        },
-      ],
+          codeYarn: <code />,
+          codeNpm: <code />,
+        }
+      ),
+      configurations: getInstallConfig(),
     },
   ],
   configure: (params: Params) => [
@@ -163,8 +168,48 @@ const onboarding: OnboardingConfig = {
   ],
 };
 
+const replayOnboarding: OnboardingConfig = {
+  install: () => [
+    {
+      type: StepType.INSTALL,
+      description: tct(
+        'Add the Sentry SDK as a dependency using [codeNpm:npm] or [codeYarn:yarn]. You need a minimum version 7.27.0 of [code:@sentry/react] in order to use Session Replay. You do not need to install any additional packages.',
+        {
+          code: <code />,
+          codeYarn: <code />,
+          codeNpm: <code />,
+        }
+      ),
+      configurations: getInstallConfig(),
+    },
+  ],
+  configure: (params: Params) => [
+    {
+      type: StepType.CONFIGURE,
+      description: getReplayConfigureDescription({
+        link: 'https://docs.sentry.io/platforms/javascript/guides/react/session-replay/',
+      }),
+      configurations: [
+        {
+          code: [
+            {
+              label: 'JavaScript',
+              value: 'javascript',
+              language: 'javascript',
+              code: getSdkSetupSnippet({...params, isReplaySelected: true}),
+            },
+          ],
+        },
+      ],
+    },
+  ],
+  verify: () => [],
+  nextSteps: () => [],
+};
+
 const docs: Docs = {
   onboarding,
+  replayOnboarding,
 };
 
 export default docs;

+ 0 - 130
static/app/gettingStartedDocs/replay-onboarding/javascript/react.tsx

@@ -1,130 +0,0 @@
-import ExternalLink from 'sentry/components/links/externalLink';
-import {Layout, LayoutProps} from 'sentry/components/onboarding/gettingStartedDoc/layout';
-import {ModuleProps} from 'sentry/components/onboarding/gettingStartedDoc/sdkDocumentation';
-import {StepType} from 'sentry/components/onboarding/gettingStartedDoc/step';
-import {tct} from 'sentry/locale';
-import type {Organization, PlatformKey} from 'sentry/types';
-
-type StepProps = {
-  newOrg: boolean;
-  organization: Organization;
-  platformKey: PlatformKey;
-  projectId: string;
-  sentryInitContent: string;
-};
-
-// Configuration Start
-const replayIntegration = `
-new Sentry.Replay(),
-`;
-
-const replayOtherConfig = `
-// This sets the sample rate to be 10%. You may want this to be 100% while
-// in development and sample at a lower rate in production.
-replaysSessionSampleRate: 0.1,
-// If the entire session is not sampled, use the below sample rate to sample
-// sessions when an error occurs.
-replaysOnErrorSampleRate: 1.0,
-`;
-
-export const steps = ({
-  sentryInitContent,
-}: Partial<StepProps> = {}): LayoutProps['steps'] => [
-  {
-    type: StepType.INSTALL,
-    description: (
-      <p>
-        {tct(
-          'Add the Sentry SDK as a dependency using [codeNpm:npm] or [codeYarn:yarn]. You need a minimum version 7.27.0 of [code:@sentry/react] in order to use Session Replay. You do not need to install any additional packages.',
-          {
-            code: <code />,
-            codeYarn: <code />,
-            codeNpm: <code />,
-          }
-        )}
-      </p>
-    ),
-    configurations: [
-      {
-        language: 'bash',
-        code: [
-          {
-            label: 'npm',
-            value: 'npm',
-            language: 'bash',
-            code: 'npm install --save @sentry/react',
-          },
-          {
-            label: 'yarn',
-            value: 'yarn',
-            language: 'bash',
-            code: 'yarn add @sentry/react',
-          },
-        ],
-      },
-    ],
-  },
-  {
-    type: StepType.CONFIGURE,
-    description: tct(
-      'Add the following to your SDK config. There are several privacy and sampling options available, all of which can be set using the [code:integrations] constructor. Learn more about configuring Session Replay by reading the [link:configuration docs].',
-      {
-        code: <code />,
-        link: (
-          <ExternalLink href="https://docs.sentry.io/platforms/javascript/session-replay/" />
-        ),
-      }
-    ),
-    configurations: [
-      {
-        language: 'javascript',
-        code: `
-import * as Sentry from "@sentry/react";
-
-Sentry.init({
-  ${sentryInitContent}
-});
-
-const container = document.getElementById(“app”);
-const root = createRoot(container);
-root.render(<App />);
-        `,
-      },
-    ],
-  },
-];
-
-// Configuration End
-
-export function GettingStartedWithReactReplay({
-  dsn,
-  organization,
-  newOrg,
-  platformKey,
-  projectId,
-  ...props
-}: ModuleProps) {
-  const integrations = replayIntegration.trim();
-  const otherConfigs = replayOtherConfig.trim();
-  let sentryInitContent: string[] = [`dsn: "${dsn}",`];
-  sentryInitContent = sentryInitContent.concat('integrations: [', integrations, '],');
-  sentryInitContent = sentryInitContent.concat(otherConfigs);
-
-  return (
-    <Layout
-      steps={steps({
-        sentryInitContent: sentryInitContent.join('\n'),
-        organization,
-        newOrg,
-        platformKey,
-        projectId,
-      })}
-      newOrg={newOrg}
-      platformKey={platformKey}
-      hideHeader
-      {...props}
-    />
-  );
-}
-
-export default GettingStartedWithReactReplay;