Browse Source

feat(feedback): [4/4] add rails + php platforms to issues feedback onboarding (#66613)

the last of the platforms -- this PR adds the following platforms:

- 'ruby-rails',
-  'php',
-  'php-laravel',
-  'php-symfony',

closes https://github.com/getsentry/sentry/issues/66162
<img width="472" alt="SCR-20240308-jkep"
src="https://github.com/getsentry/sentry/assets/56095982/5792bab9-1b98-46ac-a1bf-983e8599e9fd">
<img width="466" alt="SCR-20240308-jlnc"
src="https://github.com/getsentry/sentry/assets/56095982/c540b8ad-3796-4ece-9024-75aaab71ff52">
Michelle Zhang 1 year ago
parent
commit
9cfb10ce19

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

@@ -222,3 +222,71 @@ export const getCrashReportBackendInstallStep = params => [
     ],
   },
 ];
+
+export function getCrashReportSDKInstallFirstStepRails(params) {
+  const version =
+    params.sourcePackageRegistries.data['sentry.javascript.browser'].version;
+  const hash =
+    params.sourcePackageRegistries.data['sentry.javascript.browser'].files[
+      'bundle.min.js'
+    ].checksums['sha384-base64'];
+
+  return {
+    description: t('Make sure you have the JavaScript SDK available:'),
+    code: [
+      {
+        label: 'ERB',
+        value: 'erb',
+        language: 'erb',
+        code: `<script
+  src="https://browser.sentry-cdn.com/${version}/bundle.min.js"
+  integrity="sha384-${hash}"
+  crossorigin="anonymous"
+></script>`,
+      },
+    ],
+  };
+}
+
+export const getCrashReportPHPInstallStep = params => [
+  {
+    type: StepType.INSTALL,
+    configurations: [
+      {
+        description: tct('This function php returns the last [code:eventId]:', {
+          code: <code />,
+        }),
+        code: [
+          {
+            label: 'PHP',
+            value: 'php',
+            language: 'php',
+            code: `\Sentry\SentrySdk::getCurrentHub()->getLastEventId();`,
+          },
+        ],
+      },
+      getCrashReportSDKInstallFirstStep(params),
+      {
+        description: t(
+          'Depending on how you render your templates, the example would be in a simple php file:'
+        ),
+        code: [
+          {
+            label: 'HTML',
+            value: 'html',
+            language: 'html',
+            code: `<?php if (\Sentry\SentrySdk::getCurrentHub()->getLastEventId()) { ?>
+<script>
+  Sentry.init({ dsn: "${params.dsn}" });
+  Sentry.showReportDialog({
+    eventId:
+      "<?php echo \Sentry\SentrySdk::getCurrentHub()->getLastEventId(); ?>",
+  });
+</script>
+<?php } ?>`,
+          },
+        ],
+      },
+    ],
+  },
+];

+ 96 - 0
static/app/gettingStartedDocs/php/laravel.tsx

@@ -5,6 +5,11 @@ import type {
   DocsParams,
   OnboardingConfig,
 } from 'sentry/components/onboarding/gettingStartedDoc/types';
+import {
+  getCrashReportModalConfigDescription,
+  getCrashReportModalIntroduction,
+  getCrashReportSDKInstallFirstStep,
+} from 'sentry/components/onboarding/gettingStartedDoc/utils/feedbackOnboarding';
 import replayOnboardingJsLoader from 'sentry/gettingStartedDocs/javascript/jsLoader/jsLoader';
 import {t, tct} from 'sentry/locale';
 
@@ -242,10 +247,101 @@ const customMetricsOnboarding: OnboardingConfig = {
   ],
 };
 
