Browse Source

ref(onboarding): [4/6] convert falcon, django, bottle to new structure (#61869)

refactor work for https://github.com/getsentry/sentry/issues/61069
Michelle Zhang 1 year ago
parent
commit
48b1c159e7

+ 33 - 12
static/app/gettingStartedDocs/python/bottle.spec.tsx

@@ -1,18 +1,39 @@
-import {render, screen} from 'sentry-test/reactTestingLibrary';
+import {renderWithOnboardingLayout} from 'sentry-test/onboarding/renderWithOnboardingLayout';
+import {screen} from 'sentry-test/reactTestingLibrary';
+import {textWithMarkupMatcher} from 'sentry-test/utils';
 
-import {StepTitle} from 'sentry/components/onboarding/gettingStartedDoc/step';
+import docs from './bottle';
 
-import {GettingStartedWithBottle, steps} from './bottle';
-
-describe('GettingStartedWithBottle', function () {
+describe('bottle onboarding docs', function () {
   it('renders doc correctly', function () {
-    render(<GettingStartedWithBottle dsn="test-dsn" projectSlug="test-project" />);
+    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: 'Verify'})).toBeInTheDocument();
+
+    // Renders install instructions
+    expect(
+      screen.getByText(
+        textWithMarkupMatcher(/pip install --upgrade sentry-sdk\[bottle\]/)
+      )
+    ).toBeInTheDocument();
+  });
+
+  it('renders without performance monitoring', function () {
+    renderWithOnboardingLayout(docs, {
+      selectedProducts: [],
+    });
+
+    // Does not render config option
+    expect(
+      screen.queryByText(textWithMarkupMatcher(/traces_sample_rate: 1\.0,/))
+    ).not.toBeInTheDocument();
 
-    // Steps
-    for (const step of steps({sentryInitContent: 'test-init-content'})) {
-      expect(
-        screen.getByRole('heading', {name: step.title ?? StepTitle[step.type]})
-      ).toBeInTheDocument();
-    }
+    // Does not render config option
+    expect(
+      screen.queryByText(textWithMarkupMatcher(/profiles_sample_rate: 1\.0,/))
+    ).not.toBeInTheDocument();
   });
 });

+ 109 - 137
static/app/gettingStartedDocs/python/bottle.tsx

@@ -1,96 +1,92 @@
 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 {ProductSolution} from 'sentry/components/onboarding/productSelection';
+import {
+  Docs,
+  DocsParams,
+  OnboardingConfig,
+} from 'sentry/components/onboarding/gettingStartedDoc/types';
+import replayOnboardingJsLoader from 'sentry/gettingStartedDocs/javascript/jsLoader/jsLoader';
 import {t, tct} from 'sentry/locale';
 
-// Configuration Start
-const performanceConfiguration = `    # Set traces_sample_rate to 1.0 to capture 100%
-    # of transactions for performance monitoring.
-    traces_sample_rate=1.0,`;
-
-const profilingConfiguration = `    # Set profiles_sample_rate to 1.0 to profile 100%
-    # of sampled transactions.
-    # We recommend adjusting this value in production.
-    profiles_sample_rate=1.0,`;
-
-const introduction = (
-  <p>
-    {tct('The Bottle integration adds support for the [link:Bottle Web Framework].', {
-      link: <ExternalLink href="https://bottlepy.org/docs/dev/" />,
-    })}
-  </p>
-);
+type Params = DocsParams;
 
