diff --git a/static/app/gettingStartedDocs/node/awslambda.tsx b/static/app/gettingStartedDocs/node/awslambda.tsx
index 3ef59b3e02fcb1..a4a2ca6d52fa96 100644
--- a/static/app/gettingStartedDocs/node/awslambda.tsx
+++ b/static/app/gettingStartedDocs/node/awslambda.tsx
@@ -1,5 +1,6 @@
import {StepType} from 'sentry/components/onboarding/gettingStartedDoc/step';
import type {
+ BasePlatformOptions,
Docs,
DocsParams,
OnboardingConfig,
@@ -12,9 +13,33 @@ import {
} from 'sentry/components/onboarding/gettingStartedDoc/utils/feedbackOnboarding';
import {getJSServerMetricsOnboarding} from 'sentry/components/onboarding/gettingStartedDoc/utils/metricsOnboarding';
import {t, tct} from 'sentry/locale';
+import {trackAnalytics} from 'sentry/utils/analytics';
import {getInstallConfig, getSdkInitSnippet} from 'sentry/utils/gettingStartedDocs/node';
-type Params = DocsParams;
+export enum InstallationMode {
+ AUTO = 'auto',
+ MANUAL = 'manual',
+}
+
+const platformOptions = {
+ installationMode: {
+ label: t('Installation Mode'),
+ items: [
+ {
+ label: t('Auto'),
+ value: InstallationMode.AUTO,
+ },
+ {
+ label: t('Manual'),
+ value: InstallationMode.MANUAL,
+ },
+ ],
+ defaultValue: InstallationMode.AUTO,
+ },
+} satisfies BasePlatformOptions;
+
+type PlatformOptions = typeof platformOptions;
+type Params = DocsParams;
const getSdkSetupSnippet = (params: Params) => `
// IMPORTANT: Make sure to import and initialize Sentry at the top of your file.
@@ -39,7 +64,7 @@ Sentry.init({
// },
});`;
-const onboarding: OnboardingConfig = {
+const onboarding: OnboardingConfig = {
install: params => [
{
type: StepType.INSTALL,
@@ -87,9 +112,21 @@ const onboarding: OnboardingConfig = {
],
},
],
+ onPlatformOptionsChange(params) {
+ return option => {
+ if (option.installationMode === InstallationMode.MANUAL) {
+ trackAnalytics('integrations.switch_manual_sdk_setup', {
+ integration_type: 'first_party',
+ integration: 'aws_lambda',
+ view: 'onboarding',
+ organization: params.organization,
+ });
+ }
+ };
+ },
};
-const customMetricsOnboarding: OnboardingConfig = {
+const customMetricsOnboarding: OnboardingConfig = {
install: params => [
{
type: StepType.INSTALL,
@@ -122,7 +159,7 @@ const customMetricsOnboarding: OnboardingConfig = {
verify: getJSServerMetricsOnboarding().verify,
};
-const crashReportOnboarding: OnboardingConfig = {
+const crashReportOnboarding: OnboardingConfig = {
introduction: () => getCrashReportModalIntroduction(),
install: (params: Params) => getCrashReportJavaScriptInstallStep(params),
configure: () => [
@@ -137,10 +174,11 @@ const crashReportOnboarding: OnboardingConfig = {
nextSteps: () => [],
};
-const docs: Docs = {
+const docs: Docs = {
onboarding,
customMetricsOnboarding,
crashReportOnboarding,
+ platformOptions,
};
export default docs;
diff --git a/static/app/gettingStartedDocs/python/awslambda.tsx b/static/app/gettingStartedDocs/python/awslambda.tsx
index 7bcd9bd85e77b8..4c83cf2337af15 100644
--- a/static/app/gettingStartedDocs/python/awslambda.tsx
+++ b/static/app/gettingStartedDocs/python/awslambda.tsx
@@ -4,6 +4,7 @@ import Alert from 'sentry/components/alert';
import ExternalLink from 'sentry/components/links/externalLink';
import {StepType} from 'sentry/components/onboarding/gettingStartedDoc/step';
import {
+ type BasePlatformOptions,
type Docs,
DocsPageLocation,
type DocsParams,
@@ -13,8 +14,32 @@ import {getPythonMetricsOnboarding} from 'sentry/components/onboarding/gettingSt
import {crashReportOnboardingPython} from 'sentry/gettingStartedDocs/python/python';
import {t, tct} from 'sentry/locale';
import {space} from 'sentry/styles/space';
+import {trackAnalytics} from 'sentry/utils/analytics';
-type Params = DocsParams;
+export enum InstallationMode {
+ AUTO = 'auto',
+ MANUAL = 'manual',
+}
+
+const platformOptions = {
+ installationMode: {
+ label: t('Installation Mode'),
+ items: [
+ {
+ label: t('Auto'),
+ value: InstallationMode.AUTO,
+ },
+ {
+ label: t('Manual'),
+ value: InstallationMode.MANUAL,
+ },
+ ],
+ defaultValue: InstallationMode.AUTO,
+ },
+} satisfies BasePlatformOptions;
+
+type PlatformOptions = typeof platformOptions;
+type Params = DocsParams;
const getInstallSnippet = () => `pip install --upgrade sentry-sdk`;
@@ -53,7 +78,7 @@ sentry_sdk.init(
],
)`;
-const onboarding: OnboardingConfig = {
+const onboarding: OnboardingConfig = {
introduction: () =>
tct(
'Create a deployment package on your local machine and install the required dependencies in the deployment package. For more information, see [link:AWS Lambda deployment package in Python].',
@@ -146,14 +171,27 @@ const onboarding: OnboardingConfig = {
},
],
verify: () => [],
+ onPlatformOptionsChange(params) {
+ return option => {
+ if (option.installationMode === InstallationMode.MANUAL) {
+ trackAnalytics('integrations.switch_manual_sdk_setup', {
+ integration_type: 'first_party',
+ integration: 'aws_lambda',
+ view: 'onboarding',
+ organization: params.organization,
+ });
+ }
+ };
+ },
};
-const docs: Docs = {
+const docs: Docs = {
onboarding,
customMetricsOnboarding: getPythonMetricsOnboarding({
installSnippet: getInstallSnippet(),
}),
crashReportOnboarding: crashReportOnboardingPython,
+ platformOptions,
};
export default docs;
diff --git a/static/app/views/onboarding/components/integrations/addInstallationInstructions.tsx b/static/app/views/onboarding/components/integrations/addInstallationInstructions.tsx
index 7cf13fe9aa5420..d237cff5db4503 100644
--- a/static/app/views/onboarding/components/integrations/addInstallationInstructions.tsx
+++ b/static/app/views/onboarding/components/integrations/addInstallationInstructions.tsx
@@ -27,8 +27,8 @@ export default function AddInstallationInstructions() {
{tct(
- 'If you don’t want to add CloudFormation stack to your AWS environment, press the [manualSetup] button instead.',
- {manualSetup: {t('Manual Setup')} }
+ 'If you don’t want to add CloudFormation stack to your AWS environment, press the [manual] button above instead.',
+ {manual: {t('Manual')} }
)}
diff --git a/static/app/views/onboarding/components/useOnboardingQueryParams.tsx b/static/app/views/onboarding/components/useOnboardingQueryParams.tsx
index 628fe7f85f6c1d..bc298311fb8cfd 100644
--- a/static/app/views/onboarding/components/useOnboardingQueryParams.tsx
+++ b/static/app/views/onboarding/components/useOnboardingQueryParams.tsx
@@ -1,11 +1,16 @@
import {useCallback} from 'react';
-import {decodeBoolean, decodeList} from 'sentry/utils/queryString';
+import {decodeBoolean, decodeList, decodeScalar} from 'sentry/utils/queryString';
import useLocationQuery from 'sentry/utils/url/useLocationQuery';
import {useLocation} from 'sentry/utils/useLocation';
import {useNavigate} from 'sentry/utils/useNavigate';
type QueryValues = {
+ /**
+ * Used to show the installation mode for certain platforms, e.g. manual or auto.
+ * This is defined inside of a platform file
+ */
+ installationMode: string;
/**
* Used to show product selection (error monitoring, tracing, profiling and session replay) for certain platforms, e.g. javascript-react
*/
@@ -31,6 +36,7 @@ export function useOnboardingQueryParams(): [
product: decodeList,
showLoader: decodeBoolean,
showManualSetup: decodeBoolean,
+ installationMode: decodeScalar,
},
});
diff --git a/static/app/views/onboarding/integrationSetup.tsx b/static/app/views/onboarding/integrationSetup.tsx
index 6d92cdf0676f03..ac97c02271d24a 100644
--- a/static/app/views/onboarding/integrationSetup.tsx
+++ b/static/app/views/onboarding/integrationSetup.tsx
@@ -5,39 +5,58 @@ import {motion} from 'framer-motion';
import {openInviteMembersModal} from 'sentry/actionCreators/modal';
import {Alert} from 'sentry/components/alert';
import {Button} from 'sentry/components/button';
-import ButtonBar from 'sentry/components/buttonBar';
import ExternalLink from 'sentry/components/links/externalLink';
import LoadingError from 'sentry/components/loadingError';
-import platforms from 'sentry/data/platforms';
+import LoadingIndicator from 'sentry/components/loadingIndicator';
+import type {DocsParams} from 'sentry/components/onboarding/gettingStartedDoc/types';
+import {useLoadGettingStarted} from 'sentry/components/onboarding/gettingStartedDoc/utils/useLoadGettingStarted';
+import {
+ PlatformOptionsControl,
+ useUrlPlatformOptions,
+} from 'sentry/components/onboarding/platformOptionsControl';
import {t, tct} from 'sentry/locale';
+import ConfigStore from 'sentry/stores/configStore';
+import {useLegacyStore} from 'sentry/stores/useLegacyStore';
import {space} from 'sentry/styles/space';
import type {IntegrationProvider} from 'sentry/types/integrations';
-import type {Project} from 'sentry/types/project';
+import type {PlatformIntegration, Project} from 'sentry/types/project';
import {trackAnalytics} from 'sentry/utils/analytics';
import getDynamicText from 'sentry/utils/getDynamicText';
-import {trackIntegrationAnalytics} from 'sentry/utils/integrationUtil';
import useApi from 'sentry/utils/useApi';
import useOrganization from 'sentry/utils/useOrganization';
+import SetupIntroduction from 'sentry/views/onboarding/components/setupIntroduction';
import {AddIntegrationButton} from 'sentry/views/settings/organizationIntegrations/addIntegrationButton';
import AddInstallationInstructions from './components/integrations/addInstallationInstructions';
import PostInstallCodeSnippet from './components/integrations/postInstallCodeSnippet';
-import SetupIntroduction from './components/setupIntroduction';
type Props = {
integrationSlug: string;
- project: Project | null;
- onClickManualSetup?: () => void;
+ platform: PlatformIntegration;
+ project: Project;
};
-function IntegrationSetup(props: Props) {
+function IntegrationSetup({project, integrationSlug, platform}: Props) {
const [hasError, setHasError] = useState(false);
const [installed, setInstalled] = useState(false);
const [provider, setProvider] = useState(null);
const organization = useOrganization();
-
- const {project, integrationSlug} = props;
+ const {isSelfHosted, urlPrefix} = useLegacyStore(ConfigStore);
+
+ const {
+ isLoading,
+ docs: docsConfig,
+ dsn,
+ projectKeyId,
+ refetch,
+ } = useLoadGettingStarted({
+ orgSlug: organization.slug,
+ projSlug: project.slug,
+ platform,
+ });
+
+ const platformOptions = useUrlPlatformOptions(docsConfig?.platformOptions);
const api = useApi();
const fetchData = useCallback(() => {
@@ -64,10 +83,7 @@ function IntegrationSetup(props: Props) {
const loadingError = (
);
@@ -78,26 +94,13 @@ function IntegrationSetup(props: Props) {
);
- const renderSetupInstructions = () => {
- const currentPlatform = project?.platform ?? 'other';
- return (
- p.id === currentPlatform)?.name ?? ''
- )}
- platform={currentPlatform}
- />
- );
- };
const renderIntegrationInstructions = () => {
- if (!provider || !project) {
+ if (!provider) {
return null;
}
return (
- {renderSetupInstructions()}
-
- setInstalled(true)}
- organization={organization}
- priority="primary"
- size="sm"
- analyticsParams={{view: 'onboarding', already_installed: false}}
- modalParams={{projectId: project.id}}
- />
- {
- props.onClickManualSetup?.();
- trackIntegrationAnalytics('integrations.switch_manual_sdk_setup', {
- integration_type: 'first_party',
- integration: integrationSlug,
- view: 'onboarding',
- organization,
- });
- }}
- >
- {t('Manual Setup')}
-
-
+ setInstalled(true)}
+ organization={organization}
+ priority="primary"
+ size="sm"
+ analyticsParams={{view: 'onboarding', already_installed: false}}
+ modalParams={{projectId: project.id}}
+ />
);
};
const renderPostInstallInstructions = () => {
- if (!project || !provider) {
+ if (!provider) {
return null;
}
return (
- {renderSetupInstructions()}
;
+ }
+
+ if (!docsConfig || !dsn || !projectKeyId) {
+ return (
+
+ );
+ }
+
+ const docParams: DocsParams = {
+ api,
+ projectKeyId,
+ dsn,
+ organization,
+ platformKey: platform.id,
+ projectId: project.id,
+ projectSlug: project.slug,
+ isFeedbackSelected: false,
+ isPerformanceSelected: false,
+ isProfilingSelected: false,
+ isReplaySelected: false,
+ isSelfHosted,
+ platformOptions,
+ sourcePackageRegistries: {
+ isLoading: false,
+ data: undefined,
+ },
+ urlPrefix,
+ };
+
return (
+
+ {docsConfig.platformOptions && (
+
+ )}
+
{installed ? renderPostInstallInstructions() : renderIntegrationInstructions()}
{getDynamicText({
value: !hasError ? null : loadingError,
@@ -206,15 +239,12 @@ DocsWrapper.defaultProps = {
exit: {opacity: 0},
};
-const StyledButtonBar = styled(ButtonBar)`
- margin-top: ${space(3)};
- width: max-content;
-
- @media (max-width: ${p => p.theme.breakpoints.small}) {
- width: auto;
- grid-row-gap: ${space(1)};
- grid-auto-flow: row;
- }
+const Divider = styled('hr')`
+ height: 1px;
+ width: 100%;
+ background: ${p => p.theme.border};
+ border: none;
+ margin-bottom: ${space(3)};
`;
export default IntegrationSetup;
diff --git a/static/app/views/onboarding/setupDocs.tsx b/static/app/views/onboarding/setupDocs.tsx
index 1d62bf03f0b14d..7ab2404cb24cbf 100644
--- a/static/app/views/onboarding/setupDocs.tsx
+++ b/static/app/views/onboarding/setupDocs.tsx
@@ -33,7 +33,7 @@ function SetupDocs({location, recentCreatedProject: project}: StepProps) {
const currentPlatform =
platforms.find(p => p.id === currentPlatformKey) ?? otherPlatform;
- const [params, setParams] = useOnboardingQueryParams();
+ const [params] = useOnboardingQueryParams();
if (!project || !currentPlatform) {
return null;
@@ -41,7 +41,8 @@ function SetupDocs({location, recentCreatedProject: project}: StepProps) {
const platformName = currentPlatform.name;
const integrationSlug = project.platform && platformToIntegrationMap[project.platform];
- const showIntegrationOnboarding = integrationSlug && !params.showManualSetup;
+ const showIntegrationOnboarding =
+ integrationSlug && params.installationMode !== 'manual';
return (
@@ -51,9 +52,7 @@ function SetupDocs({location, recentCreatedProject: project}: StepProps) {
{
- setParams({showManualSetup: true});
- }}
+ platform={currentPlatform}
/>
) : (