Browse Source

feat(profiling): Add continuous profiling onboarding docs for python (#79464)

This adds continuous profiling onboarding docs for all python platforms.
Tony Xiao 4 months ago
parent
commit
7805e56c6a

+ 5 - 0
static/app/components/onboarding/gettingStartedDoc/onboardingLayout.tsx

@@ -101,6 +101,11 @@ export function OnboardingLayout({
       isSelfHosted,
       platformOptions: selectedOptions,
       newOrg,
+      profilingOptions: {
+        defaultProfilingMode: organization.features.includes('continuous-profiling')
+          ? 'continuous'
+          : 'transaction',
+      },
       replayOptions: {block: true, mask: true},
     };
 

+ 3 - 0
static/app/components/onboarding/gettingStartedDoc/types.ts

@@ -68,6 +68,9 @@ export interface DocsParams<
     screenshot?: boolean;
   };
   newOrg?: boolean;
+  profilingOptions?: {
+    defaultProfilingMode?: 'transaction' | 'continuous';
+  };
   replayOptions?: {
     block?: boolean;
     mask?: boolean;

+ 47 - 1
static/app/gettingStartedDocs/python/aiohttp.spec.tsx

@@ -1,3 +1,5 @@
+import {OrganizationFixture} from 'sentry-fixture/organization';
+
 import {renderWithOnboardingLayout} from 'sentry-test/onboarding/renderWithOnboardingLayout';
 import {screen} from 'sentry-test/reactTestingLibrary';
 import {textWithMarkupMatcher} from 'sentry-test/utils';
@@ -26,12 +28,56 @@ describe('aiohttp onboarding docs', function () {
 
     // Does not render config option
     expect(
-      screen.queryByText(textWithMarkupMatcher(/traces_sample_rate: 1\.0,/))
+      screen.queryByText(textWithMarkupMatcher(/profiles_sample_rate=1\.0,/))
     ).not.toBeInTheDocument();
 
     // Does not render config option
+    expect(
+      screen.queryByText(textWithMarkupMatcher(/traces_sample_rate=1\.0,/))
+    ).not.toBeInTheDocument();
+  });
+
+  it('renders transaction profiling', function () {
+    renderWithOnboardingLayout(docs);
+
+    // Does not render continuous profiling config
+    expect(
+      screen.queryByText(
+        textWithMarkupMatcher(/"continuous_profiling_auto_start": True,/)
+      )
+    ).not.toBeInTheDocument();
+
+    // Does render transaction profiling config
+    const matches = screen.getAllByText(
+      textWithMarkupMatcher(/profiles_sample_rate=1\.0,/)
+    );
+    expect(matches.length).toBeGreaterThan(0);
+    matches.forEach(match => expect(match).toBeInTheDocument());
+  });
+
+  it('renders continuous profiling', function () {
+    const organization = OrganizationFixture({
+      features: ['continuous-profiling'],
+    });
+
+    renderWithOnboardingLayout(
+      docs,
+      {},
+      {
+        organization,
+      }
+    );
+
+    // Does not render transaction profiling config
     expect(
       screen.queryByText(textWithMarkupMatcher(/profiles_sample_rate: 1\.0,/))
     ).not.toBeInTheDocument();
+
+    // Does render continuous profiling config
+    const matches = screen.getAllByText(
+      textWithMarkupMatcher(/"continuous_profiling_auto_start": True,/)
+    );
+    expect(matches.length).toBeGreaterThan(0);
+    matches.forEach(match => expect(match).toBeInTheDocument());
   });
 });

+ 26 - 8
static/app/gettingStartedDocs/python/aiohttp.tsx

@@ -8,7 +8,10 @@ import {
 } from 'sentry/components/onboarding/gettingStartedDoc/types';
 import {getPythonMetricsOnboarding} from 'sentry/components/onboarding/gettingStartedDoc/utils/metricsOnboarding';
 import replayOnboardingJsLoader from 'sentry/gettingStartedDocs/javascript/jsLoader/jsLoader';