+const crashReportOnboarding: OnboardingConfig = {
+  introduction: () => getCrashReportModalIntroduction(),
+  install: (params: Params) => [
+    {
+      type: StepType.INSTALL,
+      configurations: [
+        getCrashReportSDKInstallFirstStep(params),
+        {
+          description: tct(
+            'Next, create [code:resources/views/errors/500.blade.php], and embed the feedback code:',
+            {code: <code />}
+          ),
+          code: [
+            {
+              label: 'HTML',
+              value: 'html',
+              language: 'html',
+              code: `<div class="content">
+  <div class="title">Something went wrong.</div>
+
+  @if(app()->bound('sentry') && app('sentry')->getLastEventId())
+  <div class="subtitle">Error ID: {{ app('sentry')->getLastEventId() }}</div>
+  <script>
+    Sentry.init({ dsn: '${params.dsn}' });
+    Sentry.showReportDialog({
+      eventId: '{{ app('sentry')->getLastEventId() }}'
+    });
+  </script>
+  @endif
+</div>`,
+            },
+          ],
+        },
+        {
+          description: tct(
+            'For Laravel 5 up to 5.4 there is some extra work needed. You need to open up [codeApp:App/Exceptions/Handler.php] and extend the [codeRender:render] method to make sure the 500 error is rendered as a view correctly, in 5.5+ this step is not required anymore.',
+            {code: <code />}
+          ),
+          code: [
+            {
+              label: 'PHP',
+              value: 'php',
+              language: 'php',
+              code: `<?php
+
+use Symfony\Component\HttpKernel\Exception\HttpException;
+
+class Handler extends ExceptionHandler
+{
+    public function report(Exception $exception)
+    {
+        if (app()->bound('sentry') && $this->shouldReport($exception)) {
+            app('sentry')->captureException($exception);
+        }
+
+        parent::report($exception);
+    }
+
+    // This method is ONLY needed for Laravel 5 up to 5.4.
+    // You can skip this method if you are using Laravel 5.5+.
+    public function render($request, Exception $exception)
+    {
+        // Convert all non-http exceptions to a proper 500 http exception
+        // if we don't do this exceptions are shown as a default template
+        // instead of our own view in resources/views/errors/500.blade.php
+        if ($this->shouldReport($exception) && !$this->isHttpException($exception) && !config('app.debug')) {
+            $exception = new HttpException(500, 'Whoops!');
+        }
+
+        return parent::render($request, $exception);
+    }
+}`,
+            },
+          ],
+        },
+      ],
+    },
+  ],
+  configure: () => [
+    {
+      type: StepType.CONFIGURE,
+      description: getCrashReportModalConfigDescription({
+        link: 'https://docs.sentry.io/platforms/php/guides/laravel/user-feedback/configuration/#crash-report-modal',
+      }),
+    },
+  ],
+  verify: () => [],
+  nextSteps: () => [],
+};
+
 const docs: Docs = {
   onboarding,
   replayOnboardingJsLoader,
   customMetricsOnboarding,
+  crashReportOnboarding,
 };
 
 export default docs;

+ 21 - 0
static/app/gettingStartedDocs/php/php.tsx

@@ -5,6 +5,11 @@ import type {
   DocsParams,
   OnboardingConfig,
 } from 'sentry/components/onboarding/gettingStartedDoc/types';
+import {
+  getCrashReportModalConfigDescription,
+  getCrashReportModalIntroduction,
+  getCrashReportPHPInstallStep,
+} from 'sentry/components/onboarding/gettingStartedDoc/utils/feedbackOnboarding';
 import replayOnboardingJsLoader from 'sentry/gettingStartedDocs/javascript/jsLoader/jsLoader';
 import {t, tct} from 'sentry/locale';
 
@@ -202,10 +207,26 @@ const customMetricsOnboarding: OnboardingConfig = {
   ],
 };
 
+const crashReportOnboarding: OnboardingConfig = {
+  introduction: () => getCrashReportModalIntroduction(),
+  install: (params: Params) => getCrashReportPHPInstallStep(params),
+  configure: () => [
+    {
+      type: StepType.CONFIGURE,
+      description: getCrashReportModalConfigDescription({
+        link: 'https://docs.sentry.io/platforms/php/user-feedback/configuration/#crash-report-modal',
+      }),
+    },
+  ],
+  verify: () => [],
+  nextSteps: () => [],
+};
+
 const docs: Docs = {
   onboarding,
   replayOnboardingJsLoader,
   customMetricsOnboarding,
+  crashReportOnboarding,
 };
 
 export default docs;

+ 21 - 0
static/app/gettingStartedDocs/php/symfony.tsx

