From 448060a476e5242f5ada9fdfd0e9fcd9eb1d6253 Mon Sep 17 00:00:00 2001 From: Michelle Zhang <56095982+michellewzhang@users.noreply.github.com> Date: Tue, 3 Sep 2024 12:04:58 -0700 Subject: [PATCH] feat(replay): add mobile platforms to onboarding sidebar (#76709) closes https://github.com/getsentry/sentry/issues/67695 ### android: https://github.com/user-attachments/assets/4ba7d3cc-b4a7-4678-8fe6-5c55baed873c ### react native: https://github.com/user-attachments/assets/bb614c5d-6b55-4a97-b1db-a38e564cf0c1 ### apple: https://github.com/user-attachments/assets/6e30f742-13e2-498f-9d2b-261ad3c9dc18 --- .../feedback/feedbackOnboarding/sidebar.tsx | 1 + .../onboarding/gettingStartedDoc/types.ts | 4 +- .../gettingStartedDoc/utils/index.tsx | 2 +- .../utils/replayOnboarding.tsx | 8 + .../replayOnboardingLayout.tsx | 15 +- .../components/replaysOnboarding/sidebar.tsx | 65 +++----- static/app/data/platformCategories.tsx | 1 + .../gettingStartedDocs/android/android.tsx | 153 ++++++++++++++++++ static/app/gettingStartedDocs/apple/ios.tsx | 103 ++++++++++++ .../capacitor/capacitor.tsx | 2 +- .../gettingStartedDocs/electron/electron.tsx | 2 +- .../gettingStartedDocs/javascript/angular.tsx | 2 +- .../gettingStartedDocs/javascript/astro.tsx | 2 +- .../gettingStartedDocs/javascript/ember.tsx | 2 +- .../gettingStartedDocs/javascript/gatsby.tsx | 2 +- .../javascript/javascript.tsx | 2 +- .../gettingStartedDocs/javascript/nextjs.tsx | 2 +- .../gettingStartedDocs/javascript/react.tsx | 2 +- .../gettingStartedDocs/javascript/remix.tsx | 2 +- .../gettingStartedDocs/javascript/solid.tsx | 2 +- .../javascript/solidstart.tsx | 2 +- .../gettingStartedDocs/javascript/svelte.tsx | 2 +- .../javascript/sveltekit.tsx | 2 +- .../app/gettingStartedDocs/javascript/vue.tsx | 2 +- .../react-native/react-native.tsx | 102 ++++++++++++ 25 files changed, 421 insertions(+), 63 deletions(-) diff --git a/static/app/components/feedback/feedbackOnboarding/sidebar.tsx b/static/app/components/feedback/feedbackOnboarding/sidebar.tsx index 53d92c695348c7..8b74094841eb2f 100644 --- a/static/app/components/feedback/feedbackOnboarding/sidebar.tsx +++ b/static/app/components/feedback/feedbackOnboarding/sidebar.tsx @@ -334,6 +334,7 @@ function OnboardingContent({currentProject}: {currentProject: Project}) { ) { return 'feedbackOnboardingNpm'; } + // TODO: update this when we add feedback to the loader return 'replayOnboardingJsLoader'; } diff --git a/static/app/components/onboarding/gettingStartedDoc/types.ts b/static/app/components/onboarding/gettingStartedDoc/types.ts index 32c1a68f1a7462..85f652824410b3 100644 --- a/static/app/components/onboarding/gettingStartedDoc/types.ts +++ b/static/app/components/onboarding/gettingStartedDoc/types.ts @@ -94,8 +94,8 @@ export interface Docs; feedbackOnboardingNpm?: OnboardingConfig; platformOptions?: PlatformOptions; + replayOnboarding?: OnboardingConfig; replayOnboardingJsLoader?: OnboardingConfig; - replayOnboardingNpm?: OnboardingConfig; } export type ConfigType = @@ -103,6 +103,6 @@ export type ConfigType = | 'feedbackOnboardingNpm' | 'feedbackOnboardingCrashApi' | 'crashReportOnboarding' - | 'replayOnboardingNpm' + | 'replayOnboarding' | 'replayOnboardingJsLoader' | 'customMetricsOnboarding'; diff --git a/static/app/components/onboarding/gettingStartedDoc/utils/index.tsx b/static/app/components/onboarding/gettingStartedDoc/utils/index.tsx index 86800ed50cb94b..58705c2b13899c 100644 --- a/static/app/components/onboarding/gettingStartedDoc/utils/index.tsx +++ b/static/app/components/onboarding/gettingStartedDoc/utils/index.tsx @@ -75,7 +75,7 @@ export function MobileBetaBanner({link}: {link: string}) { return ( {tct( - `Currently, Mobile Replay is in beta. You can [link:read our docs] to learn how to set it up for your project.`, + `Currently, Mobile Replay is in beta. To learn more, you can [link:read our docs].`, { link: , } diff --git a/static/app/components/onboarding/gettingStartedDoc/utils/replayOnboarding.tsx b/static/app/components/onboarding/gettingStartedDoc/utils/replayOnboarding.tsx index e58e2524dc86d5..a36c849868e7b2 100644 --- a/static/app/components/onboarding/gettingStartedDoc/utils/replayOnboarding.tsx +++ b/static/app/components/onboarding/gettingStartedDoc/utils/replayOnboarding.tsx @@ -2,6 +2,14 @@ import ExternalLink from 'sentry/components/links/externalLink'; import type {DocsParams} from 'sentry/components/onboarding/gettingStartedDoc/types'; import {tct} from 'sentry/locale'; +export const getReplayMobileConfigureDescription = ({link}: {link: string}) => + tct( + 'The SDK aggressively redacts all text and images. We plan to add fine controls for redacting, but currently, we just allow either on or off. Learn more about configuring Session Replay by reading the [link:configuration docs].', + { + link: , + } + ); + export const getReplayConfigureDescription = ({link}: {link: string}) => tct( 'Add the following to your SDK config. There are several privacy and sampling options available, all of which can be set using the [code:integrations] constructor. Learn more about configuring Session Replay by reading the [link:configuration docs].', diff --git a/static/app/components/replaysOnboarding/replayOnboardingLayout.tsx b/static/app/components/replaysOnboarding/replayOnboardingLayout.tsx index 7e45ac2832670a..57cf68b4336390 100644 --- a/static/app/components/replaysOnboarding/replayOnboardingLayout.tsx +++ b/static/app/components/replaysOnboarding/replayOnboardingLayout.tsx @@ -8,6 +8,7 @@ import type {DocsParams} from 'sentry/components/onboarding/gettingStartedDoc/ty import {useSourcePackageRegistries} from 'sentry/components/onboarding/gettingStartedDoc/useSourcePackageRegistries'; import {useUrlPlatformOptions} from 'sentry/components/onboarding/platformOptionsControl'; import ReplayConfigToggle from 'sentry/components/replaysOnboarding/replayConfigToggle'; +import {space} from 'sentry/styles/space'; import useOrganization from 'sentry/utils/useOrganization'; export function ReplayOnboardingLayout({ @@ -18,14 +19,15 @@ export function ReplayOnboardingLayout({ projectSlug, newOrg, configType = 'onboarding', -}: OnboardingLayoutProps) { + hideMaskBlockToggles, +}: OnboardingLayoutProps & {hideMaskBlockToggles?: boolean}) { const organization = useOrganization(); const {isPending: isLoadingRegistry, data: registryData} = useSourcePackageRegistries(organization); const selectedOptions = useUrlPlatformOptions(docsConfig.platformOptions); const [mask, setMask] = useState(true); const [block, setBlock] = useState(true); - const {steps} = useMemo(() => { + const {introduction, steps} = useMemo(() => { const doc = docsConfig[configType] ?? docsConfig.onboarding; const docParams: DocsParams = { @@ -78,6 +80,7 @@ export function ReplayOnboardingLayout({ return ( + {introduction && {introduction}} {steps.map(step => step.type === StepType.CONFIGURE ? ( @@ -85,7 +88,7 @@ export function ReplayOnboardingLayout({ key={step.title ?? step.type} {...{ ...step, - codeHeader: ( + codeHeader: hideMaskBlockToggles ? null : ( { return { value: platform.id, @@ -175,40 +176,29 @@ function OnboardingContent({ }; }); - const organization = useOrganization(); const [jsFramework, setJsFramework] = useState<{ value: PlatformKey; label?: ReactNode; textValue?: string; }>(jsFrameworkSelectOptions[0]); - const defaultTab = - currentProject.platform && backend.includes(currentProject.platform) - ? 'jsLoader' - : 'npm'; - - const {getParamValue: setupMode, setParamValue: setSetupMode} = useUrlParams( - 'mode', - defaultTab - ); - - const showJsFrameworkInstructions = - currentProject.platform && - replayBackendPlatforms.includes(currentProject.platform) && - setupMode() === 'npm'; - + const backendPlatform = + currentProject.platform && replayBackendPlatforms.includes(currentProject.platform); + const mobilePlatform = + currentProject.platform && replayMobilePlatforms.includes(currentProject.platform); const npmOnlyFramework = currentProject.platform && replayFrontendPlatforms .filter((p): p is PlatformKey => p !== 'javascript') .includes(currentProject.platform); - const showRadioButtons = - currentProject.platform && - replayJsLoaderInstructionsPlatformList.includes(currentProject.platform); + const defaultTab = backendPlatform ? 'jsLoader' : 'npm'; + const {getParamValue: setupMode, setParamValue: setSetupMode} = useUrlParams( + 'mode', + defaultTab + ); - const backendPlatforms = - currentProject.platform && replayBackendPlatforms.includes(currentProject.platform); + const showJsFrameworkInstructions = backendPlatform && setupMode() === 'npm'; const currentPlatform = currentProject.platform ? platforms.find(p => p.id === currentProject.platform) ?? otherPlatform @@ -240,6 +230,10 @@ function OnboardingContent({ productType: 'replay', }); + const showRadioButtons = + currentProject.platform && + replayJsLoaderInstructionsPlatformList.includes(currentProject.platform); + const radioButtons = (
{showRadioButtons ? ( @@ -248,7 +242,7 @@ function OnboardingContent({ choices={[ [ 'npm', - backendPlatforms ? ( + backendPlatform ? ( {tct('I use [platformSelect]', { platformSelect: ( @@ -283,6 +277,7 @@ function OnboardingContent({ onChange={setSetupMode} /> ) : ( + !mobilePlatform && docs?.platformOptions && !isProjKeysLoading && ( @@ -306,22 +301,6 @@ function OnboardingContent({ ); } - // TODO: remove once we have mobile replay onboarding - if (['android', 'react-native'].includes(currentPlatform.language)) { - return ( - - ); - } - if (currentPlatform.language === 'apple') { - return ( - - ); - } - const doesNotSupportReplay = currentProject.platform ? !replayPlatforms.includes(currentProject.platform) : true; @@ -375,6 +354,7 @@ function OnboardingContent({ {radioButtons} diff --git a/static/app/data/platformCategories.tsx b/static/app/data/platformCategories.tsx index 3faf9fcf73a581..b30c69a502dfa1 100644 --- a/static/app/data/platformCategories.tsx +++ b/static/app/data/platformCategories.tsx @@ -475,6 +475,7 @@ export const replayPlatforms: readonly PlatformKey[] = [ export const replayOnboardingPlatforms: readonly PlatformKey[] = [ ...replayFrontendPlatforms.filter(p => !['javascript-backbone'].includes(p)), ...replayBackendPlatforms, + ...replayMobilePlatforms, ]; // These are the supported replay platforms that can also be set up using the JS loader. diff --git a/static/app/gettingStartedDocs/android/android.tsx b/static/app/gettingStartedDocs/android/android.tsx index 0d75105a393fa5..7854d5925e8c25 100644 --- a/static/app/gettingStartedDocs/android/android.tsx +++ b/static/app/gettingStartedDocs/android/android.tsx @@ -10,7 +10,9 @@ import type { DocsParams, OnboardingConfig, } from 'sentry/components/onboarding/gettingStartedDoc/types'; +import {MobileBetaBanner} from 'sentry/components/onboarding/gettingStartedDoc/utils'; import {getAndroidMetricsOnboarding} from 'sentry/components/onboarding/gettingStartedDoc/utils/metricsOnboarding'; +import {getReplayMobileConfigureDescription} from 'sentry/components/onboarding/gettingStartedDoc/utils/replayOnboarding'; import {feedbackOnboardingCrashApiJava} from 'sentry/gettingStartedDocs/java/java'; import {t, tct} from 'sentry/locale'; import {getPackageVersion} from 'sentry/utils/gettingStartedDocs/getPackageVersion'; @@ -93,6 +95,24 @@ val breakWorld = Button(this).apply { addContentView(breakWorld, ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT))`; +const getReplaySetupSnippetKotlin = (params: Params) => ` +SentryAndroid.init(context) { options -> + options.dsn = "${params.dsn.public}" + options.isDebug = true + + // Currently under experimental options: + options.experimental.sessionReplay.errorSampleRate = 1.0 + options.experimental.sessionReplay.sessionSampleRate = 1.0 +}`; + +const getReplaySetupSnippetXml = () => ` + +`; + +const getReplayConfigurationSnippet = () => ` +options.experimental.sessionReplay.redactAllText = true +options.experimental.sessionReplay.redactAllImages = true`; + const onboarding: OnboardingConfig = { install: params => isAutoInstall(params) @@ -283,12 +303,145 @@ const onboarding: OnboardingConfig = { ], }; +const replayOnboarding: OnboardingConfig = { + introduction: () => ( + + ), + install: (params: Params) => [ + { + type: StepType.INSTALL, + description: tct( + "Make sure your Sentry Android SDK version is at least 7.12.0. The easiest way to update through the Sentry Android Gradle plugin to your app module's [code:build.gradle] file.", + {code: } + ), + configurations: [ + { + code: [ + { + label: 'Groovy', + value: 'groovy', + language: 'groovy', + filename: 'app/build.gradle', + code: `plugins { + id "com.android.application" + id "io.sentry.android.gradle" version "${getPackageVersion( + params, + 'sentry.java.android.gradle-plugin', + '4.11.0' + )}" +}`, + }, + { + label: 'Kotlin', + value: 'kotlin', + language: 'kotlin', + filename: 'app/build.gradle.kts', + code: `plugins { + id("com.android.application") + id("io.sentry.android.gradle") version "${getPackageVersion( + params, + 'sentry.java.android.gradle-plugin', + '4.11.0' + )}" +}`, + }, + ], + }, + { + description: tct( + 'If you have the SDK installed without the Sentry Gradle Plugin, you can update the version directly in the [code:build.gradle] through:', + {code: } + ), + }, + { + code: [ + { + label: 'Groovy', + value: 'groovy', + language: 'groovy', + filename: 'app/build.gradle', + code: `dependencies { + implementation 'io.sentry:sentry-android:${getPackageVersion( + params, + 'sentry.java.android', + '7.14.0' + )}' +}`, + }, + { + label: 'Kotlin', + value: 'kotlin', + language: 'kotlin', + filename: 'app/build.gradle.kts', + code: `dependencies { + implementation("io.sentry:sentry-android:${getPackageVersion( + params, + 'sentry.java.android', + '7.14.0' + )}") +}`, + }, + ], + }, + { + description: t( + 'To set up the integration, add the following to your Sentry initialization:' + ), + }, + { + code: [ + { + label: 'Kotlin', + value: 'kotlin', + language: 'kotlin', + code: getReplaySetupSnippetKotlin(params), + }, + { + label: 'XML', + value: 'xml', + language: 'xml', + filename: 'AndroidManifest.xml', + code: getReplaySetupSnippetXml(), + }, + ], + }, + ], + }, + ], + configure: () => [ + { + type: StepType.CONFIGURE, + description: getReplayMobileConfigureDescription({ + link: 'https://docs.sentry.io/platforms/android/session-replay/#privacy', + }), + configurations: [ + { + description: t( + 'The following code is the default configuration, which masks and blocks everything.' + ), + code: [ + { + label: 'Kotlin', + value: 'kotlin', + language: 'kotlin', + code: getReplayConfigurationSnippet(), + }, + ], + }, + ], + }, + ], + verify: () => [], + nextSteps: () => [], +}; + const docs: Docs = { onboarding, feedbackOnboardingCrashApi: feedbackOnboardingCrashApiJava, crashReportOnboarding: feedbackOnboardingCrashApiJava, customMetricsOnboarding: getAndroidMetricsOnboarding(), platformOptions, + replayOnboarding, }; export default docs; diff --git a/static/app/gettingStartedDocs/apple/ios.tsx b/static/app/gettingStartedDocs/apple/ios.tsx index 98e0cf409b9b2b..a1eb9d10f85742 100644 --- a/static/app/gettingStartedDocs/apple/ios.tsx +++ b/static/app/gettingStartedDocs/apple/ios.tsx @@ -9,7 +9,9 @@ import type { DocsParams, OnboardingConfig, } from 'sentry/components/onboarding/gettingStartedDoc/types'; +import {MobileBetaBanner} from 'sentry/components/onboarding/gettingStartedDoc/utils'; import {metricTagsExplanation} from 'sentry/components/onboarding/gettingStartedDoc/utils/metricsOnboarding'; +import {getReplayMobileConfigureDescription} from 'sentry/components/onboarding/gettingStartedDoc/utils/replayOnboarding'; import {appleFeedbackOnboarding} from 'sentry/gettingStartedDocs/apple/macos'; import {t, tct} from 'sentry/locale'; import {getPackageVersion} from 'sentry/utils/gettingStartedDocs/getPackageVersion'; @@ -244,6 +246,20 @@ const getVerifyMetricsSnippetObjC = () => ` tags: @{ @"screen" : @"login" } ];`; +const getReplaySetupSnippet = (params: Params) => ` +SentrySDK.start(configureOptions: { options in + options.dsn = "${params.dsn.public}" + options.debug = true + + // Currently under experimental options: + options.experimental.sessionReplay.onErrorSampleRate = 1.0 + options.experimental.sessionReplay.sessionSampleRate = 1.0 +})`; + +const getReplayConfigurationSnippet = () => ` +options.experimental.sessionReplay.redactAllText = true +options.experimental.sessionReplay.redactAllImages = true`; + const onboarding: OnboardingConfig = { install: params => isAutoInstall(params) @@ -615,12 +631,99 @@ const metricsOnboarding: OnboardingConfig = { ], }; +const replayOnboarding: OnboardingConfig = { + introduction: () => ( + + ), + install: (params: Params) => [ + { + type: StepType.INSTALL, + description: t( + 'Make sure your Sentry Cocoa SDK version is at least 8.31.1. If you already have the SDK installed, you can update it to the latest version with:' + ), + configurations: [ + { + code: [ + { + label: 'SPM', + value: 'spm', + language: 'swift', + code: `.package(url: "https://github.com/getsentry/sentry-cocoa", from: "${getPackageVersion( + params, + 'sentry.cocoa', + '8.36.0' + )}"),`, + }, + { + label: 'CocoaPods', + value: 'cocoapods', + language: 'ruby', + code: `pod update`, + }, + { + label: 'Carthage', + value: 'carthage', + language: 'swift', + code: `github "getsentry/sentry-cocoa" "${getPackageVersion( + params, + 'sentry.cocoa', + '8.36.0' + )}"`, + }, + ], + }, + { + description: t( + 'To set up the integration, add the following to your Sentry initialization:' + ), + }, + { + code: [ + { + label: 'Swift', + value: 'swift', + language: 'swift', + code: getReplaySetupSnippet(params), + }, + ], + }, + ], + }, + ], + configure: () => [ + { + type: StepType.CONFIGURE, + description: getReplayMobileConfigureDescription({ + link: 'https://docs.sentry.io/platforms/apple/guides/ios/session-replay/#privacy', + }), + configurations: [ + { + description: t( + 'The following code is the default configuration, which masks and blocks everything.' + ), + code: [ + { + label: 'Swift', + value: 'swift', + language: 'swift', + code: getReplayConfigurationSnippet(), + }, + ], + }, + ], + }, + ], + verify: () => [], + nextSteps: () => [], +}; + const docs: Docs = { onboarding, feedbackOnboardingCrashApi: appleFeedbackOnboarding, crashReportOnboarding: appleFeedbackOnboarding, customMetricsOnboarding: metricsOnboarding, platformOptions, + replayOnboarding, }; export default docs; diff --git a/static/app/gettingStartedDocs/capacitor/capacitor.tsx b/static/app/gettingStartedDocs/capacitor/capacitor.tsx index 022e901b22c663..dae7338fa95083 100644 --- a/static/app/gettingStartedDocs/capacitor/capacitor.tsx +++ b/static/app/gettingStartedDocs/capacitor/capacitor.tsx @@ -487,7 +487,7 @@ const docs: Docs = { onboarding, platformOptions, feedbackOnboardingNpm: feedbackOnboarding, - replayOnboardingNpm: replayOnboarding, + replayOnboarding, crashReportOnboarding, }; diff --git a/static/app/gettingStartedDocs/electron/electron.tsx b/static/app/gettingStartedDocs/electron/electron.tsx index d773f64488b041..0c34d3f8fa170c 100644 --- a/static/app/gettingStartedDocs/electron/electron.tsx +++ b/static/app/gettingStartedDocs/electron/electron.tsx @@ -363,7 +363,7 @@ init({ const docs: Docs = { onboarding, feedbackOnboardingNpm: feedbackOnboarding, - replayOnboardingNpm: replayOnboarding, + replayOnboarding, customMetricsOnboarding, crashReportOnboarding, }; diff --git a/static/app/gettingStartedDocs/javascript/angular.tsx b/static/app/gettingStartedDocs/javascript/angular.tsx index 29074a1914f20d..8d008c35ffe293 100644 --- a/static/app/gettingStartedDocs/javascript/angular.tsx +++ b/static/app/gettingStartedDocs/javascript/angular.tsx @@ -375,7 +375,7 @@ const crashReportOnboarding: OnboardingConfig = { const docs: Docs = { onboarding, feedbackOnboardingNpm: feedbackOnboarding, - replayOnboardingNpm: replayOnboarding, + replayOnboarding, customMetricsOnboarding: getJSMetricsOnboarding({getInstallConfig}), crashReportOnboarding, }; diff --git a/static/app/gettingStartedDocs/javascript/astro.tsx b/static/app/gettingStartedDocs/javascript/astro.tsx index 6df7b83d0190e3..6a17a79be4ddfb 100644 --- a/static/app/gettingStartedDocs/javascript/astro.tsx +++ b/static/app/gettingStartedDocs/javascript/astro.tsx @@ -377,7 +377,7 @@ const crashReportOnboarding: OnboardingConfig = { const docs: Docs = { onboarding, feedbackOnboardingNpm: feedbackOnboarding, - replayOnboardingNpm: replayOnboarding, + replayOnboarding, customMetricsOnboarding: getJSMetricsOnboarding({getInstallConfig}), crashReportOnboarding, }; diff --git a/static/app/gettingStartedDocs/javascript/ember.tsx b/static/app/gettingStartedDocs/javascript/ember.tsx index aaf60a79c8ca4a..3afb07d333c5bf 100644 --- a/static/app/gettingStartedDocs/javascript/ember.tsx +++ b/static/app/gettingStartedDocs/javascript/ember.tsx @@ -288,7 +288,7 @@ const crashReportOnboarding: OnboardingConfig = { const docs: Docs = { onboarding, feedbackOnboardingNpm: feedbackOnboarding, - replayOnboardingNpm: replayOnboarding, + replayOnboarding, customMetricsOnboarding: getJSMetricsOnboarding({getInstallConfig}), crashReportOnboarding, }; diff --git a/static/app/gettingStartedDocs/javascript/gatsby.tsx b/static/app/gettingStartedDocs/javascript/gatsby.tsx index 6bbd61954fb865..f1ff44995249b4 100644 --- a/static/app/gettingStartedDocs/javascript/gatsby.tsx +++ b/static/app/gettingStartedDocs/javascript/gatsby.tsx @@ -322,7 +322,7 @@ const crashReportOnboarding: OnboardingConfig = { const docs: Docs = { onboarding, feedbackOnboardingNpm: feedbackOnboarding, - replayOnboardingNpm: replayOnboarding, + replayOnboarding, customMetricsOnboarding: getJSMetricsOnboarding({getInstallConfig}), crashReportOnboarding, }; diff --git a/static/app/gettingStartedDocs/javascript/javascript.tsx b/static/app/gettingStartedDocs/javascript/javascript.tsx index b2f332d583fdb8..f412e4039a712b 100644 --- a/static/app/gettingStartedDocs/javascript/javascript.tsx +++ b/static/app/gettingStartedDocs/javascript/javascript.tsx @@ -289,7 +289,7 @@ const crashReportOnboarding: OnboardingConfig = { const docs: Docs = { onboarding, feedbackOnboardingNpm: feedbackOnboarding, - replayOnboardingNpm: replayOnboarding, + replayOnboarding, replayOnboardingJsLoader, customMetricsOnboarding: getJSMetricsOnboarding({getInstallConfig}), crashReportOnboarding, diff --git a/static/app/gettingStartedDocs/javascript/nextjs.tsx b/static/app/gettingStartedDocs/javascript/nextjs.tsx index 195dec3cc92f20..3e80a4b93e1076 100644 --- a/static/app/gettingStartedDocs/javascript/nextjs.tsx +++ b/static/app/gettingStartedDocs/javascript/nextjs.tsx @@ -285,7 +285,7 @@ const crashReportOnboarding: OnboardingConfig = { const docs: Docs = { onboarding, feedbackOnboardingNpm: feedbackOnboarding, - replayOnboardingNpm: replayOnboarding, + replayOnboarding, customMetricsOnboarding: getJSMetricsOnboarding({ getInstallConfig: getManualInstallConfig, }), diff --git a/static/app/gettingStartedDocs/javascript/react.tsx b/static/app/gettingStartedDocs/javascript/react.tsx index e5b23ac8b612ed..86e24f76408779 100644 --- a/static/app/gettingStartedDocs/javascript/react.tsx +++ b/static/app/gettingStartedDocs/javascript/react.tsx @@ -314,7 +314,7 @@ const crashReportOnboarding: OnboardingConfig = { const docs: Docs = { onboarding, feedbackOnboardingNpm: feedbackOnboarding, - replayOnboardingNpm: replayOnboarding, + replayOnboarding, customMetricsOnboarding: getJSMetricsOnboarding({getInstallConfig}), crashReportOnboarding, }; diff --git a/static/app/gettingStartedDocs/javascript/remix.tsx b/static/app/gettingStartedDocs/javascript/remix.tsx index 6e8529f6cf97c8..cf4285161bc6ef 100644 --- a/static/app/gettingStartedDocs/javascript/remix.tsx +++ b/static/app/gettingStartedDocs/javascript/remix.tsx @@ -232,7 +232,7 @@ const crashReportOnboarding: OnboardingConfig = { const docs: Docs = { onboarding, feedbackOnboardingNpm: feedbackOnboarding, - replayOnboardingNpm: replayOnboarding, + replayOnboarding, customMetricsOnboarding: getJSMetricsOnboarding({getInstallConfig}), crashReportOnboarding, }; diff --git a/static/app/gettingStartedDocs/javascript/solid.tsx b/static/app/gettingStartedDocs/javascript/solid.tsx index 357750b5a40448..a9f60529b73208 100644 --- a/static/app/gettingStartedDocs/javascript/solid.tsx +++ b/static/app/gettingStartedDocs/javascript/solid.tsx @@ -314,7 +314,7 @@ const crashReportOnboarding: OnboardingConfig = { const docs: Docs = { onboarding, feedbackOnboardingNpm: feedbackOnboarding, - replayOnboardingNpm: replayOnboarding, + replayOnboarding, customMetricsOnboarding: getJSMetricsOnboarding({getInstallConfig}), crashReportOnboarding, }; diff --git a/static/app/gettingStartedDocs/javascript/solidstart.tsx b/static/app/gettingStartedDocs/javascript/solidstart.tsx index cef5ca1d90e49a..b4713991c9cacf 100644 --- a/static/app/gettingStartedDocs/javascript/solidstart.tsx +++ b/static/app/gettingStartedDocs/javascript/solidstart.tsx @@ -472,7 +472,7 @@ const crashReportOnboarding: OnboardingConfig = { const docs: Docs = { onboarding, feedbackOnboardingNpm: feedbackOnboarding, - replayOnboardingNpm: replayOnboarding, + replayOnboarding, customMetricsOnboarding: getJSMetricsOnboarding({getInstallConfig}), crashReportOnboarding, }; diff --git a/static/app/gettingStartedDocs/javascript/svelte.tsx b/static/app/gettingStartedDocs/javascript/svelte.tsx index 571f8de71db8a9..4aa5902e1463b2 100644 --- a/static/app/gettingStartedDocs/javascript/svelte.tsx +++ b/static/app/gettingStartedDocs/javascript/svelte.tsx @@ -311,7 +311,7 @@ const crashReportOnboarding: OnboardingConfig = { const docs: Docs = { onboarding, feedbackOnboardingNpm: feedbackOnboarding, - replayOnboardingNpm: replayOnboarding, + replayOnboarding, customMetricsOnboarding: getJSMetricsOnboarding({getInstallConfig}), crashReportOnboarding, }; diff --git a/static/app/gettingStartedDocs/javascript/sveltekit.tsx b/static/app/gettingStartedDocs/javascript/sveltekit.tsx index d838be59c457b0..689e2139bcdb99 100644 --- a/static/app/gettingStartedDocs/javascript/sveltekit.tsx +++ b/static/app/gettingStartedDocs/javascript/sveltekit.tsx @@ -208,7 +208,7 @@ const crashReportOnboarding: OnboardingConfig = { const docs: Docs = { onboarding, feedbackOnboardingNpm: feedbackOnboarding, - replayOnboardingNpm: replayOnboarding, + replayOnboarding, customMetricsOnboarding: getJSMetricsOnboarding({getInstallConfig}), crashReportOnboarding, }; diff --git a/static/app/gettingStartedDocs/javascript/vue.tsx b/static/app/gettingStartedDocs/javascript/vue.tsx index 9ae2313cd04cdc..4c2631c045d99f 100644 --- a/static/app/gettingStartedDocs/javascript/vue.tsx +++ b/static/app/gettingStartedDocs/javascript/vue.tsx @@ -384,7 +384,7 @@ const docs: Docs = { onboarding, platformOptions, feedbackOnboardingNpm: feedbackOnboarding, - replayOnboardingNpm: replayOnboarding, + replayOnboarding, customMetricsOnboarding: getJSMetricsOnboarding({getInstallConfig}), crashReportOnboarding, }; diff --git a/static/app/gettingStartedDocs/react-native/react-native.tsx b/static/app/gettingStartedDocs/react-native/react-native.tsx index eab3fd8cd56286..dfb36d6bbda007 100644 --- a/static/app/gettingStartedDocs/react-native/react-native.tsx +++ b/static/app/gettingStartedDocs/react-native/react-native.tsx @@ -9,11 +9,13 @@ import type { DocsParams, OnboardingConfig, } from 'sentry/components/onboarding/gettingStartedDoc/types'; +import {MobileBetaBanner} from 'sentry/components/onboarding/gettingStartedDoc/utils'; import { getCrashReportApiIntroduction, getCrashReportInstallDescription, } from 'sentry/components/onboarding/gettingStartedDoc/utils/feedbackOnboarding'; import {getReactNativeMetricsOnboarding} from 'sentry/components/onboarding/gettingStartedDoc/utils/metricsOnboarding'; +import {getReplayMobileConfigureDescription} from 'sentry/components/onboarding/gettingStartedDoc/utils/replayOnboarding'; import {t, tct} from 'sentry/locale'; type Params = DocsParams; @@ -72,6 +74,27 @@ shopCheckout() { } }`; +const getReplaySetupSnippet = (params: Params) => ` +import * as Sentry from '@sentry/react-native'; + +Sentry.init({ + dsn: "${params.dsn.public}", + _experiments: { + replaysSessionSampleRate: 1.0, + replaysOnErrorSampleRate: 1.0, + }, + integrations: [ + Sentry.mobileReplayIntegration(), + ], +});`; + +const getReplayConfigurationSnippet = () => ` +Sentry.mobileReplayIntegration({ + maskAllText: true, + maskAllImages: true, + maskAllVectors: true, +}),`; + const onboarding: OnboardingConfig = { install: () => [ { @@ -381,11 +404,90 @@ const getInstallConfig = () => [ }, ]; +const replayOnboarding: OnboardingConfig = { + introduction: () => ( + + ), + install: (params: Params) => [ + { + type: StepType.INSTALL, + description: t( + 'Make sure your Sentry React Native SDK version is at least 5.26.0. If you already have the SDK installed, you can update it to the latest version with:' + ), + configurations: [ + { + code: [ + { + label: 'npm', + value: 'npm', + language: 'bash', + code: `npm install @sentry/react-native --save`, + }, + { + label: 'yarn', + value: 'yarn', + language: 'bash', + code: `yarn add @sentry/react-native`, + }, + { + label: 'pnpm', + value: 'pnpm', + language: 'bash', + code: `pnpm add @sentry/react-native`, + }, + ], + }, + { + description: t( + 'To set up the integration, add the following to your Sentry initialization:' + ), + }, + { + code: [ + { + label: 'JavaScript', + value: 'javascript', + language: 'javascript', + code: getReplaySetupSnippet(params), + }, + ], + }, + ], + }, + ], + configure: () => [ + { + type: StepType.CONFIGURE, + description: getReplayMobileConfigureDescription({ + link: 'https://docs.sentry.io/platforms/react-native/session-replay/#privacy', + }), + configurations: [ + { + description: t( + 'The following code is the default configuration, which masks and blocks everything.' + ), + code: [ + { + label: 'JavaScript', + value: 'javascript', + language: 'javascript', + code: getReplayConfigurationSnippet(), + }, + ], + }, + ], + }, + ], + verify: () => [], + nextSteps: () => [], +}; + const docs: Docs = { onboarding, feedbackOnboardingCrashApi, crashReportOnboarding: feedbackOnboardingCrashApi, customMetricsOnboarding: getReactNativeMetricsOnboarding({getInstallConfig}), + replayOnboarding, }; export default docs;