-import {crashReportOnboardingPython} from 'sentry/gettingStartedDocs/python/python';
+import {
+  AlternativeConfiguration,
+  crashReportOnboardingPython,
+} from 'sentry/gettingStartedDocs/python/python';
 import {t, tct} from 'sentry/locale';
 
 type Params = DocsParams;
@@ -29,13 +32,23 @@ sentry_sdk.init(
     traces_sample_rate=1.0,`
         : ''
     }${
-      params.isProfilingSelected
+      params.isProfilingSelected &&
+      params.profilingOptions?.defaultProfilingMode === 'transaction'
         ? `
     # 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,`
-        : ''
+        : params.isProfilingSelected &&
+            params.profilingOptions?.defaultProfilingMode === 'continuous'
+          ? `
+    _experiments={
+        # Set continuous_profiling_auto_start to True
+        # to automatically start the profiler on when
+        # possible.
+        "continuous_profiling_auto_start": True,
+    },`
+          : ''
     }
 )
 `;
@@ -102,9 +115,13 @@ app = web.Application()
 app.add_routes([web.get('/', hello)])
 
 web.run_app(app)
-        `,
+`,
         },
       ],
+      additionalInfo: params.isProfilingSelected &&
+        params.profilingOptions?.defaultProfilingMode === 'continuous' && (
+          <AlternativeConfiguration />
+        ),
     },
   ],
   verify: (params: Params) => [
@@ -118,15 +135,16 @@ web.run_app(app)
           language: 'python',
 
           code: `
-          ${getSdkSetupSnippet(params)}
+${getSdkSetupSnippet(params)}
 async def hello(request):
-  1/0  # raises an error
-  return web.Response(text="Hello, world")
+    1/0  # raises an error
+    return web.Response(text="Hello, world")
 
 app = web.Application()
 app.add_routes([web.get('/', hello)])
 
-web.run_app(app)`,
+web.run_app(app)
+`,
         },
       ],
       additionalInfo: (

+ 46 - 2
static/app/gettingStartedDocs/python/asgi.spec.tsx

@@ -1,3 +1,5 @@
+import {OrganizationFixture} from 'sentry-fixture/organization';
+
 import {renderWithOnboardingLayout} from 'sentry-test/onboarding/renderWithOnboardingLayout';
 import {screen} from 'sentry-test/reactTestingLibrary';
 import {textWithMarkupMatcher} from 'sentry-test/utils';
@@ -26,12 +28,54 @@ describe('asgi onboarding docs', function () {
 
     // Does not render config option
     expect(
-      screen.queryByText(textWithMarkupMatcher(/traces_sample_rate: 1\.0,/))
+      screen.queryByText(textWithMarkupMatcher(/profiles_sample_rate=1\.0,/))
     ).not.toBeInTheDocument();
 
     // Does not render config option
     expect(
-      screen.queryByText(textWithMarkupMatcher(/profiles_sample_rate: 1\.0,/))
+      screen.queryByText(textWithMarkupMatcher(/traces_sample_rate=1\.0,/))
+    ).not.toBeInTheDocument();
+  });
+
+  it('renders transaction profiling', function () {
+    renderWithOnboardingLayout(docs);
+
+    // Does not render continuous profiling config
+    expect(
+      screen.queryByText(
+        textWithMarkupMatcher(/"continuous_profiling_auto_start": True,/)
+      )
+    ).not.toBeInTheDocument();
+
+    // Does render transaction profiling config
+    expect(
+      screen.queryByText(textWithMarkupMatcher(/profiles_sample_rate=1\.0,/))
+    ).toBeInTheDocument();
+  });
+
+  it('renders continuous profiling', function () {
+    const organization = OrganizationFixture({
+      features: ['continuous-profiling'],
+    });
+
+    renderWithOnboardingLayout(
+      docs,
+      {},
+      {
+        organization,
+      }
+    );
+
+    // Does not render transaction profiling config
+    expect(
+      screen.queryByText(textWithMarkupMatcher(/profiles_sample_rate=1\.0,/))
     ).not.toBeInTheDocument();
+
+    // Does render continuous profiling config
+    expect(
+      screen.queryByText(
+        textWithMarkupMatcher(/"continuous_profiling_auto_start": True,/)
+      )
+    ).toBeInTheDocument();
   });
 });

