Migration Guide

To upgrade from version 4.x of the SDK to version 9.x of the SDK, you must first migrate from 4.x to 5.x, then 5.x to 6.x, then 6.x to 7.x, 7.x to 8.x, and finally from 8.x to 9.x.

Migrating to 9.x from 8.x includes several breaking changes. We provide this guide to help you update your SDK.

We bumped the minimum supported OS versions to:

  • iOS: 15.0 (previously 11.0)
  • macOS: 10.14 (previously 10.13)
  • tvOS: 15.0 (previously 11.0)
  • visionOS: 1.0 (unchanged)
  • watchOS: 8.0 (previously 4.0)

We now build the precompiled XCFramework with Xcode 16. To submit to the App Store, Apple now requires Xcode 16. If you need a precompiled XCFramework built with Xcode 15, continue using Sentry SDK 8.x.x.

Additionally, the Package.swift sets swift-tools-version to 6.0.

We dropped official support for Carthage in v9. If you're using Carthage, please migrate to Swift Package Manager (SPM) or manually install the pre-built XCFramework from GitHub releases.

We now enabled the following features by default:

  • Performance V2 is enabled by default: The app start duration now finishes when the first frame is drawn instead of when the OS posts the UIWindowDidBecomeVisibleNotification. We removed the enablePerformanceV2 option.
  • Pre-warmed app start tracking: The SDK now collects pre-warmed app starts by default via enablePreWarmedAppStartTracing.
  • App hang tracking V2: This is now the default only on **iOS and tvOS and we removed the option to enable/disable it. macOS still uses V1.

We now automatically disable app hang tracking for: Widgets, Live Activities, Action Extensions, (Siri) Intent Extensions, Share Extensions. These components run in separate processes or sandboxes with different execution characteristics, which can cause false positive app hang reports.

We moved structured logging out of experimental and made it part of the stable API. The enableLogs option moved from options.experimental.enableLogs to options.enableLogs. We added log APIs to Hub and Client, and logs now include a sentry.replay_id attribute.

Migration required: Update your code from options.experimental.enableLogs = true to options.enableLogs = true. Logging is not enabled by default; you must explicitly set this option.

HTTP client errors now mark sessions as errored. This provides better visibility into failed network requests in your release health data.

We removed all deprecated profiling APIs in version 9.0.0.

  • enableFileManagerSwizzling is now a top-level non-experimental option and remains disabled by default.
  • enableDataSwizzling is now a top-level option and is enabled by default.
  • enableLogs is now a top-level non-experimental option and remains disabled by default (you must set it to true to enable logging).
  • We increased the maximum attachment size to 200MB (previously 20MB)
  • We removed the following methods and properties:
    • inAppExclude (it had no effect)
    • integrations
    • defaultIntegrations()
    • enableTracing (use tracesSampleRate or tracesSampler instead)
    • getStoreEndpoint()
    • enablePerformanceV2 the behavior of this option is now enabled by default.

  • The default trace context status is now ok instead of undefined.
  • The function property on SentryFrame now defaults to nil instead of "<redacted>"
  • The value and type properties on SentryException are now nullable; when NSException has no reason, type is set to nil
  • We changed the type of the http.response.status_code attribute for spans to int
  • We converted SentryDsn to Swift and removed the public header file SentryDsn.h

  • We renamed SentryStructuredLogLevel to SentryLogLevel
  • We renamed SentryStructuredLogAttribute to SentryLogAttribute

  • We removed the segment property from SentryTraceContext, SentryUser, and SentryBaggage
  • We removed the initializers from SentryTraceContext
  • We removed SentryDsn.getHash()
  • We removed SentryFrame.instruction

We removed the following deprecated APIs:

  • SentrySpan.setExtraValue(_:forKey:)
  • User feedback API (use the new feedback API instead)
  • Scope.useSpan() (use Scope.span instead)
  • SentryDebugMeta.uuid (use debugID instead)
  • SentryDebugMeta.name (use codeFile instead)

We made the following classes and APIs private:

  • SentryEventDecoder and SentryEventDecodable
  • SentryEnvelopeItemHeader
  • SentryIntegrationProtocol
  • SentrySession
  • SentrySDKInfo
  • SentryDebugImageProvider

  • We made the following classes final: PreviewRedactOptions, SentryProfileOptions, SentryRedactViewHelper, SentryViewScreenshotOptions, SentryReplayOptions, SentryUserFeedbackConfiguration, SentryUserFeedbackFormConfiguration, SentryUserFeedbackThemeConfiguration, SentryUserFeedbackWidgetConfiguration, SentryFeedback, and SentryExperimentalOptions

For a complete list of changes, see the Changelog of version 9.0.0

