Browse Source

Python "Create Project" wizards (part 2): `celery`, `chalice`, `django`, `falcon`, `fastapi` (#56545)

Updated getting started wizards for Python platforms: `celery`, `chalice`, `django`, `falcon`, `fastapi`
Making sure the feature checkboxes are there and work and also a "Verify" section is present.

---------

Co-authored-by: ArthurKnaus <arthur.knaus@sentry.io>
Anton Pirker 1 year ago
parent
commit
e4a6931949

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

@@ -126,7 +126,6 @@ export const platformProductAvailability = {
   'python-awslambda': [ProductSolution.PERFORMANCE_MONITORING, ProductSolution.PROFILING],
   'python-bottle': [ProductSolution.PERFORMANCE_MONITORING, ProductSolution.PROFILING],
   'python-celery': [ProductSolution.PERFORMANCE_MONITORING, ProductSolution.PROFILING],
-  'python-chalice': [ProductSolution.PERFORMANCE_MONITORING, ProductSolution.PROFILING],
   'python-django': [ProductSolution.PERFORMANCE_MONITORING, ProductSolution.PROFILING],
   'python-falcon': [ProductSolution.PERFORMANCE_MONITORING, ProductSolution.PROFILING],
   'python-fastapi': [ProductSolution.PERFORMANCE_MONITORING, ProductSolution.PROFILING],

+ 123 - 22
static/app/gettingStartedDocs/python/celery.tsx

@@ -1,24 +1,26 @@
 import {Fragment} from 'react';
+import styled from '@emotion/styled';
 
+import Alert from 'sentry/components/alert';
+import {CodeSnippet} from 'sentry/components/codeSnippet';
 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 {t, tct} from 'sentry/locale';
+import {space} from 'sentry/styles/space';
 
 // 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 performanceConfiguration = `    # Set traces_sample_rate to 1.0 to capture 100%
-    # of transactions for performance monitoring.
-    # We recommend adjusting this value in production.
-    traces_sample_rate=1.0,`;
-
 const introduction = (
   <p>
     {tct('The celery integration adds support for the [link:Celery Task Queue System].', {
@@ -33,24 +35,48 @@ export const steps = ({
   sentryInitContent: string;
 }): LayoutProps['steps'] => [
   {
-    type: StepType.CONFIGURE,
+    type: StepType.INSTALL,
     description: (
       <p>
-        {tct(
-          'Just add [celeryIntegrationCode:CeleryIntegration()] to your [integrationsCode:integrations] list:',
-          {
-            celeryIntegrationCode: <code />,
-            integrationsCode: <code />,
-          }
-        )}
+        {tct('Install [code:sentry-sdk] from PyPI with the [code:celery] extra:', {
+          code: <code />,
+        })}
       </p>
     ),
+    configurations: [
+      {
+        language: 'bash',
+        code: 'pip install --upgrade sentry-sdk[celery]',
+      },
+    ],
+  },
+  {
+    type: StepType.CONFIGURE,
+    description: (
+      <div>
+        <p>
+          {tct(
+            'If you have the [code:celery] package in your dependencies, the Celery integration will be enabled automatically when you initialize the Sentry SDK.',
+            {
+              code: <code />,
+            }
+          )}
+        </p>
+        <p>
+          {tct(
+            'Make sure that the call to [code:init] is loaded on worker startup, and not only in the module where your tasks are defined. Otherwise, the initialization happens too late and events might end up not being reported.',
+            {
+              code: <code />,
+            }
+          )}
+        </p>
+      </div>
+    ),
     configurations: [
       {
         language: 'python',
         code: `
 import sentry_sdk
-from sentry_sdk.integrations.celery import CeleryIntegration
 
 sentry_sdk.init(
 ${sentryInitContent}
@@ -60,15 +86,88 @@ ${sentryInitContent}
     ],
     additionalInfo: (
       <Fragment>
-        {t(
-          'Additionally, the Sentry Python SDK will set the transaction on the event to the task name, and it will improve the grouping for global Celery errors such as timeouts.'
-        )}
+        <h5>{t('Standalone Setup')}</h5>
+        {t("If you're using Celery standalone, there are two ways to set this up:")}
+        <ul>
+          <li>
+            {tct(
+              "Initializing the SDK in the configuration file loaded with Celery's [code:--config] parameter",
+              {
+                code: <code />,
+              }
+            )}
+          </li>
+          <li>
+            {tct(
+              'Initializing the SDK by hooking it to either the [celerydInit: celeryd_init] or [workerInit: worker_init] signals:',
+              {
+                celerydInit: (
+                  <ExternalLink href="https://docs.celeryq.dev/en/stable/userguide/signals.html?#celeryd-init" />
+                ),
+                workerInit: (
+                  <ExternalLink href="https://docs.celeryq.dev/en/stable/userguide/signals.html?#worker-init" />
+                ),
+              }
+            )}
+            <CodeSnippet dark language="python">
+              {`import sentry_sdk
+from celery import Celery, signals
+
+app = Celery("myapp")
+
+#@signals.worker_init.connect
+@signals.celeryd_init.connect
+def init_sentry(**_kwargs):
+    sentry_sdk.init(...)  # same as above
+              `}
+            </CodeSnippet>
+          </li>
+        </ul>
+        <h5>{t('Setup With Django')}</h5>
         <p>
-          {t('The integration will automatically report errors from all celery jobs.')}
+          {tct(
+            "If you're using Celery with Django in a conventional setup, have already initialized the SDK in [settingsLink:your settings.py], and have Celery using the same settings with [celeryDocsLinks:config_from_object], you don't need to initialize the SDK separately for Celery.",
+            {
+              settingsLink: (
+                <ExternalLink href="https://docs.sentry.io/platforms/python/guides/django/#configure" />
+              ),
+              celeryDocsLinks: (
+                <ExternalLink href="https://docs.celeryq.dev/en/stable/django/first-steps-with-django.html" />
+              ),
+            }
+          )}
         </p>
       </Fragment>
     ),
   },
+  {
+    type: StepType.VERIFY,
+    description: (
+      <div>
+        <p>
+          {t(
+            "To verify if your SDK is initialized on worker start, you can pass `debug=True` to `sentry_sdk.init()` to see extra output when the SDK is initialized. If the output appears during worker startup and not only after a task has started, then it's working properly."
+          )}
+        </p>
+        <AlertWithMarginBottom type="info">
+          {tct(
+            `Sentry uses custom message headers for distributed tracing. For Celery versions 4.x, with [celeryDocLink: message protocol of version 1], this functionality is broken, and Celery fails to propagate custom headers to the worker. Protocol version 2, which is the default since Celery version 4.0, is not affected.
+
+            The fix for the custom headers propagation issue was introduced to Celery project ([celeryPRLink: PR]) starting with version 5.0.1. However, the fix was not backported to versions 4.x.
+            `,
+            {
+              celeryDocLink: (
+                <ExternalLink href="https://docs.celeryq.dev/en/stable/internals/protocol.html#version-1" />
+              ),
+              celeryPRLink: (
+                <ExternalLink href="https://github.com/celery/celery/pull/6374" />
+              ),
+            }
+          )}
+        </AlertWithMarginBottom>
+      </div>
+    ),
+  },
 ];
 // Configuration End
 