-export const steps = ({
-  sentryInitContent,
-}: {
-  sentryInitContent: string;
-}): LayoutProps['steps'] => [
-  {
-    type: StepType.INSTALL,
-    description: (
-      <p>
-        {tct(
-          'Install [sentrySdkCode:sentry-sdk] from PyPI with the [sentryBotteCode:bottle] extra:',
-          {
-            sentrySdkCode: <code />,
-            sentryBotteCode: <code />,
-          }
-        )}
-      </p>
-    ),
-    configurations: [
-      {
-        language: 'bash',
-        code: 'pip install --upgrade sentry-sdk[bottle]',
-      },
-    ],
-  },
-  {
-    type: StepType.CONFIGURE,
-    description: (
-      <p>
-        {tct(
-          'If you have the [code:bottle] package in your dependencies, the Bottle integration will be enabled automatically when you initialize the Sentry SDK. Initialize the Sentry SDK before your app has been initialized:',
-          {
-            code: <code />,
-          }
-        )}
-      </p>
-    ),
-    configurations: [
-      {
-        language: 'python',
-        code: `
-import sentry_sdk
-
-from bottle import Bottle
+const getSdkSetupSnippet = (params: Params) => `import sentry_sdk
 
 sentry_sdk.init(
-${sentryInitContent}
+    dsn="${params.dsn}",${
+      params.isPerformanceSelected
+        ? `
+    # Set traces_sample_rate to 1.0 to capture 100%
+    # of transactions for performance monitoring.
+    traces_sample_rate=1.0,`
+        : ''
+    }${
+      params.isProfilingSelected
+        ? `
+    # Set profiles_sample_rate to 1.0 to profile 100%
+    # of sampled transactions.
+    # We recommend adjusting this value in production.
+    profiles_sample_rate=1.0,`
+        : ''
+    }
 )
+`;
 
+const onboarding: OnboardingConfig = {
+  introduction: () =>
+    tct('The Bottle integration adds support for the [link:Bottle Web Framework].', {
+      link: <ExternalLink href="https://bottlepy.org/docs/dev/" />,
+    }),
+  install: () => [
+    {
+      type: StepType.INSTALL,
+      description: tct(
+        'Install [sentrySdkCode:sentry-sdk] from PyPI with the [sentryBotteCode:bottle] extra:',
+        {
+          sentrySdkCode: <code />,
+          sentryBotteCode: <code />,
+        }
+      ),
+      configurations: [
+        {
+          language: 'bash',
+          code: 'pip install --upgrade sentry-sdk[bottle]',
+        },
+      ],
+    },
+  ],
+  configure: (params: Params) => [
+    {
+      type: StepType.CONFIGURE,
+      description: tct(
+        'If you have the [code:bottle] package in your dependencies, the Bottle integration will be enabled automatically when you initialize the Sentry SDK. Initialize the Sentry SDK before your app has been initialized:',
+        {
+          code: <code />,
+        }
+      ),
+      configurations: [
+        {
+          language: 'python',
+          code: `from bottle import Bottle
+${getSdkSetupSnippet(params)}
 app = Bottle()
       `,
-      },
-    ],
-  },
-  {
-    type: StepType.VERIFY,
-    description: (
-      <p>{t('To verify that everything is working trigger an error on purpose:')}</p>
-    ),
-    configurations: [
-      {
-        language: 'python',
-        code: `from bottle import Bottle, run
-
-sentry_sdk.init(
-  ${sentryInitContent}
-)
-
+        },
+      ],
+    },
+  ],
+  verify: (params: Params) => [
+    {
+      type: StepType.VERIFY,
+      description: t(
+        'To verify that everything is working, trigger an error on purpose:'
+      ),
+      configurations: [
+        {
+          language: 'python',
+
+          code: `from bottle import Bottle, run
+${getSdkSetupSnippet(params)}
 app = Bottle()
 
 @app.route('/')
@@ -100,58 +96,34 @@ def hello():
 
 run(app, host='localhost', port=8000)
       `,
-      },
-    ],
-    additionalInfo: (
-      <span>
-        <p>
-          {tct(
-            'When you point your browser to [link:http://localhost:8000/] a transaction in the Performance section of Sentry will be created.',
-            {
-              link: <ExternalLink href="http://localhost:8000/" />,
-            }
-          )}
-        </p>
-        <p>
-          {t(
-            'Additionally, an error event will be sent to Sentry and will be connected to the transaction.'
-          )}
-        </p>
-        <p>{t('It takes a couple of moments for the data to appear in Sentry.')}</p>
-      </span>
-    ),
-  },
-];
-// Configuration End
-
-export function GettingStartedWithBottle({
-  dsn,
-  activeProductSelection = [],
-  ...props
-}: ModuleProps) {
-  const otherConfigs: string[] = [];
-
-  let sentryInitContent: string[] = [`    dsn="${dsn}",`];
-
-  if (activeProductSelection.includes(ProductSolution.PERFORMANCE_MONITORING)) {
-    otherConfigs.push(performanceConfiguration);
-  }
-
-  if (activeProductSelection.includes(ProductSolution.PROFILING)) {
-    otherConfigs.push(profilingConfiguration);
-  }
-
-  sentryInitContent = sentryInitContent.concat(otherConfigs);
-
-  return (
-    <Layout
-      introduction={introduction}
-      steps={steps({
-        sentryInitContent: sentryInitContent.join('\n'),
-      })}
-      {...props}
-    />
-  );
-}
-
-export default GettingStartedWithBottle;
+        },
+      ],
+      additionalInfo: (
+        <span>
+          <p>
+            {tct(
+              'When you point your browser to [link:http://localhost:8000/] a transaction in the Performance section of Sentry will be created.',
+              {
+                link: <ExternalLink href="http://localhost:8000/" />,
+              }
+            )}
+          </p>
+          <p>
+            {t(
+              'Additionally, an error event will be sent to Sentry and will be connected to the transaction.'
+            )}
+          </p>
+          <p>{t('It takes a couple of moments for the data to appear in Sentry.')}</p>
+        </span>
+      ),
+    },
+  ],
+  nextSteps: () => [],
+};
+
+const docs: Docs = {
+  onboarding,
+  replayOnboardingJsLoader,
+};
+
+export default docs;