Migrating to 8.x from 7.x includes a few breaking changes. We provide this guide to help you update your SDK. It's important to note that this version adds a dependency to Swift, and that we renamed the default branch on the sentry-cocoa repository from master to main.

The minimum supported OS versions have been bumped to macOS 10.13, iOS 11, tvOS 11, and watchOS 4. We bumped the minimum Xcode version to 13.

The following features are now enabled by default:

App Hang events might group differently as we now set the event stack trace snapshot property to true.

The OOM (out of memory integration) actually tracks watchdog terminations based on heuristics. We renamed the integration to better reflect what it does.

This version includes the following configuration changes:

  • Rename SentryOptions.enableAutoPerformanceTracking to SentryOptions.enableAutoPerformanceTracing
  • Rename SentryOptions.enableUIViewControllerTracking to SentryOptions.enableUIViewControllerTracing
  • Rename SentryOptions.enablePreWarmedAppStartTracking to SentryOptions.enablePreWarmedAppStartTracing
  • Rename SentryOptions.enableFileIOTracking to SentryOptions.enableFileIOTracing
  • Rename SentryOptions.enableCoreDataTracking to SentryOptions.enableCoreDataTracing
  • Rename SentryOptions.enableOutOfMemoryTracking to SentryOptions.enableWatchdogTerminationTracking

We made some changes to make the API more ergonomic in Swift:

  • Rename SentrySDK.addBreadcrumb(crumb:) to SentrySDK.addBreadcrumb(_ crumb:)
  • Rename SentryScope.add(_ crumb:) to SentryScope.addBreadcrumb(_ crumb:)
  • Rename SentryScope.add(_ attachment:) to SentryScope.addAttachment(_ attachment:)
  • Rename Client to SentryClient

We cleaned up our public classes by removing a few functions and properties, that shouldn't be public, to make the API cleaner. In case we removed something you need, please open an issue on GitHub.

  • Make SpanProtocol.data non nullable
  • Mark [SpanProtocol setExtraValue:forKey:] as deprecated
  • Make SpanContext immutable
    • Remove tags from SpanContext
    • Remove context property from SentrySpan
  • Remove SentryScope.apply(to:)
  • Remove SentryScope.apply(to:maxBreadcrumb:)
  • Remove [SentryOptions initWithDict:didFailWithError:]
  • Remove [SentryOptions sdkInfo]
  • Make SentrySession and SentrySDKInfo internal
  • Remove default attachment content type
  • Remove captureEnvelope from SentryHub and SentryClient
  • Remove confusing transaction tag

We removed the version of SentrySDK.startWithOptions that took a dictionary, and renamed SentrySDK.startWithOptionsObject to SentrySDK.startWithOptions. The recommended way to initialize Sentry has not changed:

Copied
import Sentry

SentrySDK.start { options in
    options.dsn = "___PUBLIC_DSN___"
    // ...
}

SentrySDK.close now calls flush, which is a blocking call.

Migrating to 7.x from 6.x includes a few breaking changes. We provide this guide to help you to update your SDK.

This version includes the following configuration changes:

  • Change the default maximum number of cached envelopes from 100 to 30. You can now configure this number with SentryOptions.maxCacheItems.
  • When setting a value SentryOptions.sampleRate that is not >= 0.0 and <= 1.0 the SDK sets it to the default of 1.0 instead of keeping the set value.

This version introduces a change to the grouping of issues. The SDK now sets the inApp flag for frames originating from only the main executable using CFBundleExecutable. In previous versions, all frames originating from the application bundle were marked as inApp. This had the downside of marking frames of private frameworks inside the bundle as inApp. This problem is fixed now. Applications using static frameworks shouldn't be affected by this change. For more information read mark in-app frames.

We cleaned up our public classes by removing a few functions and properties, that shouldn't be public, to make the API cleaner. In case we removed something you need, please open an issue on GitHub.

  • Remove SentrySDK.currentHub and SentrySDK.setCurrentHub.
  • Remove SentryClient.storeEnvelope, which is reserved for Hybrid SDKs.
  • Make closeCachedSessionWithTimestamp private, which is reserved for internal use.
  • Remove deprecated SentryHub.getScope. Use SentryHub.scope instead.
  • Replace SentryException.thread with SentryException.threadId and SentryException.stacktrace to align with the unified API.
  • Replace dict SentryMechanism.meta with new class SentryMechanismMeta and move SenryNSError to SentryMechanismMeta to align with the unified API.
  • Change SentryEvent.timestamp to nullable.

We replaced the SentryLogLevel with SentryLevel, renamed logLevel to diagnosticLevel on SentryOptions to align with other Sentry SDKs, and set the default diagnosticLevel to SentryLevel.debug. Furthermore, we removed setting the logLevel statically on the SentrySDK. Please use the SentryOptions to set the diagnosticLevel instead.

