ios.tsx 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  1. import ExternalLink from 'sentry/components/links/externalLink';
  2. import List from 'sentry/components/list/';
  3. import ListItem from 'sentry/components/list/listItem';
  4. import {StepType} from 'sentry/components/onboarding/gettingStartedDoc/step';
  5. import type {
  6. BasePlatformOptions,
  7. Docs,
  8. DocsParams,
  9. OnboardingConfig,
  10. } from 'sentry/components/onboarding/gettingStartedDoc/types';
  11. import {
  12. getReplayMobileConfigureDescription,
  13. getReplayVerifyStep,
  14. } from 'sentry/components/onboarding/gettingStartedDoc/utils/replayOnboarding';
  15. import {appleFeedbackOnboarding} from 'sentry/gettingStartedDocs/apple/macos';
  16. import {t, tct} from 'sentry/locale';
  17. import {getPackageVersion} from 'sentry/utils/gettingStartedDocs/getPackageVersion';
  18. export enum InstallationMode {
  19. AUTO = 'auto',
  20. MANUAL = 'manual',
  21. }
  22. const platformOptions = {
  23. installationMode: {
  24. label: t('Installation Mode'),
  25. items: [
  26. {
  27. label: t('Auto'),
  28. value: InstallationMode.AUTO,
  29. },
  30. {
  31. label: t('Manual'),
  32. value: InstallationMode.MANUAL,
  33. },
  34. ],
  35. defaultValue:
  36. navigator.userAgent.indexOf('Win') !== -1
  37. ? InstallationMode.MANUAL
  38. : InstallationMode.AUTO,
  39. },
  40. } satisfies BasePlatformOptions;
  41. type PlatformOptions = typeof platformOptions;
  42. type Params = DocsParams<PlatformOptions>;
  43. const isAutoInstall = (params: Params) =>
  44. params.platformOptions.installationMode === InstallationMode.AUTO;
  45. const getAutoInstallSnippet = () =>
  46. `brew install getsentry/tools/sentry-wizard && sentry-wizard -i ios`;
  47. const getManualInstallSnippet = (params: Params) => `
  48. .package(url: "https://github.com/getsentry/sentry-cocoa", from: "${getPackageVersion(
  49. params,
  50. 'sentry.cocoa',
  51. '8.9.3'
  52. )}"),`;
  53. const getConfigurationSnippet = (params: Params) => `
  54. import Sentry
  55. // ....
  56. func application(_ application: UIApplication,
  57. didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
  58. SentrySDK.start { options in
  59. options.dsn = "${params.dsn.public}"
  60. options.debug = true // Enabling debug when first installing is always helpful${
  61. params.isPerformanceSelected
  62. ? `
  63. // Set tracesSampleRate to 1.0 to capture 100% of transactions for tracing.
  64. // We recommend adjusting this value in production.
  65. options.tracesSampleRate = 1.0`
  66. : ''
  67. }${
  68. params.isProfilingSelected &&
  69. params.profilingOptions?.defaultProfilingMode !== 'continuous'
  70. ? `
  71. // Sample rate for profiling, applied on top of TracesSampleRate.
  72. // We recommend adjusting this value in production.
  73. options.profilesSampleRate = 1.0`
  74. : ''
  75. }
  76. }${
  77. params.isProfilingSelected &&
  78. params.profilingOptions?.defaultProfilingMode === 'continuous'
  79. ? `
  80. // Manually call startProfiler and stopProfiler
  81. // to profile the code in between
  82. SentrySDK.startProfiler()
  83. // this code will be profiled
  84. //
  85. // Calls to stopProfiler are optional - if you don't stop the profiler, it will keep profiling
  86. // your application until the process exits or stopProfiler is called.
  87. SentrySDK.stopProfiler()`
  88. : ''
  89. }
  90. return true
  91. }`;
  92. const getConfigurationSnippetSwiftUi = (params: Params) => `
  93. import Sentry
  94. @main
  95. struct SwiftUIApp: App {
  96. init() {
  97. SentrySDK.start { options in
  98. options.dsn = "${params.dsn.public}"
  99. options.debug = true // Enabling debug when first installing is always helpful${
  100. params.isPerformanceSelected
  101. ? `
  102. // Set tracesSampleRate to 1.0 to capture 100% of transactions for tracing.
  103. // We recommend adjusting this value in production.
  104. options.tracesSampleRate = 1.0`
  105. : ''
  106. }${
  107. params.isProfilingSelected &&
  108. params.profilingOptions?.defaultProfilingMode !== 'continuous'
  109. ? `
  110. // Sample rate for profiling, applied on top of TracesSampleRate.
  111. // We recommend adjusting this value in production.
  112. options.profilesSampleRate = 1.0`
  113. : ''
  114. }
  115. }${
  116. params.isProfilingSelected &&
  117. params.profilingOptions?.defaultProfilingMode === 'continuous'
  118. ? `
  119. // Manually call startProfiler and stopProfiler
  120. // to profile the code in between
  121. SentrySDK.startProfiler()
  122. // this code will be profiled
  123. //
  124. // Calls to stopProfiler are optional - if you don't stop the profiler, it will keep profiling
  125. // your application until the process exits or stopProfiler is called.
  126. SentrySDK.stopProfiler()`
  127. : ''
  128. }
  129. }
  130. }`;
  131. const getVerifySnippet = () => `
  132. let button = UIButton(type: .roundedRect)
  133. button.frame = CGRect(x: 20, y: 50, width: 100, height: 30)
  134. button.setTitle("Break the world", for: [])
  135. button.addTarget(self, action: #selector(self.breakTheWorld(_:)), for: .touchUpInside)
  136. view.addSubview(button)
  137. @IBAction func breakTheWorld(_ sender: AnyObject) {
  138. fatalError("Break the world")
  139. }`;
  140. const getExperimentalFeaturesSnippetSwift = () => `
  141. import Sentry
  142. SentrySDK.start { options in
  143. // ...
  144. // Enable all experimental features
  145. options.attachViewHierarchy = true
  146. options.enableMetricKit = true
  147. options.enableTimeToFullDisplayTracing = true
  148. options.swiftAsyncStacktraces = true
  149. options.enableAppLaunchProfiling = true
  150. }`;
  151. const getExperimentalFeaturesSnippetObjC = () => `
  152. @import Sentry;
  153. [SentrySDK startWithConfigureOptions:^(SentryOptions *options) {
  154. // ...
  155. // Enable all experimental features
  156. options.attachViewHierarchy = YES;
  157. options.enableMetricKit = YES;
  158. options.enableTimeToFullDisplayTracing = YES;
  159. options.swiftAsyncStacktraces = YES;
  160. options.enableAppLaunchProfiling = YES;
  161. }];`;
  162. const getReplaySetupSnippet = (params: Params) => `
  163. SentrySDK.start(configureOptions: { options in
  164. options.dsn = "${params.dsn.public}"
  165. options.debug = true
  166. options.sessionReplay.onErrorSampleRate = 1.0
  167. options.sessionReplay.sessionSampleRate = 0.1
  168. })`;
  169. const getReplayConfigurationSnippet = () => `
  170. options.sessionReplay.redactAllText = true
  171. options.sessionReplay.redactAllImages = true`;
  172. const onboarding: OnboardingConfig<PlatformOptions> = {
  173. install: params =>
  174. isAutoInstall(params)
  175. ? [
  176. {
  177. type: StepType.INSTALL,
  178. description: (
  179. <p>
  180. {tct(
  181. 'Add Sentry automatically to your app with the [wizardLink:Sentry wizard] (call this inside your project directory).',
  182. {
  183. wizardLink: (
  184. <ExternalLink href="https://docs.sentry.io/platforms/apple/guides/ios/#install" />
  185. ),
  186. }
  187. )}
  188. </p>
  189. ),
  190. configurations: [
  191. {
  192. language: 'bash',
  193. code: getAutoInstallSnippet(),
  194. },
  195. ],
  196. },
  197. ]
  198. : [
  199. {
  200. type: StepType.INSTALL,
  201. description: tct(
  202. 'We recommend installing the SDK with Swift Package Manager (SPM), but we also support [alternateMethods: alternate installation methods]. To integrate Sentry into your Xcode project using SPM, open your App in Xcode and open [addPackage: File > Add Packages]. Then add the SDK by entering the Git repo url in the top right search field:',
  203. {
  204. alternateMethods: (
  205. <ExternalLink href="https://docs.sentry.io/platforms/apple/install/" />
  206. ),
  207. addPackage: <strong />,
  208. }
  209. ),
  210. configurations: [
  211. {
  212. language: 'url',
  213. code: `https://github.com/getsentry/sentry-cocoa.git`,
  214. },
  215. {
  216. description: (
  217. <p>
  218. {tct(
  219. 'Alternatively, when your project uses a [packageSwift: Package.swift] file to manage dependencies, you can specify the target with:',
  220. {
  221. packageSwift: <code />,
  222. }
  223. )}
  224. </p>
  225. ),
  226. language: 'swift',
  227. partialLoading: params.sourcePackageRegistries.isLoading,
  228. code: getManualInstallSnippet(params),
  229. },
  230. ],
  231. },
  232. ],
  233. configure: params =>
  234. isAutoInstall(params)
  235. ? [
  236. {
  237. type: StepType.CONFIGURE,
  238. description: t(
  239. 'The Sentry wizard will automatically patch your application:'
  240. ),
  241. configurations: [
  242. {
  243. description: (
  244. <List symbol="bullet">
  245. <ListItem>
  246. {t('Install the Sentry SDK via Swift Package Manager or Cocoapods')}
  247. </ListItem>
  248. <ListItem>
  249. {tct(
  250. 'Update your [appDelegate: AppDelegate] or SwiftUI App Initializer with the default Sentry configuration and an example error',
  251. {
  252. appDelegate: <code />,
  253. }
  254. )}
  255. </ListItem>
  256. <ListItem>
  257. {tct(
  258. 'Add a new [code: Upload Debug Symbols] phase to your [code: xcodebuild] build script',
  259. {
  260. code: <code />,
  261. }
  262. )}
  263. </ListItem>
  264. <ListItem>
  265. {tct(
  266. 'Create [code: .sentryclirc] with an auth token to upload debug symbols (this file is automatically added to [code: .gitignore])',
  267. {
  268. code: <code />,
  269. }
  270. )}
  271. </ListItem>
  272. <ListItem>
  273. {t(
  274. "When you're using Fastlane, it will add a Sentry lane for uploading debug symbols"
  275. )}
  276. </ListItem>
  277. </List>
  278. ),
  279. additionalInfo: tct(
  280. 'Alternatively, you can also [manualSetupLink:set up the SDK manually].',
  281. {
  282. manualSetupLink: (
  283. <ExternalLink href="https://docs.sentry.io/platforms/apple/guides/ios/manual-setup/" />
  284. ),
  285. stepsBelow: <strong />,
  286. }
  287. ),
  288. },
  289. ],
  290. },
  291. ]
  292. : [
  293. {
  294. type: StepType.CONFIGURE,
  295. description: (
  296. <p>
  297. {tct(
  298. 'Make sure you initialize the SDK as soon as possible in your application lifecycle e.g. in your [appDelegate:] method:',
  299. {
  300. appDelegate: (
  301. <code>
  302. - [UIAppDelegate application:didFinishLaunchingWithOptions:]
  303. </code>
  304. ),
  305. }
  306. )}
  307. </p>
  308. ),
  309. configurations: [
  310. {
  311. language: 'swift',
  312. code: getConfigurationSnippet(params),
  313. },
  314. {
  315. description: (
  316. <p>
  317. {tct(
  318. "When using SwiftUI and your app doesn't implement an app delegate, initialize the SDK within the [initializer: App conformer's initializer]:",
  319. {
  320. initializer: (
  321. <ExternalLink href="https://developer.apple.com/documentation/swiftui/app/main()" />
  322. ),
  323. }
  324. )}
  325. </p>
  326. ),
  327. language: 'swift',
  328. code: getConfigurationSnippetSwiftUi(params),
  329. },
  330. ],
  331. },
  332. ],
  333. verify: params =>
  334. isAutoInstall(params)
  335. ? [
  336. {
  337. type: StepType.VERIFY,
  338. description: t(
  339. 'The Sentry wizard automatically adds a code snippet that captures a message to your project. Simply run your app and you should see this message in your Sentry project.'
  340. ),
  341. },
  342. {
  343. title: t('Experimental Features'),
  344. description: tct(
  345. 'Want to play with some new features? Try out our experimental features for [vh: View Hierarchy], [ttfd: Time to Full Display (TTFD)], [metricKit: MetricKit], [prewarmedAppStart: Prewarmed App Start Tracing], and [asyncStacktraces: Swift Async Stacktraces]. Experimental features are still a work-in-progress and may have bugs. We recognize the irony. [break] Let us know if you have feedback through [gh: GitHub issues].',
  346. {
  347. vh: (
  348. <ExternalLink href="https://docs.sentry.io/platforms/apple/guides/ios/enriching-events/viewhierarchy/" />
  349. ),
  350. ttfd: (
  351. <ExternalLink href="https://docs.sentry.io/platforms/apple/guides/ios/tracing/instrumentation/automatic-instrumentation/#time-to-full-display" />
  352. ),
  353. metricKit: (
  354. <ExternalLink href="https://docs.sentry.io/platforms/apple/guides/watchos/configuration/metric-kit/" />
  355. ),
  356. prewarmedAppStart: (
  357. <ExternalLink href="https://docs.sentry.io/platforms/apple/tracing/instrumentation/automatic-instrumentation/#prewarmed-app-start-tracing" />
  358. ),
  359. asyncStacktraces: (
  360. <ExternalLink href="https://docs.sentry.io/platforms/apple/guides/ios/#stitch-together-swift-concurrency-stack-traces" />
  361. ),
  362. gh: (
  363. <ExternalLink href="https://github.com/getsentry/sentry-cocoa/issues" />
  364. ),
  365. break: <br />,
  366. }
  367. ),
  368. configurations: [
  369. {
  370. code: [
  371. {
  372. label: 'Swift',
  373. value: 'swift',
  374. language: 'swift',
  375. code: getExperimentalFeaturesSnippetSwift(),
  376. },
  377. {
  378. label: 'Objective-C',
  379. value: 'c',
  380. language: 'c',
  381. code: getExperimentalFeaturesSnippetObjC(),
  382. },
  383. ],
  384. },
  385. ],
  386. },
  387. ]
  388. : [
  389. {
  390. type: StepType.VERIFY,
  391. description: (
  392. <p>
  393. {tct(
  394. 'This snippet contains an intentional error you can use to test that errors are uploaded to Sentry correctly. You can add it to your main [viewController: ViewController].',
  395. {
  396. viewController: <code />,
  397. }
  398. )}
  399. </p>
  400. ),
  401. configurations: [
  402. {
  403. language: 'swift',
  404. code: getVerifySnippet(),
  405. },
  406. ],
  407. },
  408. ],
  409. nextSteps: () => [
  410. {
  411. id: 'cocoapods-carthage',
  412. name: t('CocoaPods/Carthage'),
  413. description: t(
  414. 'Learn about integrating Sentry into your project using CocoaPods or Carthage.'
  415. ),
  416. link: 'https://docs.sentry.io/platforms/apple/install/',
  417. },
  418. {
  419. id: 'debug-symbols',
  420. name: t('Debug Symbols'),
  421. description: t('Symbolicate and get readable stacktraces in your Sentry errors.'),
  422. link: 'https://docs.sentry.io/platforms/apple/dsym/',
  423. },
  424. {
  425. id: 'swiftui',
  426. name: t('SwiftUI'),
  427. description: t('Learn about our first class integration with SwiftUI.'),
  428. link: 'https://docs.sentry.io/platforms/apple/tracing/instrumentation/swiftui-instrumentation/',
  429. },
  430. ],
  431. };
  432. const replayOnboarding: OnboardingConfig<PlatformOptions> = {
  433. install: (params: Params) => [
  434. {
  435. type: StepType.INSTALL,
  436. description: t(
  437. 'Make sure your Sentry Cocoa SDK version is at least 8.43.0. If you already have the SDK installed, you can update it to the latest version with:'
  438. ),
  439. configurations: [
  440. {
  441. code: [
  442. {
  443. label: 'SPM',
  444. value: 'spm',
  445. language: 'swift',
  446. code: `.package(url: "https://github.com/getsentry/sentry-cocoa", from: "${getPackageVersion(
  447. params,
  448. 'sentry.cocoa',
  449. '8.36.0'
  450. )}"),`,
  451. },
  452. {
  453. label: 'CocoaPods',
  454. value: 'cocoapods',
  455. language: 'ruby',
  456. code: `pod update`,
  457. },
  458. {
  459. label: 'Carthage',
  460. value: 'carthage',
  461. language: 'swift',
  462. code: `github "getsentry/sentry-cocoa" "${getPackageVersion(
  463. params,
  464. 'sentry.cocoa',
  465. '8.36.0'
  466. )}"`,
  467. },
  468. ],
  469. },
  470. {
  471. description: t(
  472. 'To set up the integration, add the following to your Sentry initialization:'
  473. ),
  474. },
  475. {
  476. code: [
  477. {
  478. label: 'Swift',
  479. value: 'swift',
  480. language: 'swift',
  481. code: getReplaySetupSnippet(params),
  482. },
  483. ],
  484. },
  485. ],
  486. },
  487. ],
  488. configure: () => [
  489. {
  490. type: StepType.CONFIGURE,
  491. description: getReplayMobileConfigureDescription({
  492. link: 'https://docs.sentry.io/platforms/apple/guides/ios/session-replay/#privacy',
  493. }),
  494. configurations: [
  495. {
  496. description: t(
  497. 'The following code is the default configuration, which masks and blocks everything.'
  498. ),
  499. code: [
  500. {
  501. label: 'Swift',
  502. value: 'swift',
  503. language: 'swift',
  504. code: getReplayConfigurationSnippet(),
  505. },
  506. ],
  507. },
  508. ],
  509. },
  510. ],
  511. verify: getReplayVerifyStep({
  512. replayOnErrorSampleRateName: 'options\u200b.sessionReplay\u200b.onErrorSampleRate',
  513. replaySessionSampleRateName: 'options\u200b.sessionReplay\u200b.sessionSampleRate',
  514. }),
  515. nextSteps: () => [],
  516. };
  517. const docs: Docs<PlatformOptions> = {
  518. onboarding,
  519. feedbackOnboardingCrashApi: appleFeedbackOnboarding,
  520. crashReportOnboarding: appleFeedbackOnboarding,
  521. platformOptions,
  522. replayOnboarding,
  523. };
  524. export default docs;