Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,41 @@
> This release promotes Metrics out of experimental and **removes** `options.experimental.enableMetrics` and `options.experimental.beforeSendMetric`. If you set either of these, your app will fail to compile after upgrading.
> Migrate to `options.enableMetrics` and `options.beforeSendMetric` (top-level on `Options`) — the defaults and behavior are unchanged.

> [!WARNING]
> Session Replay now runs on iOS 26 with Liquid Glass. Previously, the SDK auto-disabled Session Replay on iOS 26 builds that adopted Liquid Glass (built with Xcode 26+ and `UIDesignRequiresCompatibility` not set). Now that the underlying redaction issues have been addressed, replays will be captured in those environments — verify your masking still meets your privacy requirements.
> If you want to keep Session Replay disabled on Liquid Glass builds, you will need to gate the sample rates yourself. For reference, see how the SDK used to perform the check: https://github.com/getsentry/sentry-cocoa/blob/adef457c1344e5efda4b74a1f33913d4d49ef7e0/Sources/Swift/Integrations/SessionReplay/SentrySessionReplayEnvironmentChecker.swift
>
> Example — disable Session Replay when Liquid Glass is active:
>
> ```swift
> import Sentry
>
> SentrySDK.start { options in
> options.dsn = "___PUBLIC_DSN___"
>
> var sessionRate: Float = 0.2
> var errorRate: Float = 1.0
>
> if #available(iOS 26.0, *) {
> let compatibilityMode = Bundle.main.object(forInfoDictionaryKey: "UIDesignRequiresCompatibility") as? Bool ?? false
> let xcodeVersion = Int(Bundle.main.object(forInfoDictionaryKey: "DTXcode") as? String ?? "") ?? 0
> let builtWithXcode26OrLater = xcodeVersion >= 2600
> let liquidGlassActive = builtWithXcode26OrLater && !compatibilityMode
> if liquidGlassActive {
> sessionRate = 0
> errorRate = 0
> }
> }
>
> options.sessionReplay.sessionSampleRate = sessionRate
> options.sessionReplay.onErrorSampleRate = errorRate
> }
> ```

### Improvements