6.x

Copied
SentrySDK.start { options in
  options.logLevel = SentryLogLevel.verbose
}

// Or

SentrySDK.logLevel = SentryLogLevel.verbose

7.x

Copied
SentrySDK.start { options in
  options.diagnosticLevel = SentryLevel.debug
}

Migrating to 6.x from 5.x includes a few breaking changes. We provide this guide to help you to update your SDK.

This version includes the following configuration changes:

  • Auto Session Tracking is enabled by default. This feature is collecting and sending health data about the usage of your application.
  • Attach stack traces is enabled per default.
  • We bumped the minimum iOS version to 9.0.
  • Use a BOOL in SentryOptions instead of NSNumber to store booleans.
  • We had previously removed the enabled option from SentryOptions, but we brought it back in version 6.0.7 with slightly changed functionality. Previously setting an empty or incorrect DSN also set enabled to false. This side effect is removed. Setting the DSN has no impact on enabled. If the DSN is nil or empty or enabled is set to false and the client won't send any data to Sentry.

This version uses the envelope endpoint. If you are using self-hosted Sentry, you must use Sentry version >= v20.6.0 or higher. If you are using sentry.io, there is no impact. For this change, we also now cache events in envelopes on the disk. We decided not to migrate the few cached events from 5.x to 6.x into envelopes. Instead, we remove them from the disk. As a result, you might lose a few cached events when upgrading.

We removed the deprecated SDK inits. The recommended way to initialize Sentry is now:

Copied
import Sentry

SentrySDK.start { options in
    options.dsn = "___PUBLIC_DSN___"
    // ...
}

We cleaned up our public headers and made most of our classes private. If you can't access one of the classes you need please open an issue and tell us your use case so we can evaluates whether to either make the class public again or provide another API for you.

In 5.x, we used a nullable NSString to represent an event ID. The SDK, Hub, and Client returned this nullable NSString for the event ID to capture messages, events, errors, and so forth. In 6.x, we have a new type SentryId, which is not nullable, to represent an event ID. Instead of returning nil when an event couldn't be queued for submission we return SentryId.empty.

Example in 5.x:

Copied
import Sentry

let eventId = SentrySDK.capture(message: "A message")
if (nil != eventId) {
    // event was queued for submission
} else {
    // event wasn't queued for submission
}

Example in 6.x:

Copied
import Sentry

let eventId = SentrySDK.capture(message: "A message")
if (eventId != SentryId.empty) {
    // event was queued for submission
} else {
    // event wasn't queued for submission
}

In 6.x, we introduce a new type SentryMessage for event.message. SentryMessage provides you the ability to pass a format string with parameters to Sentry, which can help group similar messages into the same issue.

Example in 5.x:

Copied
import Sentry

let event = Event()
event.message = "Hello World"

Example in 6.x:

Copied
import Sentry

let event = Event()
event.message = SentryMessage(formatted: "Hello World")

In 5.x, you could pass a nullable scope to capture methods of the SDK, Hub, and Client, such as SentrySdk.captureMessage(). In 6.x, we changed the Scope to nonnull and provide overloads for the Hub and the Client.

Please see the Changelog for a complete list of changes.

The samples below illustrate how the SDK works:

Example in 4.x:

Copied
do {
    Client.shared = try Client(dsn: "___PUBLIC_DSN___")
    try Client.shared?.startCrashHandler()
} catch let error {
    print("\(error)")
}

Example in 5.x:

Copied
SentrySDK.start(options: [
    "dsn": "___PUBLIC_DSN___",
    "debug": true
])

Example in 4.x:`

Copied
Client.shared?.breadcrumbs.add(Breadcrumb(level: .info, category: "test"))

Example in 5.x:

Copied
SentrySDK.addBreadcrumb(Breadcrumb(level: .info, category: "test"))

Example in 4.x:

Copied
let event = Event(level: .debug)
event.message = "Test Message"
event.environment = "staging"
event.extra = ["ios": true]
Client.shared?.send(event: event)

Example in 5.x:

Copied
SentrySDK.capture(message: "Test Message") { (scope) in
    scope.setEnvironment("staging")
    scope.setExtras(["ios": true])
    let u = Sentry.User(userId: "1")
    u.email = "tony@example.com"
    scope.setUser(u)
}

Example in 4.x:

Copied
let u = User(userId: "1")
u.email = "tony@example.com"
Client.shared?.user = user

Example in 5.x:

Copied
let u = Sentry.User(userId: "1")
u.email = "tony@example.com"
SentrySDK.setUser(u)
Was this helpful?
Help improve this content
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").