@@ -5,6 +5,11 @@ import type {
   DocsParams,
   OnboardingConfig,
 } from 'sentry/components/onboarding/gettingStartedDoc/types';
+import {
+  getCrashReportModalConfigDescription,
+  getCrashReportModalIntroduction,
+  getCrashReportPHPInstallStep,
+} from 'sentry/components/onboarding/gettingStartedDoc/utils/feedbackOnboarding';
 import replayOnboardingJsLoader from 'sentry/gettingStartedDocs/javascript/jsLoader/jsLoader';
 import {t, tct} from 'sentry/locale';
 
@@ -143,9 +148,25 @@ SENTRY_DSN="${params.dsn}"
   nextSteps: () => [],
 };
 
+const crashReportOnboarding: OnboardingConfig = {
+  introduction: () => getCrashReportModalIntroduction(),
+  install: (params: Params) => getCrashReportPHPInstallStep(params),
+  configure: () => [
+    {
+      type: StepType.CONFIGURE,
+      description: getCrashReportModalConfigDescription({
+        link: 'https://docs.sentry.io/platforms/php/guides/symfony/user-feedback/configuration/#crash-report-modal',
+      }),
+    },
+  ],
+  verify: () => [],
+  nextSteps: () => [],
+};
+
 const docs: Docs = {
   onboarding,
   replayOnboardingJsLoader,
+  crashReportOnboarding,
 };
 
 export default docs;

+ 57 - 0
static/app/gettingStartedDocs/ruby/rails.tsx

@@ -1,9 +1,15 @@
+import ExternalLink from 'sentry/components/links/externalLink';
 import {StepType} from 'sentry/components/onboarding/gettingStartedDoc/step';
 import type {
   Docs,
   DocsParams,
   OnboardingConfig,
 } from 'sentry/components/onboarding/gettingStartedDoc/types';
+import {
+  getCrashReportModalConfigDescription,
+  getCrashReportModalIntroduction,
+  getCrashReportSDKInstallFirstStepRails,
+} from 'sentry/components/onboarding/gettingStartedDoc/utils/feedbackOnboarding';
 import replayOnboardingJsLoader from 'sentry/gettingStartedDocs/javascript/jsLoader/jsLoader';
 import {t, tct} from 'sentry/locale';
 
@@ -82,9 +88,60 @@ const onboarding: OnboardingConfig = {
   nextSteps: () => [],
 };
 
+const crashReportOnboarding: OnboardingConfig = {
+  introduction: () => getCrashReportModalIntroduction(),
+  install: (params: Params) => [
+    {
+      type: StepType.INSTALL,
+      description: tct(
+        "In Rails, being able to serve dynamic pages in response to errors is required to pass the needed [codeEvent:event_id] to the JavaScript SDK. [link:Read our docs] to learn more. Once you're able to serve dynamic exception pages, you can support user feedback.",
+        {
+          codeEvent: <code />,
+          link: (
+            <ExternalLink href="https://docs.sentry.io/platforms/ruby/guides/rails/user-feedback/#integration" />
+          ),
+        }
+      ),
+      configurations: [
+        getCrashReportSDKInstallFirstStepRails(params),
+        {
+          description: t(
+            'Additionally, you need the template that brings up the dialog:'
+          ),
+          code: [
+            {
+              label: 'ERB',
+              value: 'erb',
+              language: 'erb',
+              code: `<% sentry_id = request.env["sentry.error_event_id"] %>
+<% if sentry_id.present? %>
+<script>
+  Sentry.init({ dsn: "${params.dsn}" });
+  Sentry.showReportDialog({ eventId: "<%= sentry_id %>" });
+</script>
+<% end %>`,
+            },
+          ],
+        },
+      ],
+    },
+  ],
+  configure: () => [
+    {
+      type: StepType.CONFIGURE,
+      description: getCrashReportModalConfigDescription({
+        link: 'https://docs.sentry.io/platforms/ruby/guides/rails/user-feedback/configuration/#crash-report-modal',
+      }),
+    },
+  ],
+  verify: () => [],
+  nextSteps: () => [],
+};
+
 const docs: Docs = {
   onboarding,
   replayOnboardingJsLoader,
+  crashReportOnboarding,
 };
 
 export default docs;