@@ -79,10 +178,7 @@ export function GettingStartedWithCelery({
 }: ModuleProps) {
   const otherConfigs: string[] = [];
 
-  let sentryInitContent: string[] = [
-    `    dsn="${dsn}",`,
-    `    integrations=[CeleryIntegration()],`,
-  ];
+  let sentryInitContent: string[] = [`    dsn="${dsn}",`];
 
   if (activeProductSelection.includes(ProductSolution.PERFORMANCE_MONITORING)) {
     otherConfigs.push(performanceConfiguration);
@@ -106,3 +202,8 @@ export function GettingStartedWithCelery({
 }
 
 export default GettingStartedWithCelery;
+
+const AlertWithMarginBottom = styled(Alert)`
+  margin-top: ${space(2)};
+  margin-bottom: 0;
+`;

+ 49 - 29
static/app/gettingStartedDocs/python/chalice.tsx

@@ -1,21 +1,9 @@
 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 {tct} from 'sentry/locale';
+import {t, tct} from 'sentry/locale';
 
 // Configuration Start
-
-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 performanceConfiguration = `    # Set traces_sample_rate to 1.0 to capture 100%
-    # of transactions for performance monitoring.
-    # We recommend adjusting this value in production.
-    traces_sample_rate=1.0,`;
-
 export const steps = ({
   sentryInitContent,
 }: {
@@ -25,9 +13,13 @@ export const steps = ({
     type: StepType.INSTALL,
     description: (
       <p>
-        {tct('Install [code:sentry-sdk] from PyPI:', {
-          code: <code />,
-        })}
+        {tct(
+          'Install [sentrySdkCode:sentry-sdk] from PyPI with the [sentryBotteCode:chalice] extra:',
+          {
+            sentrySdkCode: <code />,
+            sentryBotteCode: <code />,
+          }
+        )}
       </p>
     ),
     configurations: [
@@ -39,6 +31,9 @@ export const steps = ({
   },
   {
     type: StepType.CONFIGURE,
+    description: t(
+      'To configure the SDK, initialize it with the integration before or after your app has been initialized:'
+    ),
     configurations: [
       {
         language: 'python',
@@ -58,14 +53,47 @@ app = Chalice(app_name="appname")
       },
     ],
   },
+  {
+    type: StepType.VERIFY,
+    description: (
+      <p>{t('To verify that everything is working trigger an error on purpose:')}</p>
+    ),
+    configurations: [
+      {
+        language: 'python',
+        code: `from chalice import Chalice
+
+sentry_sdk.init(
+${sentryInitContent}
+)
+
+app = Chalice(app_name="helloworld")
+
+@app.schedule(Rate(1, unit=Rate.MINUTES))
+def every_minute(event):
+    1/0  # raises an error
+
+@app.route("/")
+def index():
+    1/0  # raises an error
+    return {"hello": "world"}`,
+      },
+    ],
+    additionalInfo: (
+      <p>
+        {tct(
+          'When you enter the [code:"/"] route or the scheduled task is run, an error event will be sent to Sentry.',
+          {
+            code: <code />,
+          }
+        )}
+      </p>
+    ),
+  },
 ];
 // Configuration End
 
-export function GettingStartedWithChalice({
-  dsn,
-  activeProductSelection = [],
-  ...props
-}: ModuleProps) {
+export function GettingStartedWithChalice({dsn, ...props}: ModuleProps) {
   const otherConfigs: string[] = [];
 
   let sentryInitContent: string[] = [
@@ -73,14 +101,6 @@ export function GettingStartedWithChalice({
     `    integrations=[ChaliceIntegration()],`,
   ];
 
-  if (activeProductSelection.includes(ProductSolution.PERFORMANCE_MONITORING)) {
-    otherConfigs.push(performanceConfiguration);
-  }
-
-  if (activeProductSelection.includes(ProductSolution.PROFILING)) {
-    otherConfigs.push(profilingConfiguration);
-  }
-
   sentryInitContent = sentryInitContent.concat(otherConfigs);
 
   return (

+ 55 - 30
static/app/gettingStartedDocs/python/django.tsx

@@ -6,20 +6,22 @@ import {ProductSolution} from 'sentry/components/onboarding/productSelection';
 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 performanceConfiguration = `    # Set traces_sample_rate to 1.0 to capture 100%
-    # of transactions for performance monitoring.
-    # We recommend adjusting this value in production.
-    traces_sample_rate=1.0,`;
-
-const piiConfiguration = `    # If you wish to associate users to errors (assuming you are using
-    # django.contrib.auth) you may enable sending PII data.
-    send_default_pii=True,`;
+const introduction = (
+  <p>
+    {tct('The Django integration adds support for the [link:Django Web Framework].', {
+      link: <ExternalLink href="https://www.djangoproject.com/" />,
+    })}
+  </p>
+);
 
 export const steps = ({
   sentryInitContent,
@@ -30,17 +32,26 @@ export const steps = ({
     type: StepType.INSTALL,
     description: (
       <p>
-        {tct(
-          'The Django integration adds support for the [link:Django Web Framework] from Version 1.6 upwards.',
-          {link: <ExternalLink href="https://www.djangoproject.com/" />}
-        )}
+        {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]:', {code: <code />})}</p>,
-        code: 'pip install --upgrade sentry-sdk',
+        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]',
       },
     ],
   },
@@ -49,17 +60,19 @@ export const steps = ({
     description: (
       <p>
         {tct(
-          'To configure the SDK, initialize it with the Django integration in your [code:settings.py] file:',
-          {code: <code />}
+          '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: `
+        code: `# settings.py
 import sentry_sdk
-from sentry_sdk.integrations.django import DjangoIntegration
 
 sentry_sdk.init(
 ${sentryInitContent}
@@ -76,21 +89,36 @@ ${sentryInitContent}
       {
         language: 'python',
 
-        code: `
+        code: `# urls.py
 from django.urls import path
 
 def trigger_error(request):
     division_by_zero = 1 / 0
 
-    urlpatterns = [
-        path('sentry-debug/', trigger_error),
-        # ...
-    ]
+urlpatterns = [
+    path('sentry-debug/', trigger_error),
+    # ...
+]
         `,
       },
     ],
-    additionalInfo: t(
-      'Visiting this route will trigger an error that will be captured by Sentry.'
+    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>
     ),
   },
 ];
@@ -103,11 +131,7 @@ export function GettingStartedWithDjango({
 }: ModuleProps) {
   const otherConfigs: string[] = [];
 
-  let sentryInitContent: string[] = [
-    `    dsn="${dsn}",`,
-    `    integrations=[DjangoIntegration()],`,
-    piiConfiguration,
-  ];
+  let sentryInitContent: string[] = [`    dsn="${dsn}",`];
 
   if (activeProductSelection.includes(ProductSolution.PERFORMANCE_MONITORING)) {
     otherConfigs.push(performanceConfiguration);
@@ -121,6 +145,7 @@ export function GettingStartedWithDjango({
 
   return (
     <Layout
+      introduction={introduction}
       steps={steps({
         sentryInitContent: sentryInitContent.join('\n'),
       })}

+ 61 - 18
static/app/gettingStartedDocs/python/falcon.tsx

@@ -6,25 +6,20 @@ import {ProductSolution} from 'sentry/components/onboarding/productSelection';
 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 performanceConfiguration = `    # Set traces_sample_rate to 1.0 to capture 100%
-    # of transactions for performance monitoring.
-    # We recommend adjusting this value in production.
-    traces_sample_rate=1.0,`;
-
 const introduction = (
   <p>
-    {tct(
-      'The Falcon integration adds support for the [link:Falcon Web Framework]. The integration has been confirmed to work with Falcon 1.4 and 2.0.',
-      {
-        link: <ExternalLink href="https://falconframework.org/" />,
-      }
-    )}
+    {tct('The Falcon integration adds support for the [link:Falcon Web Framework].', {
+      link: <ExternalLink href="https://falconframework.org/" />,
+    })}
   </p>
 );
 
@@ -55,8 +50,15 @@ export const steps = ({
   },
   {
     type: StepType.CONFIGURE,
-    description: t(
-      'To configure the SDK, initialize it with the integration before your app has been initialized:'
+    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: [
       {
@@ -64,7 +66,6 @@ export const steps = ({
         code: `
 import falcon
 import sentry_sdk
-from sentry_sdk.integrations.falcon import FalconIntegration
 
 sentry_sdk.init(
 ${sentryInitContent}
@@ -75,6 +76,51 @@ 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}
+)
+
+class HelloWorldResource:
+    def on_get(self, req, resp):
+        message = {
+            'hello': "world",
+        }
+        1 / 0  # raises an error
+        resp.media = message
+
+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
 
@@ -85,10 +131,7 @@ export function GettingStartedWithFalcon({
 }: ModuleProps) {
   const otherConfigs: string[] = [];
 
-  let sentryInitContent: string[] = [
-    `    dsn="${dsn}",`,
-    `    integrations=[FalconIntegration()],`,
-  ];
+  let sentryInitContent: string[] = [`    dsn="${dsn}",`];
 
   if (activeProductSelection.includes(ProductSolution.PERFORMANCE_MONITORING)) {
     otherConfigs.push(performanceConfiguration);

+ 36 - 11
static/app/gettingStartedDocs/python/fastapi.tsx

@@ -6,17 +6,15 @@ import {ProductSolution} from 'sentry/components/onboarding/productSelection';
 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 performanceConfiguration = `    # Set traces_sample_rate to 1.0 to capture 100%
-    # of transactions for performance monitoring.
-    # We recommend adjusting this value in production.
-    traces_sample_rate=1.0,`;
-
 const introduction = (
   <p>
     {tct('The FastAPI integration adds support for the [link:FastAPI Framework].', {
@@ -52,8 +50,15 @@ export const steps = ({
   },
   {
     type: StepType.CONFIGURE,
-    description: t(
-      'To configure the Sentry SDK, initialize it before your app has been initialized:'
+    description: (
+      <p>
+        {tct(
+          'If you have the [codeFastAPI:fastapi] package in your dependencies, the FastAPI integration will be enabled automatically when you initialize the Sentry SDK. Initialize the Sentry SDK before your app has been initialized:',
+          {
+            codeFastAPI: <code />,
+          }
+        )}
+      </p>
     ),
     configurations: [
       {
@@ -63,7 +68,6 @@ from fastapi import FastAPI
 
 import sentry_sdk
 
-
 sentry_sdk.init(
 ${sentryInitContent}
 )
@@ -94,16 +98,37 @@ app = FastAPI()
         code: `
 from fastapi import FastAPI
 
+import sentry_sdk
+
+sentry_sdk.init(
+${sentryInitContent}
+)
+
 app = FastAPI()
 
 @app.get("/sentry-debug")
 async def trigger_error():
-division_by_zero = 1 / 0
+    division_by_zero = 1 / 0
       `,
       },
     ],
-    additionalInfo: t(
-      'Visiting this route will trigger an error that will be captured by Sentry.'
+    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/sentry-debug/" />,
+            }
+          )}
+        </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>
     ),
   },
 ];