+ 33 - 12
static/app/gettingStartedDocs/python/django.spec.tsx

@@ -1,18 +1,39 @@
-import {render, screen} from 'sentry-test/reactTestingLibrary';
+import {renderWithOnboardingLayout} from 'sentry-test/onboarding/renderWithOnboardingLayout';
+import {screen} from 'sentry-test/reactTestingLibrary';
+import {textWithMarkupMatcher} from 'sentry-test/utils';
 
-import {StepTitle} from 'sentry/components/onboarding/gettingStartedDoc/step';
+import docs from './django';
 
-import {GettingStartedWithDjango, steps} from './django';
-
-describe('GettingStartedWithDjango', function () {
+describe('django onboarding docs', function () {
   it('renders doc correctly', function () {
-    render(<GettingStartedWithDjango dsn="test-dsn" projectSlug="test-project" />);
+    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: 'Verify'})).toBeInTheDocument();
+
+    // Renders install instructions
+    expect(
+      screen.getByText(
+        textWithMarkupMatcher(/pip install --upgrade sentry-sdk\[django\]/)
+      )
+    ).toBeInTheDocument();
+  });
+
+  it('renders without performance monitoring', function () {
+    renderWithOnboardingLayout(docs, {
+      selectedProducts: [],
+    });
+
+    // Does not render config option
+    expect(
+      screen.queryByText(textWithMarkupMatcher(/traces_sample_rate: 1\.0,/))
+    ).not.toBeInTheDocument();
 
-    // Steps
-    for (const step of steps()) {
-      expect(
-        screen.getByRole('heading', {name: step.title ?? StepTitle[step.type]})
-      ).toBeInTheDocument();
-    }
+    // Does not render config option
+    expect(
+      screen.queryByText(textWithMarkupMatcher(/profiles_sample_rate: 1\.0,/))
+    ).not.toBeInTheDocument();
   });
 });

+ 120 - 135
static/app/gettingStartedDocs/python/django.tsx

@@ -1,95 +1,104 @@
 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 {ProductSolution} from 'sentry/components/onboarding/productSelection';
+import {
+  Docs,
+  DocsParams,
+  OnboardingConfig,
+} from 'sentry/components/onboarding/gettingStartedDoc/types';
+import replayOnboardingJsLoader from 'sentry/gettingStartedDocs/javascript/jsLoader/jsLoader';
 import {t, tct} from 'sentry/locale';
 
