Browse Source

ref(onboarding): [5/6] convert php, laravel, symfony to new structure (#61880)

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

+ 31 - 16
static/app/gettingStartedDocs/php/laravel.spec.tsx

@@ -1,22 +1,37 @@
-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 './laravel';
 
-import {GettingStartedWithLaravel, steps} from './laravel';
-
-describe('GettingStartedWithLaravel', function () {
+describe('laravel onboarding docs', function () {
   it('renders doc correctly', function () {
-    render(<GettingStartedWithLaravel 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(/composer require sentry\/sentry-laravel/))
+    ).toBeInTheDocument();
+  });
+
+  it('renders without performance monitoring', function () {
+    renderWithOnboardingLayout(docs, {
+      selectedProducts: [],
+    });
+
+    // Does not render config option
+    expect(
+      screen.queryByText(textWithMarkupMatcher(/SENTRY_TRACES_SAMPLE_RATE=1\.0,/))
+    ).not.toBeInTheDocument();
 
-    // Steps
-    for (const step of steps({
-      dsn: 'test-dsn',
-      hasPerformance: true,
-      hasProfiling: true,
-    })) {
-      expect(
-        screen.getByRole('heading', {name: step.title ?? StepTitle[step.type]})
-      ).toBeInTheDocument();
-    }
+    // Does not render config option
+    expect(
+      screen.queryByText(textWithMarkupMatcher(/SENTRY_PROFILES_SAMPLE_RATE=1\.0,/))
+    ).not.toBeInTheDocument();
   });
 });

+ 119 - 136
static/app/gettingStartedDocs/php/laravel.tsx

@@ -1,20 +1,18 @@
 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';
 
-interface StepsParams {
-  dsn: string;
-  hasPerformance: boolean;
-  hasProfiling: boolean;
-}
+type Params = DocsParams;
 
-// Configuration Start
-const introduction = (
-  <p>
-    {tct(
+const onboarding: OnboardingConfig = {
+  introduction: () =>
+    tct(
       'This guide is for Laravel 8+. We also provide instructions for [otherVersionsLink:other versions] as well as [lumenSpecificLink:Lumen-specific instructions].',
       {
         otherVersionsLink: (
@@ -24,134 +22,119 @@ const introduction = (
           <ExternalLink href="https://docs.sentry.io/platforms/php/guides/laravel/other-versions/lumen/" />
         ),
       }
-    )}
-  </p>
-);
-
-export const steps = ({
-  dsn,
-  hasPerformance,
-  hasProfiling,
-}: StepsParams): LayoutProps['steps'] => [
-  {
-    type: StepType.INSTALL,
-    configurations: [
-      {
-        description: (
-          <p>
-            {tct('Install the [code:sentry/sentry-laravel] package:', {
-              code: <code />,
-            })}
-          </p>
-        ),
-        language: 'bash',
-        code: `composer require sentry/sentry-laravel`,
-      },
-      ...(hasProfiling
-        ? [
-            {
-              description: t('Install the Excimer extension via PECL:'),
-              language: 'bash',
-              code: 'pecl install excimer',
-            },
-          ]
-        : []),
-      {
-        description: (
-          <p>
-            {tct(
-              'Enable capturing unhandled exception to report to Sentry by making the following change to your [code:App/Exceptions/Handler.php]:',
-              {
+    ),
+  install: (params: Params) => [
+    {
+      type: StepType.INSTALL,
+      configurations: [
+        {
+          description: (
+            <p>
+              {tct('Install the [code:sentry/sentry-laravel] package:', {
                 code: <code />,
-              }
-            )}
-          </p>
-        ),
-        language: 'php',
-        code: `
-public function register() {
-  $this->reportable(function (Throwable $e) {
-    if (app()->bound('sentry')) {
-      app('sentry')->captureException($e);
-    }
-  });
-}
-        `,
-      },
-    ],
-  },
-  {
-    type: StepType.CONFIGURE,
-    configurations: [
-      {
-        description: t('Configure the Sentry DSN with this command:'),
-        language: 'shell',
-        code: `php artisan sentry:publish --dsn=${dsn}`,
-      },
-      {
-        description: (
-          <p>
-            {tct(
-              'It creates the config file ([sentryPHPCode:config/sentry.php]) and adds the [dsnCode:DSN] to your [envCode:.env] file where you can add further configuration options:',
-              {sentryPHPCode: <code />, dsnCode: <code />, envCode: <code />}
-            )}
-          </p>
-        ),
-        language: 'shell',
-        code: `SENTRY_LARAVEL_DSN=${dsn}${
-          hasPerformance
-            ? `
+              })}
+            </p>
+          ),
+          language: 'bash',
+          code: `composer require sentry/sentry-laravel`,
+        },
+        ...(params.isProfilingSelected
+          ? [
+              {
+                description: t('Install the Excimer extension via PECL:'),
+                language: 'bash',
+                code: 'pecl install excimer',
+              },
+            ]
+          : []),
+        {
+          description: (
+            <p>
+              {tct(
+                'Enable capturing unhandled exception to report to Sentry by making the following change to your [code:App/Exceptions/Handler.php]:',
+                {
+                  code: <code />,
+                }
+              )}
+            </p>
+          ),
+          language: 'php',
+          code: `
+  public function register() {
+    $this->reportable(function (Throwable $e) {
+      if (app()->bound('sentry')) {
+        app('sentry')->captureException($e);
+      }
+    });
+  }
+          `,
+        },
+      ],
+    },
+  ],
+  configure: (params: Params) => [
+    {
+      type: StepType.CONFIGURE,
+      configurations: [
+        {
+          description: t('Configure the Sentry DSN with this command:'),
+          language: 'shell',
+          code: `php artisan sentry:publish --dsn=${params.dsn}`,
+        },
+        {
+          description: (
+            <p>
+              {tct(
+                'It creates the config file ([sentryPHPCode:config/sentry.php]) and adds the [dsnCode:DSN] to your [envCode:.env] file where you can add further configuration options:',
+                {sentryPHPCode: <code />, dsnCode: <code />, envCode: <code />}
+              )}
+            </p>
+          ),
+          language: 'shell',
+          code: `SENTRY_LARAVEL_DSN=${params.dsn}${
+            params.isPerformanceSelected
+              ? `
 # Specify a fixed sample rate
 SENTRY_TRACES_SAMPLE_RATE=1.0`
-            : ''
-        }${
-          hasProfiling
-            ? `
+              : ''
+          }${
+            params.isProfilingSelected
+              ? `
 # Set a sampling rate for profiling - this is relative to traces_sample_rate
 SENTRY_PROFILES_SAMPLE_RATE=1.0`
-            : ''
-        }`,
-      },
-    ],
-  },
-  {
-    type: StepType.VERIFY,
-    configurations: [
-      {
-        description: (
-          <p>
-            {tct(
-              'You can test your configuration using the provided [code:sentry:test] artisan command:',
-              {
-                code: <code />,
-              }
-            )}
-          </p>
-        ),
-        language: 'shell',
-        code: 'php artisan sentry:test',
-      },
-    ],
-  },
-];
-// Configuration End
+              : ''
+          }`,
+        },
+      ],
+    },
+  ],
+  verify: () => [
+    {
+      type: StepType.VERIFY,
+      configurations: [
+        {
+          description: (
+            <p>
+              {tct(
+                'You can test your configuration using the provided [code:sentry:test] artisan command:',
+                {
+                  code: <code />,
+                }
+              )}
+            </p>
+          ),
+          language: 'shell',
+          code: 'php artisan sentry:test',
+        },
+      ],
+    },
+  ],
+  nextSteps: () => [],
+};
 
-export function GettingStartedWithLaravel({
-  dsn,
-  activeProductSelection = [],
-  ...props
-}: ModuleProps) {
-  const hasPerformance = activeProductSelection.includes(
-    ProductSolution.PERFORMANCE_MONITORING
-  );
-  const hasProfiling = activeProductSelection.includes(ProductSolution.PROFILING);
-  return (
-    <Layout
-      introduction={introduction}
-      steps={steps({dsn, hasPerformance, hasProfiling})}
-      {...props}
-    />
-  );
-}
+const docs: Docs = {
+  onboarding,
+  replayOnboardingJsLoader,
+};
 
-export default GettingStartedWithLaravel;
+export default docs;

+ 31 - 16
static/app/gettingStartedDocs/php/php.spec.tsx

@@ -1,22 +1,37 @@
-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 './php';
 
-import {GettingStartedWithPHP, steps} from './php';
-
-describe('GettingStartedWithPHP', function () {
+describe('php onboarding docs', function () {
   it('renders doc correctly', function () {
-    render(<GettingStartedWithPHP 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(/composer require sentry\/sdk/))
+    ).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({
-      dsn: 'test-dsn',
-      hasPerformance: true,
-      hasProfiling: true,
-    })) {
-      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();
   });
 });

+ 99 - 112
static/app/gettingStartedDocs/php/php.tsx

@@ -1,120 +1,107 @@
 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';
 
-interface StepsParams {
-  dsn: string;
-  hasPerformance: boolean;
-  hasProfiling: boolean;
-}
+type Params = DocsParams;
 
-// Configuration Start
-export const steps = ({
-  dsn,
-  hasPerformance,
-  hasProfiling,
-}: StepsParams): LayoutProps['steps'] => [
-  {
-    type: StepType.INSTALL,
-    configurations: [
-      {
-        description: (
-          <p>
-            {tct(
-              'To install the PHP SDK, you need to be using Composer in your project. For more details about Composer, see the [composerDocumentationLink:Composer documentation].',
+const onboarding: OnboardingConfig = {
+  install: (params: Params) => [
+    {
+      type: StepType.INSTALL,
+      description: tct(
+        'To install the PHP SDK, you need to be using Composer in your project. For more details about Composer, see the [composerDocumentationLink:Composer documentation].',
+        {
+          composerDocumentationLink: <ExternalLink href="https://getcomposer.org/doc/" />,
+        }
+      ),
+      configurations: [
+        {
+          language: 'bash',
+          code: 'composer require sentry/sdk',
+        },
+        ...(params.isProfilingSelected
+          ? [
               {
-                composerDocumentationLink: (
-                  <ExternalLink href="https://getcomposer.org/doc/" />
-                ),
-              }
-            )}
-          </p>
-        ),
-        language: 'bash',
-        code: 'composer require sentry/sdk',
-      },
-      ...(hasProfiling
-        ? [
-            {
-              description: t('Install the Excimer extension via PECL:'),
-              language: 'bash',
-              code: 'pecl install excimer',
-            },
-          ]
-        : []),
-    ],
-  },
-  {
-    type: StepType.CONFIGURE,
-    description: t(
-      'To capture all errors, even the one during the startup of your application, you should initialize the Sentry PHP SDK as soon as possible.'
-    ),
-    configurations: [
-      {
-        language: 'php',
-        code: `\\Sentry\\init([
-    'dsn' => '${dsn}',${
-      hasPerformance
-        ? `
-    // Specify a fixed sample rate
-    'traces_sample_rate' => 1.0,`
-        : ''
-    }${
-      hasProfiling
-        ? `
-    // Set a sampling rate for profiling - this is relative to traces_sample_rate
-    'profiles_sample_rate' => 1.0,`
-        : ''
-    }
-]);`,
-        additionalInfo: hasPerformance && (
-          <p>
-            {tct(
-              'To instrument certain regions of your code, you can [instrumentationLink:create transactions to capture them].',
-              {
-                instrumentationLink: (
-                  <ExternalLink href="https://docs.sentry.io/platforms/php/performance/instrumentation/custom-instrumentation/" />
-                ),
-              }
-            )}
-          </p>
-        ),
-      },
-    ],
-  },
-  {
-    type: StepType.VERIFY,
-    description: t(
-      'In PHP you can either capture a caught exception or capture the last error with captureLastError.'
-    ),
-    configurations: [
-      {
-        language: 'php',
-        code: `
-try {
-  $this->functionFailsForSure();
-} catch (\\Throwable $exception) {
-  \\Sentry\\captureException($exception);
-}`,
-      },
-    ],
-  },
-];
-// Configuration End
+                description: t('Install the Excimer extension via PECL:'),
+                language: 'bash',
+                code: 'pecl install excimer',
+              },
+            ]
+          : []),
+      ],
+    },
+  ],
+  configure: (params: Params) => [
+    {
+      type: StepType.CONFIGURE,
+      description: t(
+        'To capture all errors, even the one during the startup of your application, you should initialize the Sentry PHP SDK as soon as possible.'
+      ),
+      configurations: [
+        {
+          language: 'php',
+          code: `\\Sentry\\init([
+      'dsn' => '${params.dsn}',${
+        params.isPerformanceSelected
+          ? `
+      // Specify a fixed sample rate
+      'traces_sample_rate' => 1.0,`
+          : ''
+      }${
+        params.isProfilingSelected
+          ? `
+      // Set a sampling rate for profiling - this is relative to traces_sample_rate
+      'profiles_sample_rate' => 1.0,`
+          : ''
+      }
+  ]);`,
+          additionalInfo: params.isPerformanceSelected && (
+            <p>
+              {tct(
+                'To instrument certain regions of your code, you can [instrumentationLink:create transactions to capture them].',
+                {
+                  instrumentationLink: (
+                    <ExternalLink href="https://docs.sentry.io/platforms/php/performance/instrumentation/custom-instrumentation/" />
+                  ),
+                }
+              )}
+            </p>
+          ),
+        },
+      ],
+    },
+  ],
+  verify: () => [
+    {
+      type: StepType.VERIFY,
+      description: t(
+        'In PHP you can either capture a caught exception or capture the last error with captureLastError.'
+      ),
+      configurations: [
+        {
+          language: 'php',
+          code: `
+  try {
+    $this->functionFailsForSure();
+  } catch (\\Throwable $exception) {
+    \\Sentry\\captureException($exception);
+  }`,
+        },
+      ],
+    },
+  ],
+  nextSteps: () => [],
+};
 
-export function GettingStartedWithPHP({
-  dsn,
-  activeProductSelection = [],
-  ...props
-}: ModuleProps) {
-  const hasPerformance = activeProductSelection.includes(
-    ProductSolution.PERFORMANCE_MONITORING
-  );
-  const hasProfiling = activeProductSelection.includes(ProductSolution.PROFILING);
-  return <Layout steps={steps({dsn, hasPerformance, hasProfiling})} {...props} />;
-}
+const docs: Docs = {
+  onboarding,
+  replayOnboardingJsLoader,
+};
 
-export default GettingStartedWithPHP;
+export default docs;

+ 31 - 16
static/app/gettingStartedDocs/php/symfony.spec.tsx

@@ -1,22 +1,37 @@
-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 './symfony';
 
-import {GettingStartedWithSymfony, steps} from './symfony';
-
-describe('GettingStartedWithSymfony', function () {
+describe('symfony onboarding docs', function () {
   it('renders doc correctly', function () {
-    render(<GettingStartedWithSymfony 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(/composer require sentry\/sentry-symfony/))
+    ).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({
-      dsn: 'test-dsn',
-      hasPerformance: true,
-      hasProfiling: true,
-    })) {
-      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();
   });
 });

+ 133 - 160
static/app/gettingStartedDocs/php/symfony.tsx

@@ -1,178 +1,151 @@
 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';
 
-interface StepsParams {
-  dsn: string;
-  hasPerformance: boolean;
-  hasProfiling: boolean;
-}
+type Params = DocsParams;
 
-// Configuration Start
-const introduction = (
-  <p>
-    {tct(
+const onboarding: OnboardingConfig = {
+  introduction: () =>
+    tct(
       'Symfony is supported via the [code:sentry-symfony] package as a native bundle.',
       {code: <code />}
-    )}
-  </p>
-);
-
-export const steps = ({
-  dsn,
-  hasPerformance,
-  hasProfiling,
-}: StepsParams): LayoutProps['steps'] => [
-  {
-    type: StepType.INSTALL,
-    configurations: [
-      {
-        language: 'bash',
-        description: (
-          <p>
-            {tct('Install the [code:sentry/sentry-symfony] bundle:', {code: <code />})}
-          </p>
-        ),
-        code: 'composer require sentry/sentry-symfony',
-      },
-      ...(hasProfiling
-        ? [
-            {
-              description: t('Install the Excimer extension via PECL:'),
-              language: 'bash',
-              code: 'pecl install excimer',
-            },
-          ]
-        : []),
-    ],
-  },
-  {
-    type: StepType.CONFIGURE,
-    configurations: [
-      {
-        description: (
-          <p>{tct('Add your DSN to your [code:.env] file:', {code: <code />})}</p>
-        ),
-        language: 'shell',
-        code: `
+    ),
+  install: (params: Params) => [
+    {
+      type: StepType.INSTALL,
+      configurations: [
+        {
+          language: 'bash',
+          description: (
+            <p>
+              {tct('Install the [code:sentry/sentry-symfony] bundle:', {code: <code />})}
+            </p>
+          ),
+          code: 'composer require sentry/sentry-symfony',
+        },
+        ...(params.isProfilingSelected
+          ? [
+              {
+                description: t('Install the Excimer extension via PECL:'),
+                language: 'bash',
+                code: 'pecl install excimer',
+              },
+            ]
+          : []),
+      ],
+    },
+  ],
+  configure: (params: Params) => [
+    {
+      type: StepType.CONFIGURE,
+      configurations: [
+        {
+          description: (
+            <p>{tct('Add your DSN to your [code:.env] file:', {code: <code />})}</p>
+          ),
+          language: 'shell',
+          code: `
 ###> sentry/sentry-symfony ###
-SENTRY_DSN="${dsn}"
+SENTRY_DSN="${params.dsn}"
 ###< sentry/sentry-symfony ###
-        `,
-      },
-      ...(hasPerformance || hasProfiling
-        ? [
-            {
-              description: (
-                <p>
-                  {tct(
-                    'Add further configuration options to your [code:config/packages/sentry.yaml] file:',
-                    {code: <code />}
-                  )}
-                </p>
-              ),
-              language: 'yaml',
-              code: `when@prod:
-    sentry:
-        dsn: '%env(SENTRY_DSN)%'${
-          hasPerformance
-            ? `
-        # Specify a fixed sample rate
-        traces_sample_rate: 1.0`
-            : ''
-        }${
-          hasProfiling
-            ? `
-        # Set a sampling rate for profiling - this is relative to traces_sample_rate
-        profiles_sample_rate: 1.0`
-            : ''
-        }`,
-            },
-          ]
-        : []),
-    ],
-  },
-  {
-    type: StepType.VERIFY,
-    description: (
-      <p>
-        {tct(
-          'To test that both logger error and exception are correctly sent to [sentryLink:sentry.io], you can create the following controller:',
-          {
-            sentryLink: <ExternalLink href="https://sentry.io" />,
-          }
-        )}
-      </p>
-    ),
-    configurations: [
-      {
-        language: 'php',
-        code: `
-<?php
+          `,
+        },
+        ...(params.isPerformanceSelected || params.isProfilingSelected
+          ? [
+              {
+                description: (
+                  <p>
+                    {tct(
+                      'Add further configuration options to your [code:config/packages/sentry.yaml] file:',
+                      {code: <code />}
+                    )}
+                  </p>
+                ),
+                language: 'yaml',
+                code: `when@prod:
+      sentry:
+          dsn: '%env(SENTRY_DSN)%'${
+            params.isPerformanceSelected
+              ? `
+          # Specify a fixed sample rate
+          traces_sample_rate: 1.0`
+              : ''
+          }${
+            params.isProfilingSelected
+              ? `
+          # Set a sampling rate for profiling - this is relative to traces_sample_rate
+          profiles_sample_rate: 1.0`
+              : ''
+          }`,
+              },
+            ]
+          : []),
+      ],
+    },
+  ],
+  verify: () => [
+    {
+      type: StepType.VERIFY,
+      configurations: [
+        {
+          language: 'php',
+          code: `
+  <?php
 
-namespace App\\Controller;
+  namespace App\\Controller;
 
-use Psr\\Log\\LoggerInterface;
-use Symfony\\Bundle\\FrameworkBundle\\Controller\\AbstractController;
-use Symfony\\Component\\Routing\\Annotation\\Route;
+  use Psr\\Log\\LoggerInterface;
+  use Symfony\\Bundle\\FrameworkBundle\\Controller\\AbstractController;
+  use Symfony\\Component\\Routing\\Annotation\\Route;
 
-class SentryTestController extends AbstractController {
-  /**
-   * @var LoggerInterface
-   */
-  private $logger;
+  class SentryTestController extends AbstractController {
+    /**
+     * @var LoggerInterface
+     */
+    private $logger;
 
-  public function __construct(LoggerInterface $logger)
-  {
-    $this->logger = $logger;
-  }
+    public function __construct(LoggerInterface $logger)
+    {
+      $this->logger = $logger;
+    }
 
-  /**
-   * @Route(name="sentry_test", path="/_sentry-test")
-   */
-  public function testLog()
-  {
-    // the following code will test if monolog integration logs to sentry
-    $this->logger->error('My custom logged error.');
+    /**
+     * @Route(name="sentry_test", path="/_sentry-test")
+     */
+    public function testLog()
+    {
+      // the following code will test if monolog integration logs to sentry
+      $this->logger->error('My custom logged error.');
 
-    // the following code will test if an uncaught exception logs to sentry
-    throw new \\RuntimeException('Example exception.');
+      // the following code will test if an uncaught exception logs to sentry
+      throw new \\RuntimeException('Example exception.');
+    }
   }
-}
-        `,
-      },
-    ],
-    additionalInfo: (
-      <p>
-        {tct(
-          "After you visit the [code:/_sentry-test page], you can view and resolve the recorded error by logging into [sentryLink:sentry.io] and opening your project. Clicking on the error's title will open a page where you can see detailed information and mark it as resolved.",
-          {sentryLink: <ExternalLink href="https://sentry.io" />, code: <code />}
-        )}
-      </p>
-    ),
-  },
-];
-// Configuration End
+          `,
+        },
+      ],
+      additionalInfo: (
+        <p>
+          {tct(
+            "After you visit the [code:/_sentry-test page], you can view and resolve the recorded error by logging into [sentryLink:sentry.io] and opening your project. Clicking on the error's title will open a page where you can see detailed information and mark it as resolved.",
+            {sentryLink: <ExternalLink href="https://sentry.io" />, code: <code />}
+          )}
+        </p>
+      ),
+    },
+  ],
+  nextSteps: () => [],
+};
 
-export function GettingStartedWithSymfony({
-  dsn,
-  activeProductSelection = [],
-  ...props
-}: ModuleProps) {
-  const hasPerformance = activeProductSelection.includes(
-    ProductSolution.PERFORMANCE_MONITORING
-  );
-  const hasProfiling = activeProductSelection.includes(ProductSolution.PROFILING);
-  return (
-    <Layout
-      introduction={introduction}
-      steps={steps({dsn, hasPerformance, hasProfiling})}
-      {...props}
-    />
-  );
-}
+const docs: Docs = {
+  onboarding,
+  replayOnboardingJsLoader,
+};
 
-export default GettingStartedWithSymfony;
+export default docs;