- Remove `enableSessionReplayInUnreliableEnvironment` experimental option and the environment checker that temporarily disabled Session Replay on iOS 26 (#7831)

### Features

- Make feature Metrics generally available, moving experimental options to top-level options (#7843)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,6 @@ public enum SentrySDKOverrides: String, CaseIterable {

case disableMaskAllImages = "--io.sentry.session-replay.disable-mask-all-images"
case disableMaskAllText = "--io.sentry.session-replay.disable-mask-all-text"

case enableInUnreliableEnvironment = "--io.sentry.session-replay.enable-in-unreliable-environment"
}
case sessionReplay = "Session Replay"

Expand Down Expand Up @@ -323,7 +321,7 @@ extension SentrySDKOverrides.Performance {
extension SentrySDKOverrides.SessionReplay {
public var overrideType: OverrideType {
switch self {
case .disable, .disableViewRendererV2, .enableFastViewRendering, .disableMaskAllText, .disableMaskAllImages, .enableInUnreliableEnvironment: return .boolean
case .disable, .disableViewRendererV2, .enableFastViewRendering, .disableMaskAllText, .disableMaskAllImages: return .boolean
case .onErrorSampleRate, .sessionSampleRate: return .float
case .quality: return .string
}
Expand Down Expand Up @@ -420,7 +418,7 @@ extension SentrySDKOverrides.SessionReplay {
public var ignoresDisableEverything: Bool {
switch self {
case .disable: return false
case .disableViewRendererV2, .enableFastViewRendering, .disableMaskAllText, .disableMaskAllImages, .onErrorSampleRate, .sessionSampleRate, .quality, .enableInUnreliableEnvironment: return true
case .disableViewRendererV2, .enableFastViewRendering, .disableMaskAllText, .disableMaskAllImages, .onErrorSampleRate, .sessionSampleRate, .quality: return true
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,6 @@ public struct SentrySDKWrapper {
]
let defaultReplayQuality = options.sessionReplay.quality
options.sessionReplay.quality = SentryReplayOptions.SentryReplayQuality(rawValue: (SentrySDKOverrides.SessionReplay.quality.stringValue as? NSString)?.integerValue ?? defaultReplayQuality.rawValue) ?? defaultReplayQuality

// Allow configuring unreliable environment protection via SDK override.
// Default to false for the sample app to allow testing on iOS 26+ with Liquid Glass.
options.experimental.enableSessionReplayInUnreliableEnvironment = SentrySDKOverrides.SessionReplay.enableInUnreliableEnvironment.boolValue
}

#endif // !os(macOS) && !os(watchOS) && !os(visionOS)
Expand Down
1 change: 0 additions & 1 deletion Samples/Shared/feature-flags.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ schemeTemplates:
"--io.sentry.session-replay.enable-fast-view-rendering": false
"--io.sentry.session-replay.disable-mask-all-images": false
"--io.sentry.session-replay.disable-mask-all-text": false
"--io.sentry.session-replay.enable-in-unreliable-environment": false

# user feedback
"--io.sentry.feedback.use-custom-feedback-button": false
Expand Down
4 changes: 0 additions & 4 deletions Sentry.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,6 @@
D4CBA2472DE06D0200581618 /* libSentryTestUtils.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8431F00A29B284F200D8DC56 /* libSentryTestUtils.a */; };
D4CBA2532DE06D1600581618 /* TestConstantTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4CBA2512DE06D1600581618 /* TestConstantTests.swift */; };
D4DEE6592E439B2E00FCA5A9 /* SentryProfileTimeseriesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D4DEE6582E439B2E00FCA5A9 /* SentryProfileTimeseriesTests.m */; };
D4E9420C2E9D1D8000DB7521 /* TestSessionReplayEnvironmentCheckerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4E9420B2E9D1D7600DB7521 /* TestSessionReplayEnvironmentCheckerTests.swift */; };
D4ECA4012E3CBEDE00C757EA /* SentryDummyPublicEmptyClass.m in Sources */ = {isa = PBXBuildFile; fileRef = D4ECA4002E3CBEDE00C757EA /* SentryDummyPublicEmptyClass.m */; };
D4ECA4022E3CBEDE00C757EA /* SentryDummyPrivateEmptyClass.m in Sources */ = {isa = PBXBuildFile; fileRef = D4ECA3FF2E3CBEDE00C757EA /* SentryDummyPrivateEmptyClass.m */; };
D4EE12D22DE9AC3800385BAF /* TestNSNotificationCenterWrapperTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4EE12D12DE9AC3300385BAF /* TestNSNotificationCenterWrapperTests.swift */; };
Expand Down Expand Up @@ -1054,7 +1053,6 @@
D4CBA2432DE06D0200581618 /* SentryTestUtilsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SentryTestUtilsTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
D4CBA2512DE06D1600581618 /* TestConstantTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestConstantTests.swift; sourceTree = "<group>"; };
D4DEE6582E439B2E00FCA5A9 /* SentryProfileTimeseriesTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryProfileTimeseriesTests.m; sourceTree = "<group>"; };
D4E9420B2E9D1D7600DB7521 /* TestSessionReplayEnvironmentCheckerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestSessionReplayEnvironmentCheckerTests.swift; sourceTree = "<group>"; };
D4ECA3FF2E3CBEDE00C757EA /* SentryDummyPrivateEmptyClass.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryDummyPrivateEmptyClass.m; sourceTree = "<group>"; };
D4ECA4002E3CBEDE00C757EA /* SentryDummyPublicEmptyClass.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryDummyPublicEmptyClass.m; sourceTree = "<group>"; };
D4EE12D12DE9AC3300385BAF /* TestNSNotificationCenterWrapperTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestNSNotificationCenterWrapperTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2106,7 +2104,6 @@
D43B0E5F2DE7416600EE3759 /* TestFileManagerTests.swift */,
D4599F8E2E9911380045BB95 /* TestInfoPlistWrapperTests.swift */,
D4EE12D12DE9AC3300385BAF /* TestNSNotificationCenterWrapperTests.swift */,
D4E9420B2E9D1D7600DB7521 /* TestSessionReplayEnvironmentCheckerTests.swift */,
);
path = Sources;
sourceTree = "<group>";
Expand Down Expand Up @@ -3120,7 +3117,6 @@
D44B16722DE464AD006DBDB3 /* TestDispatchFactoryTests.swift in Sources */,
D4EE12D22DE9AC3800385BAF /* TestNSNotificationCenterWrapperTests.swift in Sources */,
62E75EB92E152953002EC91B /* InvocationsTests.swift in Sources */,
D4E9420C2E9D1D8000DB7521 /* TestSessionReplayEnvironmentCheckerTests.swift in Sources */,
D4599F8F2E99113E0045BB95 /* TestInfoPlistWrapperTests.swift in Sources */,
D4CBA2532DE06D1600581618 /* TestConstantTests.swift in Sources */,
);
Expand Down