-// Configuration Start
-const performanceConfiguration = `    # Set traces_sample_rate to 1.0 to capture 100%
-    # of transactions for performance monitoring.
-    traces_sample_rate=1.0,`;
+type Params = DocsParams;
+
+const getSdkSetupSnippet = (params: Params) => `
+# settings.py
+import sentry_sdk
 
-const profilingConfiguration = `    # Set profiles_sample_rate to 1.0 to profile 100%
+sentry_sdk.init(
+    dsn="${params.dsn}",${
+      params.isPerformanceSelected
+        ? `
+    # Set traces_sample_rate to 1.0 to capture 100%
+    # of transactions for performance monitoring.
+    traces_sample_rate=1.0,`
+        : ''
+    }${
+      params.isProfilingSelected
+        ? `
+    # Set profiles_sample_rate to 1.0 to profile 100%
     # of sampled transactions.
     # We recommend adjusting this value in production.
-    profiles_sample_rate=1.0,`;
+    profiles_sample_rate=1.0,`
+        : ''
+    }
+)
+`;
 
-const introduction = (
-  <p>
-    {tct('The Django integration adds support for the [link:Django Web Framework].', {
+const onboarding: OnboardingConfig = {
+  introduction: () =>
+    tct('The Django integration adds support for the [link:Django Web Framework].', {
       link: <ExternalLink href="https://www.djangoproject.com/" />,
-    })}
-  </p>
-);
-
-export const steps = ({
-  sentryInitContent,
-}: {
-  sentryInitContent?: string;
-} = {}): LayoutProps['steps'] => [
-  {
-    type: StepType.INSTALL,
-    description: (
-      <p>
-        {tct('The Django integration adds support for the [link:Django Web Framework].', {
+    }),
+  install: () => [
+    {
+      type: StepType.INSTALL,
+      description: tct(
+        'The Django integration adds support for the [link:Django Web Framework].',
+        {
           link: <ExternalLink href="https://www.djangoproject.com/" />,
-        })}
-      </p>
-    ),
-    configurations: [
-      {
-        language: 'bash',
-        description: (
-          <p>
-            {tct(
-              'Install [code:sentry-sdk] from PyPI with the [sentryDjangoCode:django] extra:',
-              {
-                code: <code />,
-                sentryDjangoCode: <code />,
-              }
-            )}
-          </p>
-        ),
-        code: 'pip install --upgrade sentry-sdk[django]',
-      },
-    ],
-  },
-  {
-    type: StepType.CONFIGURE,
-    description: (
-      <p>
-        {tct(
-          'If you have the [codeDjango:django] package in your dependencies, the Django integration will be enabled automatically when you initialize the Sentry SDK. Initialize the Sentry SDK in your Django [codeSettings:settings.py] file:',
-          {
-            codeDjango: <code />,
-            codeSettings: <code />,
-          }
-        )}
-      </p>
-    ),
-    configurations: [
-      {
-        language: 'python',
-        code: `# settings.py
-import sentry_sdk
-
-sentry_sdk.init(
-${sentryInitContent}
-)`,
-      },
-    ],
-  },
-  {
-    type: StepType.VERIFY,
-    description: t(
-      'You can easily verify your Sentry installation by creating a route that triggers an error:'
-    ),
-    configurations: [
-      {
-        language: 'python',
+        }
+      ),
+      configurations: [
+        {
+          language: 'bash',
+          description: (
+            <p>
+              {tct(
+                'Install [code:sentry-sdk] from PyPI with the [sentryDjangoCode:django] extra:',
+                {
+                  code: <code />,
+                  sentryDjangoCode: <code />,
+                }
+              )}
+            </p>
+          ),
+          code: 'pip install --upgrade sentry-sdk[django]',
+        },
+      ],
+    },
+  ],
+  configure: (params: Params) => [
+    {
+      type: StepType.CONFIGURE,
+      description: tct(
+        'If you have the [codeDjango:django] package in your dependencies, the Django integration will be enabled automatically when you initialize the Sentry SDK. Initialize the Sentry SDK in your Django [codeSettings:settings.py] file:',
+        {
+          codeDjango: <code />,
+          codeSettings: <code />,
+        }
+      ),
+      configurations: [
+        {
+          language: 'python',
+          code: `
+${getSdkSetupSnippet(params)}
+api = falcon.API()
+      `,
+        },
+      ],
+    },
+  ],
+  verify: () => [
+    {
+      type: StepType.VERIFY,
+      description: t(
+        'You can easily verify your Sentry installation by creating a route that triggers an error:'
+      ),
+      configurations: [
+        {
+          language: 'python',
 
-        code: `# urls.py
+          code: `# urls.py
 from django.urls import path
 
 def trigger_error(request):
@@ -99,59 +108,35 @@ urlpatterns = [
     path('sentry-debug/', trigger_error),
     # ...
 ]
-        `,
-      },
-    ],
-    additionalInfo: (
-      <div>
-        <p>
-          {tct(
-            'When you point your browser to [link:http://localhost:8000/sentry-debug/] a transaction in the Performance section of Sentry will be created.',
-            {
-              link: <ExternalLink href="http://localhost:8000/" />,
-            }
-          )}
-        </p>
-        <p>
-          {t(
-            'Additionally, an error event will be sent to Sentry and will be connected to the transaction.'
-          )}
-        </p>
-        <p>{t('It takes a couple of moments for the data to appear in Sentry.')}</p>
-      </div>
-    ),
-  },
-];
-// Configuration End
-
-export function GettingStartedWithDjango({
-  dsn,
-  activeProductSelection = [],
-  ...props
-}: ModuleProps) {
-  const otherConfigs: string[] = [];
-
-  let sentryInitContent: string[] = [`    dsn="${dsn}",`];
-
-  if (activeProductSelection.includes(ProductSolution.PERFORMANCE_MONITORING)) {
-    otherConfigs.push(performanceConfiguration);
-  }
-
-  if (activeProductSelection.includes(ProductSolution.PROFILING)) {
-    otherConfigs.push(profilingConfiguration);
-  }
-
-  sentryInitContent = sentryInitContent.concat(otherConfigs);
+                  `,
+        },
+      ],
+      additionalInfo: (
+        <div>
+          <p>
+            {tct(
+              'When you point your browser to [link:http://localhost:8000/sentry-debug/] a transaction in the Performance section of Sentry will be created.',
+              {
+                link: <ExternalLink href="http://localhost:8000/" />,
+              }
+            )}
+          </p>
+          <p>
+            {t(
+              'Additionally, an error event will be sent to Sentry and will be connected to the transaction.'
+            )}
+          </p>
+          <p>{t('It takes a couple of moments for the data to appear in Sentry.')}</p>
+        </div>
+      ),
+    },
+  ],
+  nextSteps: () => [],
+};
 
-  return (
-    <Layout
-      introduction={introduction}
-      steps={steps({
-        sentryInitContent: sentryInitContent.join('\n'),
-      })}
-      {...props}
-    />
-  );
-}
+const docs: Docs = {
+  onboarding,
+  replayOnboardingJsLoader,
+};
 
-export default GettingStartedWithDjango;
+export default docs;

+ 33 - 12
static/app/gettingStartedDocs/python/falcon.spec.tsx

@@ -1,18 +1,39 @@
-import {render, screen} from 'sentry-test/reactTestingLibrary';
+import {renderWithOnboardingLayout} from 'sentry-test/onboarding/renderWithOnboardingLayout';
+import {screen} from 'sentry-test/reactTestingLibrary';
+import {textWithMarkupMatcher} from 'sentry-test/utils';
 
-import {StepTitle} from 'sentry/components/onboarding/gettingStartedDoc/step';
+import docs from './falcon';
 
-import {GettingStartedWithFalcon, steps} from './falcon';
-
-describe('GettingStartedWithFalcon', function () {
+describe('falcon onboarding docs', function () {
   it('renders doc correctly', function () {
-    render(<GettingStartedWithFalcon dsn="test-dsn" projectSlug="test-project" />);
+    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: 'Verify'})).toBeInTheDocument();
+
+    // Renders install instructions
+    expect(
+      screen.getByText(
+        textWithMarkupMatcher(/\$ pip install --upgrade 'sentry-sdk\[falcon\]'/)
+      )
+    ).toBeInTheDocument();
+  });
+
+  it('renders without performance monitoring', function () {
+    renderWithOnboardingLayout(docs, {
+      selectedProducts: [],
+    });
+
+    // Does not render config option
+    expect(
+      screen.queryByText(textWithMarkupMatcher(/traces_sample_rate: 1\.0,/))
+    ).not.toBeInTheDocument();
 
-    // Steps
-    for (const step of steps({sentryInitContent: 'test-init-content'})) {
-      expect(
-        screen.getByRole('heading', {name: step.title ?? StepTitle[step.type]})
-      ).toBeInTheDocument();
-    }
+    // Does not render config option
+    expect(
+      screen.queryByText(textWithMarkupMatcher(/profiles_sample_rate: 1\.0,/))
+    ).not.toBeInTheDocument();
   });
 });

+ 109 - 133
static/app/gettingStartedDocs/python/falcon.tsx

@@ -1,94 +1,94 @@
 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 {ProductSolution} from 'sentry/components/onboarding/productSelection';
+import {
+  Docs,
+  DocsParams,
+  OnboardingConfig,
+} from 'sentry/components/onboarding/gettingStartedDoc/types';
+import replayOnboardingJsLoader from 'sentry/gettingStartedDocs/javascript/jsLoader/jsLoader';
 import {t, tct} from 'sentry/locale';
 
-// Configuration Start
-const performanceConfiguration = `    # Set traces_sample_rate to 1.0 to capture 100%
-    # of transactions for performance monitoring.
-    traces_sample_rate=1.0,`;
-
-const profilingConfiguration = `    # Set profiles_sample_rate to 1.0 to profile 100%
-    # of sampled transactions.
-    # We recommend adjusting this value in production.
-    profiles_sample_rate=1.0,`;
-
-const introduction = (
-  <p>
-    {tct('The Falcon integration adds support for the [link:Falcon Web Framework].', {
-      link: <ExternalLink href="https://falconframework.org/" />,
-    })}
-  </p>
-);
+type Params = DocsParams;
 
-export const steps = ({
-  sentryInitContent,
-}: {
-  sentryInitContent: string;
-}): LayoutProps['steps'] => [
-  {
-    type: StepType.INSTALL,
-    description: (
-      <p>
-        {tct(
-          'Install [sentrySdkCode:sentry-sdk] from PyPI with the [sentryFalconCode:falcon] extra:',
-          {
-            sentrySdkCode: <code />,
-            sentryFalconCode: <code />,
-          }
-        )}
-      </p>
-    ),
-    configurations: [
-      {
-        language: 'bash',
-        code: "$ pip install --upgrade 'sentry-sdk[falcon]'",
-      },
-    ],
-  },
-  {
-    type: StepType.CONFIGURE,
-    description: (
-      <p>
-        {tct(
-          'If you have the [codeFalcon:falcon] package in your dependencies, the Falcon integration will be enabled automatically when you initialize the Sentry SDK. Initialize the Sentry SDK before your app has been initialized:',
-          {
-            codeFalcon: <code />,
-          }
-        )}
-      </p>
-    ),
-    configurations: [
-      {
-        language: 'python',
-        code: `
+const getSdkSetupSnippet = (params: Params) => `
 import falcon
 import sentry_sdk
 
 sentry_sdk.init(
-${sentryInitContent}
+    dsn="${params.dsn}",${
+      params.isPerformanceSelected
+        ? `
+    # Set traces_sample_rate to 1.0 to capture 100%
+    # of transactions for performance monitoring.
+    traces_sample_rate=1.0,`
+        : ''
+    }${
+      params.isProfilingSelected
+        ? `
+    # Set profiles_sample_rate to 1.0 to profile 100%
+    # of sampled transactions.
+    # We recommend adjusting this value in production.
+    profiles_sample_rate=1.0,`
+        : ''
+    }
 )
+`;
 
+const onboarding: OnboardingConfig = {
+  introduction: () =>
+    tct('The Falcon integration adds support for the [link:Falcon Web Framework].', {
+      link: <ExternalLink href="https://falconframework.org/" />,
+    }),
+  install: () => [
+    {
+      type: StepType.INSTALL,
+      description: tct(
+        'Install [sentrySdkCode:sentry-sdk] from PyPI with the [sentryFalconCode:falcon] extra:',
+        {
+          sentrySdkCode: <code />,
+          sentryFalconCode: <code />,
+        }
+      ),
+      configurations: [
+        {
+          language: 'bash',
+          code: "$ pip install --upgrade 'sentry-sdk[falcon]'",
+        },
+      ],
+    },
+  ],
+  configure: (params: Params) => [
+    {
+      type: StepType.CONFIGURE,
+      description: tct(
+        'If you have the [codeFalcon:falcon] package in your dependencies, the Falcon integration will be enabled automatically when you initialize the Sentry SDK. Initialize the Sentry SDK before your app has been initialized:',
+        {
+          codeFalcon: <code />,
+        }
+      ),
+      configurations: [
+        {
+          language: 'python',
+          code: `
+${getSdkSetupSnippet(params)}
 api = falcon.API()
       `,
-      },
-    ],
-  },
-  {
-    type: StepType.VERIFY,
-    description: t('To verify that everything is working trigger an error on purpose:'),
-    configurations: [
-      {
-        language: 'python',
-        code: `import falcon
-imoprt sentry_sdk
-
-sentry_sdk.init(
-${sentryInitContent}
-)
-
+        },
+      ],
+    },
+  ],
+  verify: (params: Params) => [
+    {
+      type: StepType.VERIFY,
+      description: t(
+        'To verify that everything is working, trigger an error on purpose:'
+      ),
+      configurations: [
+        {
+          language: 'python',
+
+          code: `
+${getSdkSetupSnippet(params)}
 class HelloWorldResource:
     def on_get(self, req, resp):
         message = {
@@ -100,58 +100,34 @@ class HelloWorldResource:
 app = falcon.App()
 app.add_route('/', HelloWorldResource())
       `,
-      },
-    ],
-    additionalInfo: (
-      <div>
-        <p>
-          {tct(
-            'When you point your browser to [link:http://localhost:8000/] a transaction in the Performance section of Sentry will be created.',
-            {
-              link: <ExternalLink href="http://localhost:8000/" />,
-            }
-          )}
-        </p>
-        <p>
-          {t(
-            'Additionally, an error event will be sent to Sentry and will be connected to the transaction.'
-          )}
-        </p>
-        <p>{t('It takes a couple of moments for the data to appear in Sentry.')}</p>
-      </div>
-    ),
-  },
-];
-// Configuration End
-
-export function GettingStartedWithFalcon({
-  dsn,
-  activeProductSelection = [],
-  ...props
-}: ModuleProps) {
-  const otherConfigs: string[] = [];
-
-  let sentryInitContent: string[] = [`    dsn="${dsn}",`];
-
-  if (activeProductSelection.includes(ProductSolution.PERFORMANCE_MONITORING)) {
-    otherConfigs.push(performanceConfiguration);
-  }
-
-  if (activeProductSelection.includes(ProductSolution.PROFILING)) {
-    otherConfigs.push(profilingConfiguration);
-  }
-
-  sentryInitContent = sentryInitContent.concat(otherConfigs);
-
-  return (
-    <Layout
-      introduction={introduction}
-      steps={steps({
-        sentryInitContent: sentryInitContent.join('\n'),
-      })}
-      {...props}
-    />
-  );
-}
-
-export default GettingStartedWithFalcon;
+        },
+      ],
+      additionalInfo: (
+        <div>
+          <p>
+            {tct(
+              'When you point your browser to [link:http://localhost:8000/] a transaction in the Performance section of Sentry will be created.',
+              {
+                link: <ExternalLink href="http://localhost:8000/" />,
+              }
+            )}
+          </p>
+          <p>
+            {t(
+              'Additionally, an error event will be sent to Sentry and will be connected to the transaction.'
+            )}
+          </p>
+          <p>{t('It takes a couple of moments for the data to appear in Sentry.')}</p>
+        </div>
+      ),
+    },
+  ],
+  nextSteps: () => [],
+};
+
+const docs: Docs = {
+  onboarding,
+  replayOnboardingJsLoader,
+};
+
+export default docs;