+ 30 - 4
static/app/gettingStartedDocs/python/asgi.tsx

@@ -1,3 +1,5 @@
+import {Fragment} from 'react';
+
 import ExternalLink from 'sentry/components/links/externalLink';
 import {StepType} from 'sentry/components/onboarding/gettingStartedDoc/step';
 import {
@@ -7,7 +9,10 @@ import {
   type OnboardingConfig,
 } from 'sentry/components/onboarding/gettingStartedDoc/types';
 import {getPythonMetricsOnboarding} from 'sentry/components/onboarding/gettingStartedDoc/utils/metricsOnboarding';
-import {crashReportOnboardingPython} from 'sentry/gettingStartedDocs/python/python';
+import {
+  AlternativeConfiguration,
+  crashReportOnboardingPython,
+} from 'sentry/gettingStartedDocs/python/python';
 import {t, tct} from 'sentry/locale';
 
 type Params = DocsParams;
@@ -29,13 +34,23 @@ sentry_sdk.init(
     traces_sample_rate=1.0,`
         : ''
     }${
-      params.isProfilingSelected
+      params.isProfilingSelected &&
+      params.profilingOptions?.defaultProfilingMode === 'transaction'
         ? `
     # 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,`
-        : ''
+        : params.isProfilingSelected &&
+            params.profilingOptions?.defaultProfilingMode === 'continuous'
+          ? `
+    _experiments={
+        # Set continuous_profiling_auto_start to True
+        # to automatically start the profiler on when
+        # possible.
+        "continuous_profiling_auto_start": True,
+    },`
+          : ''
     }
 )
 
@@ -109,7 +124,18 @@ const onboarding: OnboardingConfig = {
           code: getSdkSetupSnippet(params),
         },
       ],
-      additionalInfo: t('The middleware supports both ASGI 2 and ASGI 3 transparently.'),
+      additionalInfo: (
+        <Fragment>
+          {params.isProfilingSelected &&
+            params.profilingOptions?.defaultProfilingMode === 'continuous' && (
+              <Fragment>
+                <AlternativeConfiguration />
+                <br />
+              </Fragment>
+            )}
+          {t('The middleware supports both ASGI 2 and ASGI 3 transparently.')}
+        </Fragment>
+      ),
     },
   ],
   verify: () => [

+ 46 - 2
static/app/gettingStartedDocs/python/awslambda.spec.tsx

@@ -1,3 +1,5 @@
+import {OrganizationFixture} from 'sentry-fixture/organization';
+
 import {renderWithOnboardingLayout} from 'sentry-test/onboarding/renderWithOnboardingLayout';
 import {screen} from 'sentry-test/reactTestingLibrary';
 import {textWithMarkupMatcher} from 'sentry-test/utils';
@@ -26,12 +28,54 @@ describe('awslambda onboarding docs', function () {
 
     // Does not render config option
     expect(
-      screen.queryByText(textWithMarkupMatcher(/traces_sample_rate: 1\.0,/))
+      screen.queryByText(textWithMarkupMatcher(/profiles_sample_rate=1\.0,/))
     ).not.toBeInTheDocument();
 
     // Does not render config option
     expect(
-      screen.queryByText(textWithMarkupMatcher(/profiles_sample_rate: 1\.0,/))
+      screen.queryByText(textWithMarkupMatcher(/traces_sample_rate=1\.0,/))
+    ).not.toBeInTheDocument();
+  });
+
+  it('renders transaction profiling', function () {
+    renderWithOnboardingLayout(docs);
+
+    // Does not render continuous profiling config
+    expect(
+      screen.queryByText(
+        textWithMarkupMatcher(/"continuous_profiling_auto_start": True,/)
+      )
+    ).not.toBeInTheDocument();
+
+    // Does render transaction profiling config
+    expect(
+      screen.queryByText(textWithMarkupMatcher(/profiles_sample_rate=1\.0,/))
+    ).toBeInTheDocument();
+  });
+
+  it('renders continuous profiling', function () {
+    const organization = OrganizationFixture({
+      features: ['continuous-profiling'],
+    });
+
+    renderWithOnboardingLayout(
+      docs,
+      {},
+      {
+        organization,
+      }
+    );
+
+    // Does not render transaction profiling config
+    expect(
+      screen.queryByText(textWithMarkupMatcher(/profiles_sample_rate=1\.0,/))
     ).not.toBeInTheDocument();
+
+    // Does render continuous profiling config
+    expect(
+      screen.queryByText(
+        textWithMarkupMatcher(/"continuous_profiling_auto_start": True,/)
+      )
+    ).toBeInTheDocument();
   });
 });