This file was deleted.

This file was deleted.

9 changes: 0 additions & 9 deletions Sources/Sentry/SentryReplayApi.m
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,6 @@ - (void)start SENTRY_DISABLE_THREAD_SANITIZER("double-checked lock produce false
SentryOptions, SentrySDKInternal.currentHub.client.options);
SentryDependencyContainer *sharedContainer =
[SentryDependencyContainer sharedInstance];
if (![SentrySessionReplay
shouldEnableSessionReplayWithEnvironmentChecker:
[sharedContainer sessionReplayEnvironmentChecker]
experimentalOptions:currentOptions
.experimental]) {
SENTRY_LOG_ERROR(@"[Session Replay] Session replay is disabled due to "
@"environment potentially causing PII leaks.");
return;
}
SENTRY_LOG_DEBUG(@"[Session Replay] Initializing replay integration");

replayIntegration =
Expand Down
3 changes: 0 additions & 3 deletions Sources/Swift/Helper/Dependencies.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@
@objc public static let threadWrapper = SentryThreadWrapper()
@objc public static let processInfoWrapper: SentryProcessInfoSource = ProcessInfo.processInfo
static let infoPlistWrapper: SentryInfoPlistWrapperProvider = SentryInfoPlistWrapper()
@objc public static let sessionReplayEnvironmentChecker: SentrySessionReplayEnvironmentChecker = {
SentrySessionReplayEnvironmentChecker(infoPlistWrapper: Dependencies.infoPlistWrapper)
}()
@objc public static let dispatchQueueWrapper = SentryDispatchQueueWrapper()
@objc public static let notificationCenterWrapper: SentryNSNotificationCenterWrapper = NotificationCenter.default
@objc public static let binaryImageCache = SentryBinaryImageCache()
Expand Down
14 changes: 0 additions & 14 deletions Sources/Swift/Helper/InfoPlist/SentryInfoPlistKey.swift
Original file line number Diff line number Diff line change
@@ -1,18 +1,4 @@
enum SentryInfoPlistKey: String {
/// Key used to set the Xcode version used to build app
case xcodeVersion = "DTXcode"

/// A Boolean value that indicates whether the system runs the app using a compatibility mode for UI.
///
/// If `YES`, the system runs the app using a compatibility mode for UI elements. The compatibility mode displays the app as it looks when built against previous versions of the SDKs.
///
/// If `NO`, the system uses the UI design of the running OS, with no compatibility mode. Absence of the key, or NO, is the default value for apps linking against the latest SDKs.
///
/// - Warning: This key is used temporarily while reviewing and refining an app's UI for the design in the latest SDKs (i.e. Liquid Glass).
///
/// - SeeAlso: [Apple Documentation](https://developer.apple.com/documentation/BundleResources/Information-Property-List/UIDesignRequiresCompatibility)
case designRequiresCompatibility = "UIDesignRequiresCompatibility"

/// The extension configuration dictionary for app extensions
///
/// - SeeAlso: [Apple Documentation](https://developer.apple.com/documentation/bundleresources/information_property_list/nsextension)
Expand Down
4 changes: 0 additions & 4 deletions Sources/Swift/Helper/InfoPlist/SentryXcodeVersion.swift

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -69,23 +69,6 @@ import UIKit

deinit { displayLink.invalidate() }

@objc
static public func shouldEnableSessionReplay(environmentChecker: SentrySessionReplayEnvironmentCheckerProvider, experimentalOptions: SentryExperimentalOptions) -> Bool {
// Detect if we are running on iOS 26.0 with Liquid Glass and disable session replay.
// This needs to be done until masking for session replay is properly supported, as it can lead
// to PII leaks otherwise.
if environmentChecker.isReliable() {
return true
}
guard experimentalOptions.enableSessionReplayInUnreliableEnvironment else {
SentrySDKLog.fatal("[Session Replay] Detected environment potentially causing PII leaks, disabling Session Replay. To override this mechanism, set `options.experimental.enableSessionReplayInUnreliableEnvironment` to `true`")
return false
}
SentrySDKLog.warning("[Session Replay] Detected environment potentially causing PII leaks, but `options.experimental.enableSessionReplayInUnreliableEnvironment` is set to `true`, ignoring and enabling Session Replay.")

return true
}

public func start(rootView: UIView?, fullSession: Bool) {
SentrySDKLog.debug("[Session Replay] Starting session replay with full session: \(fullSession)")
guard !isRunning else {
Expand Down
Loading
Loading