Browse Source

Python "Create Project" wizards (part 1): `asgi`, `aiohttp`, `awslambda`, and `bottle` (#56468)

Update "Getting Started" wizards for Python platforms: `asgi`,
`aiohttp`, `awslambda`, and `bottle`.

Making sure the feature checkboxes are there and work and also a
"Verify" section is present.
Anton Pirker 1 year ago
parent
commit
fbc865e8b7

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

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

+ 62 - 14
static/app/gettingStartedDocs/python/aiohttp.tsx

@@ -6,21 +6,19 @@ 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 AIOHTTP integration adds support for the [link:AIOHTTP-Server Web Framework]. A Python version of 3.6 or greater is required.',
+      'The AIOHTTP integration adds support for the [link:AIOHTTP-Server Web Framework].',
       {
         link: <ExternalLink href="https://docs.aiohttp.org/en/stable/web.html" />,
       }
@@ -65,20 +63,28 @@ export const steps = ({
   },
   {
     type: StepType.CONFIGURE,
-    description: t('Initialize the SDK before starting the server:'),
+    description: (
+      <p>
+        {tct(
+          'If you have the [code:aiohttp] package in your dependencies, the AIOHTTO integration will be enabled automatically. There is nothing to do for you except initializing the Sentry SDK before initializing your application:',
+          {
+            code: <code />,
+          }
+        )}
+      </p>
+    ),
     configurations: [
       {
         language: 'python',
         code: `
+from aiohttp import web
+
 import sentry_sdk
-from sentry_sdk.integrations.aiohttp import AioHttpIntegration
 
 sentry_sdk.init(
 ${sentryInitContent}
 )
 
-from aiohttp import web
-
 async def hello(request):
     return web.Response(text="Hello, world")
 
@@ -90,6 +96,51 @@ web.run_app(app)
       },
     ],
   },
+  {
+    type: StepType.VERIFY,
+    description: t(
+      'You can easily verify your Sentry installation by creating a route that triggers an error:'
+    ),
+    configurations: [
+      {
+        language: 'python',
+
+        code: `
+from aiohttp import web
+
+sentry_sdk.init(
+${sentryInitContent}
+)
+
+async def hello(request):
+    1/0  # raises an error
+    return web.Response(text="Hello, world")
+
+app = web.Application()
+app.add_routes([web.get('/', hello)])
+
+web.run_app(app)`,
+      },
+    ],
+    additionalInfo: (
+      <span>
+        <p>
+          {tct(
+            `When you point your browser to [localhostLInk:http://localhost:8080/] a transaction in the Performance section of Sentry will be created.`,
+            {
+              localhostLInk: <ExternalLink href="http://localhost:8080/" />,
+            }
+          )}
+        </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
 
@@ -100,10 +151,7 @@ export function GettingStartedWithAIOHTTP({
 }: ModuleProps) {
   const otherConfigs: string[] = [];
 
-  let sentryInitContent: string[] = [
-    `    dsn="${dsn}",`,
-    `    integrations=[AioHttpIntegration()],`,
-  ];
+  let sentryInitContent: string[] = [`    dsn="${dsn}",`];
 
   if (activeProductSelection.includes(ProductSolution.PERFORMANCE_MONITORING)) {
     otherConfigs.push(performanceConfiguration);

+ 1 - 1
static/app/gettingStartedDocs/python/asgi.spec.tsx

@@ -9,7 +9,7 @@ describe('GettingStartedWithASGI', function () {
     render(<GettingStartedWithASGI dsn="test-dsn" />);
 
     // Steps
-    for (const step of steps()) {
+    for (const step of steps({sentryInitContent: 'test-init-content'})) {
       expect(
         screen.getByRole('heading', {name: step.title ?? StepTitle[step.type]})
       ).toBeInTheDocument();

+ 106 - 19
static/app/gettingStartedDocs/python/asgi.tsx

@@ -2,13 +2,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 {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 introduction = (
   <p>
     {tct(
-      'The ASGI middleware can be used to instrument any [link:ASGI-compatible web framework] to attach request data for your events.',
+      'The ASGI middleware can be used to instrument any bare bones ASGI application. If you have a ASGI based web framework (like FastAPI, Starlette, or others), please use the specific integration for the framework.',
       {
         link: <ExternalLink href="https://asgi.readthedocs.io/en/latest/" />,
       }
@@ -17,21 +22,33 @@ const introduction = (
 );
 
 export const steps = ({
-  dsn,
-}: Partial<Pick<ModuleProps, 'dsn'>> = {}): LayoutProps['steps'] => [
+  sentryInitContent,
+}: {
+  sentryInitContent: string;
+}): LayoutProps['steps'] => [
+  {
+    type: StepType.INSTALL,
+    description: (
+      <p>
+        {tct('Install [code:sentry-sdk] from PyPI:', {
+          code: <code />,
+        })}
+      </p>
+    ),
+    configurations: [
+      {
+        language: 'bash',
+        code: '$ pip install --upgrade sentry-sdk',
+      },
+    ],
+  },
   {
     type: StepType.CONFIGURE,
     description: (
       <p>
-        {tct(
-          'This can be used to instrument, for example [starletteLink:Starlette] or [djangoLink:Django Channels 2.0].',
-          {
-            starletteLink: <ExternalLink href="https://www.starlette.io/middleware/" />,
-            djangoLink: (
-              <ExternalLink href="https://channels.readthedocs.io/en/latest/" />
-            ),
-          }
-        )}
+        {tct('Wrap your ASGI application with [code: SentryAsgiMiddleware]:', {
+          code: <code />,
+        })}
       </p>
     ),
     configurations: [
@@ -44,11 +61,7 @@ from sentry_sdk.integrations.asgi import SentryAsgiMiddleware
 from myapp import asgi_app
 
 sentry_sdk.init(
-    dsn="${dsn}",
-    # 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,
+${sentryInitContent}
 )
 
 asgi_app = SentryAsgiMiddleware(asgi_app)
@@ -57,11 +70,85 @@ asgi_app = SentryAsgiMiddleware(asgi_app)
     ],
     additionalInfo: t('The middleware supports both ASGI 2 and ASGI 3 transparently.'),
   },
+  {
+    type: StepType.VERIFY,
+    description: (
+      <p>{t('To verify that everything is working trigger an error on purpose:')}</p>
+    ),
+    configurations: [
+      {
+        language: 'python',
+        code: `sentry_sdk.init(
+${sentryInitContent}
+)
+
+def app(scope):
+    async def get_body():
+        return f"The number is: {1/0}" # raises an error!
+
+    async def asgi(receive, send):
+        await send(
+            {
+                "type": "http.response.start",
+                "status": 200,
+                "headers": [[b"content-type", b"text/plain"]],
+            }
+        )
+        await send({"type": "http.response.body", "body": await get_body()})
+
+    return asgi
+
+app = SentryAsgiMiddleware(app)
+      `,
+      },
+    ],
+    additionalInfo: (
+      <span>
+        <p>
+          {tct(
+            'Run your ASGI app with uvicorn ([code:uvicorn main:app --port 8000]) and point your browser to [link:http://localhost:8000]. A transaction in the Performance section of Sentry will be created.',
+            {
+              code: <code />,
+              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 GettingStartedWithASGI({dsn, ...props}: ModuleProps) {
-  return <Layout steps={steps({dsn})} introduction={introduction} {...props} />;
+export function GettingStartedWithASGI({
+  dsn,
+  activeProductSelection = [],
+  ...props
+}: ModuleProps) {
+  const otherConfigs: string[] = [];
+
+  let sentryInitContent: string[] = [`    dsn="${dsn}",`];
+
+  if (activeProductSelection.includes(ProductSolution.PERFORMANCE_MONITORING)) {
+    otherConfigs.push(performanceConfiguration);
+  }
+
+  sentryInitContent = sentryInitContent.concat(otherConfigs);
+
+  return (
+    <Layout
+      introduction={introduction}
+      steps={steps({
+        sentryInitContent: sentryInitContent.join('\n'),
+      })}
+      {...props}
+    />
+  );
 }
 
 export default GettingStartedWithASGI;

+ 3 - 5
static/app/gettingStartedDocs/python/awslambda.tsx

@@ -11,17 +11,15 @@ 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(

+ 63 - 20
static/app/gettingStartedDocs/python/bottle.tsx

@@ -6,25 +6,21 @@ 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.
+    # We recommend adjusting this value in production.
+    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 Bottle integration adds support for the Bottle Web Framework. Currently it works well with the stable version of Bottle (0.12). However the integration with the development version (0.13) doesn't work properly.",
-      {
-        link: <ExternalLink href="https://bottlepy.org/docs/dev/" />,
-      }
-    )}
+    {tct('The Bottle integration adds support for the [link:Bottle Web Framework].', {
+      link: <ExternalLink href="https://bottlepy.org/docs/dev/" />,
+    })}
   </p>
 );
 
@@ -49,14 +45,21 @@ export const steps = ({
     configurations: [
       {
         language: 'bash',
-        code: 'pip install --upgrade sentry-sdk[chalice]',
+        code: 'pip install --upgrade sentry-sdk[bottle]',
       },
     ],
   },
   {
     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 [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: [
       {
@@ -64,8 +67,7 @@ export const steps = ({
         code: `
 import sentry_sdk
 
-from bottle import Bottle, run
-from sentry_sdk.integrations.bottle import BottleIntegration
+from bottle import Bottle
 
 sentry_sdk.init(
 ${sentryInitContent}
@@ -76,6 +78,50 @@ 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}
+)
+
+app = Bottle()
+
+@app.route('/')
+def hello():
+    1/0
+    return "Hello World!"
+
+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
 
@@ -86,10 +132,7 @@ export function GettingStartedWithBottle({
 }: ModuleProps) {
   const otherConfigs: string[] = [];
 
-  let sentryInitContent: string[] = [
-    `    dsn="${dsn}",`,
-    `    integrations=[BottleIntegration()],`,
-  ];
+  let sentryInitContent: string[] = [`    dsn="${dsn}",`];
 
   if (activeProductSelection.includes(ProductSolution.PERFORMANCE_MONITORING)) {
     otherConfigs.push(performanceConfiguration);