+ 32 - 10
static/app/gettingStartedDocs/python/awslambda.tsx

@@ -1,3 +1,4 @@
+import {Fragment} from 'react';
 import styled from '@emotion/styled';
 
 import Alert from 'sentry/components/alert';
@@ -10,7 +11,10 @@ import {
   type OnboardingConfig,
 } from 'sentry/components/onboarding/gettingStartedDoc/types';
 import {getPythonMetricsOnboarding} from 'sentry/components/onboarding/gettingStartedDoc/utils/metricsOnboarding';
-import {crashReportOnboardingPython} from 'sentry/gettingStartedDocs/python/python';
+import {
+  AlternativeConfiguration,
+  crashReportOnboardingPython,
+} from 'sentry/gettingStartedDocs/python/python';
 import {t, tct} from 'sentry/locale';
 import {space} from 'sentry/styles/space';
 import {trackAnalytics} from 'sentry/utils/analytics';
@@ -38,13 +42,23 @@ sentry_sdk.init(
     traces_sample_rate=1.0,`
         : ''
     }${
-      params.isProfilingSelected
+      params.isProfilingSelected &&
+      params.profilingOptions?.defaultProfilingMode === 'transaction'
         ? `
     # 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,`
-        : ''
+        : params.isProfilingSelected &&
+            params.profilingOptions?.defaultProfilingMode === 'continuous'
+          ? `
+    _experiments={
+        # Set continuous_profiling_auto_start to True
+        # to automatically start the profiler on when
+        # possible.
+        "continuous_profiling_auto_start": True,
+    },`
+          : ''
     }
 )
 
@@ -102,13 +116,21 @@ const onboarding: OnboardingConfig<PlatformOptions> = {
           code: getSdkSetupSnippet(params),
         },
       ],
-      additionalInfo: tct(
-        "Check out Sentry's [link:AWS sample apps] for detailed examples.",
-        {
-          link: (
-            <ExternalLink href="https://github.com/getsentry/examples/tree/master/aws-lambda/python" />
-          ),
-        }
+      additionalInfo: (
+        <Fragment>
+          {params.isProfilingSelected &&
+            params.profilingOptions?.defaultProfilingMode === 'continuous' && (
+              <Fragment>
+                <AlternativeConfiguration />
+                <br />
+              </Fragment>
+            )}
+          {tct("Check out Sentry's [link:AWS sample apps] for detailed examples.", {
+            link: (
+              <ExternalLink href="https://github.com/getsentry/examples/tree/master/aws-lambda/python" />
+            ),
+          })}
+        </Fragment>
       ),
     },
     {

+ 47 - 1
static/app/gettingStartedDocs/python/bottle.spec.tsx

@@ -1,3 +1,5 @@
+import {OrganizationFixture} from 'sentry-fixture/organization';
+
 import {renderWithOnboardingLayout} from 'sentry-test/onboarding/renderWithOnboardingLayout';
 import {screen} from 'sentry-test/reactTestingLibrary';
 import {textWithMarkupMatcher} from 'sentry-test/utils';
@@ -28,12 +30,56 @@ describe('bottle onboarding docs', function () {
 
     // Does not render config option
     expect(
-      screen.queryByText(textWithMarkupMatcher(/traces_sample_rate: 1\.0,/))
+      screen.queryByText(textWithMarkupMatcher(/profiles_sample_rate=1\.0,/))
     ).not.toBeInTheDocument();
 
     // Does not render config option
+    expect(
+      screen.queryByText(textWithMarkupMatcher(/traces_sample_rate=1\.0,/))
+    ).not.toBeInTheDocument();
+  });
+
+  it('renders transaction profiling', function () {
+    renderWithOnboardingLayout(docs);
+
+    // Does not render continuous profiling config
+    expect(
+      screen.queryByText(
+        textWithMarkupMatcher(/"continuous_profiling_auto_start": True,/)
+      )
+    ).not.toBeInTheDocument();
+
+    // Does render transaction profiling config
+    const matches = screen.getAllByText(
+      textWithMarkupMatcher(/profiles_sample_rate=1\.0,/)
+    );
+    expect(matches.length).toBeGreaterThan(0);
+    matches.forEach(match => expect(match).toBeInTheDocument());
+  });
+
+  it('renders continuous profiling', function () {
+    const organization = OrganizationFixture({
+      features: ['continuous-profiling'],
+    });
+
+    renderWithOnboardingLayout(
+      docs,
+      {},
+      {
+        organization,
+      }
+    );
+
+    // Does not render transaction profiling config
     expect(
       screen.queryByText(textWithMarkupMatcher(/profiles_sample_rate: 1\.0,/))
     ).not.toBeInTheDocument();
+
+    // Does render continuous profiling config
+    const matches = screen.getAllByText(
+      textWithMarkupMatcher(/"continuous_profiling_auto_start": True,/)
+    );
+    expect(matches.length).toBeGreaterThan(0);
+    matches.forEach(match => expect(match).toBeInTheDocument());
   });
 });

+ 22 - 5
static/app/gettingStartedDocs/python/bottle.tsx

@@ -8,7 +8,10 @@ import {
 } from 'sentry/components/onboarding/gettingStartedDoc/types';
 import {getPythonMetricsOnboarding} from 'sentry/components/onboarding/gettingStartedDoc/utils/metricsOnboarding';
 import replayOnboardingJsLoader from 'sentry/gettingStartedDocs/javascript/jsLoader/jsLoader';
-import {crashReportOnboardingPython} from 'sentry/gettingStartedDocs/python/python';
+import {
+  AlternativeConfiguration,
+  crashReportOnboardingPython,
+} from 'sentry/gettingStartedDocs/python/python';
 import {t, tct} from 'sentry/locale';
 
 type Params = DocsParams;
@@ -27,13 +30,23 @@ sentry_sdk.init(
     traces_sample_rate=1.0,`
         : ''
     }${
-      params.isProfilingSelected
+      params.isProfilingSelected &&
+      params.profilingOptions?.defaultProfilingMode === 'transaction'
         ? `
     # 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,`
-        : ''
+        : params.isProfilingSelected &&
+            params.profilingOptions?.defaultProfilingMode === 'continuous'
+          ? `
+    _experiments={
+        # Set continuous_profiling_auto_start to True
+        # to automatically start the profiler on when
+        # possible.
+        "continuous_profiling_auto_start": True,
+    },`
+          : ''
     }
 )
 `;
@@ -84,9 +97,13 @@ const onboarding: OnboardingConfig = {
           code: `from bottle import Bottle
 ${getSdkSetupSnippet(params)}
 app = Bottle()
-      `,
+`,
         },
       ],
+      additionalInfo: params.isProfilingSelected &&
+        params.profilingOptions?.defaultProfilingMode === 'continuous' && (
+          <AlternativeConfiguration />
+        ),
     },
   ],
   verify: (params: Params) => [
@@ -109,7 +126,7 @@ def hello():
     return "Hello World!"
 
 run(app, host='localhost', port=8000)
-      `,
+`,
         },
       ],
       additionalInfo: (

Some files were not shown because too many files changed in this diff