Skip to content
Open
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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## Unreleased

### Fixes

- Add options `options.sessionReplay.includeSubtreeTraversalForViewType` and `options.sessionReplay.excludeSubtreeTraversalForViewType` to ignore views from subtree traversal (#7063)

## 8.57.3

### Fixes
Expand Down
16 changes: 8 additions & 8 deletions Sentry.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -698,8 +698,6 @@
84EB21942BF01C6C00EDDA28 /* TestNSNotificationCenterWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B18DE4328D9F8F6004845C6 /* TestNSNotificationCenterWrapper.swift */; };
84EB21962BF01CEA00EDDA28 /* SentryCrashInstallationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84EB21952BF01CEA00EDDA28 /* SentryCrashInstallationTests.swift */; };
84F2A1CE2E06001300A94524 /* (null) in Sources */ = {isa = PBXBuildFile; };
84F994E62A6894B500EC0190 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84F994E52A6894B500EC0190 /* CoreData.framework */; };
84F994E82A6894BD00EC0190 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 84F994E72A6894BD00EC0190 /* SystemConfiguration.framework */; platformFilters = (ios, maccatalyst, macos, tvos, ); };
861265F92404EC1500C4AFDE /* SentryArray.h in Headers */ = {isa = PBXBuildFile; fileRef = 861265F72404EC1500C4AFDE /* SentryArray.h */; };
861265FA2404EC1500C4AFDE /* SentryArray.m in Sources */ = {isa = PBXBuildFile; fileRef = 861265F82404EC1500C4AFDE /* SentryArray.m */; };
8E0551E026A7A63C00400526 /* TestProtocolClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8E0551DF26A7A63C00400526 /* TestProtocolClient.swift */; };
Expand Down Expand Up @@ -1015,6 +1013,8 @@
F41362152E1C568400B84443 /* SentryScopePersistentStore+Context.swift in Sources */ = {isa = PBXBuildFile; fileRef = F41362142E1C568400B84443 /* SentryScopePersistentStore+Context.swift */; };
F4227F092EFB0D8C004A27DB /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 6387B82F1ED851970045A84C /* libz.tbd */; };
F426748D2EB11E7900E09150 /* SentryReplayApiTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F42674872EB11E7000E09150 /* SentryReplayApiTests.swift */; };
F43F8CBC2EFC1E970004C45D /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F43F8CB62EFC1E970004C45D /* SystemConfiguration.framework */; platformFilters = (ios, maccatalyst, macos, tvos, xros, ); };
F43F8CBE2EFC1EA00004C45D /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F43F8CBD2EFC1EA00004C45D /* CoreData.framework */; };
F443DB272E09BE8C009A9045 /* LoadValidatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F443DB262E09BE8C009A9045 /* LoadValidatorTests.swift */; };
F44858132E03579D0013E63B /* SentryCrashDynamicLinker+Test.h in Headers */ = {isa = PBXBuildFile; fileRef = F44858122E0357940013E63B /* SentryCrashDynamicLinker+Test.h */; };
F451FAA62E0B304E0050ACF2 /* LoadValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = F451FAA52E0B304E0050ACF2 /* LoadValidator.swift */; };
Expand Down Expand Up @@ -2036,8 +2036,6 @@
84EACEBC2C33CA7A009B8753 /* SentryWithoutUIKit.modulemap */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; name = SentryWithoutUIKit.modulemap; path = Sources/Resources/SentryWithoutUIKit.modulemap; sourceTree = SOURCE_ROOT; };
84EACEDF2C3DCAE2009B8753 /* DeploymentTargets.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = DeploymentTargets.xcconfig; sourceTree = "<group>"; };
84EB21952BF01CEA00EDDA28 /* SentryCrashInstallationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryCrashInstallationTests.swift; sourceTree = "<group>"; };
84F994E52A6894B500EC0190 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = ./System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
84F994E72A6894BD00EC0190 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = ./System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
861265F72404EC1500C4AFDE /* SentryArray.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SentryArray.h; path = include/SentryArray.h; sourceTree = "<group>"; };
861265F82404EC1500C4AFDE /* SentryArray.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SentryArray.m; sourceTree = "<group>"; };
8E0551DF26A7A63C00400526 /* TestProtocolClient.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestProtocolClient.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2380,6 +2378,8 @@
F41362122E1C566100B84443 /* SentryScopePersistentStore+User.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SentryScopePersistentStore+User.swift"; sourceTree = "<group>"; };
F41362142E1C568400B84443 /* SentryScopePersistentStore+Context.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SentryScopePersistentStore+Context.swift"; sourceTree = "<group>"; };
F42674872EB11E7000E09150 /* SentryReplayApiTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SentryReplayApiTests.swift; sourceTree = "<group>"; };
F43F8CB62EFC1E970004C45D /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
F43F8CBD2EFC1EA00004C45D /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
F443DB262E09BE8C009A9045 /* LoadValidatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadValidatorTests.swift; sourceTree = "<group>"; };
F44858122E0357940013E63B /* SentryCrashDynamicLinker+Test.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SentryCrashDynamicLinker+Test.h"; sourceTree = "<group>"; };
F451FAA52E0B304E0050ACF2 /* LoadValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadValidator.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2520,9 +2520,9 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
84F994E82A6894BD00EC0190 /* SystemConfiguration.framework in Frameworks */,
F43F8CBC2EFC1E970004C45D /* SystemConfiguration.framework in Frameworks */,
F43F8CBE2EFC1EA00004C45D /* CoreData.framework in Frameworks */,
F4227F092EFB0D8C004A27DB /* libz.tbd in Frameworks */,
84F994E62A6894B500EC0190 /* CoreData.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -2815,9 +2815,9 @@
6304360C1EC05CEF00C4D3FA /* Frameworks */ = {
isa = PBXGroup;
children = (
F43F8CBD2EFC1EA00004C45D /* CoreData.framework */,
F43F8CB62EFC1E970004C45D /* SystemConfiguration.framework */,
D483AFA32E9D555300B43C27 /* XCTest.framework */,
84F994E72A6894BD00EC0190 /* SystemConfiguration.framework */,
84F994E52A6894B500EC0190 /* CoreData.framework */,
6387B82F1ED851970045A84C /* libz.tbd */,
);
name = Frameworks;
Expand Down
44 changes: 44 additions & 0 deletions Sources/SentrySwiftUI/Preview/PreviewRedactOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,44 @@ public class PreviewRedactOptions: SentryRedactOptions {
*/
public let unmaskedViewClasses: [AnyClass]

/**
* A set of view type identifier strings that should be excluded from subtree traversal.
*
* Views matching these types will have their subtrees skipped during redaction to avoid crashes
* caused by traversing problematic view hierarchies (e.g., views that activate internal CoreAnimation
* animations when their layers are accessed).
*
* Matching uses partial string containment: if a view's class name (from `type(of: view).description()`)
* contains any of these strings, the subtree will be ignored. For example, "MyView" will match
* "MyApp.MyView", "MyViewSubclass", "Some.MyView.Container", etc.
*
* - Note: See ``SentryReplayOptions.DefaultValues.excludedViewClasses`` for the default value.
* - Note: The final set of excluded view types is computed by `SentryUIRedactBuilder` using the formula:
* **Default View Classes + Excluded View Classes - Included View Classes**
* Default view classes are defined in `SentryUIRedactBuilder` (e.g., `CameraUI.ChromeSwiftUIView` on iOS 26+).
*/
public let excludedViewClasses: Set<String>

/**
* A set of view type identifier strings that should be included in subtree traversal.
*
* View types exactly matching these strings will be removed from the excluded set, allowing their subtrees
* to be traversed even if they would otherwise be excluded by default or via `excludedViewClasses`.
*
* Matching uses exact string matching: the view's class name (from `type(of: view).description()`)
* must exactly equal one of these strings. For example, "MyApp.MyView" will only match exactly "MyApp.MyView",
* not "MyApp.MyViewSubclass".
*
* - Note: See ``SentryReplayOptions.DefaultValues.includedViewClasses`` for the default value.
* - Note: The final set of excluded view types is computed by `SentryUIRedactBuilder` using the formula:
* **Default View Classes + Excluded View Classes - Included View Classes**
* Default view classes are defined in `SentryUIRedactBuilder` (e.g., `CameraUI.ChromeSwiftUIView` on iOS 26+).
* - Note: Included patterns use exact matching (not partial) to prevent accidental matches. For example,
* if "ChromeCameraUI" is excluded and "Camera" is included, "ChromeCameraUI" will still be excluded
* because "Camera" doesn't exactly match "ChromeCameraUI".
*/
public let includedViewClasses: Set<String>

/**
* Enables the up to 5x faster view renderer.
*
Expand All @@ -50,6 +88,8 @@ public class PreviewRedactOptions: SentryRedactOptions {
* - maskAllImages: Flag to redact all images in the app by drawing a rectangle over it.
* - maskedViewClasses: The classes of views to mask.
* - unmaskedViewClasses: The classes of views to exclude from masking.
* - excludedViewClasses: A set of view type identifiers that should be excluded from subtree traversal.
* - includedViewClasses: A set of view type identifiers that should be included in subtree traversal.
* - enableViewRendererV2: Enables the up to 5x faster view renderer.
*
* - Note: See ``SentryReplayOptions.DefaultValues`` for the default values of each parameter.
Expand All @@ -59,12 +99,16 @@ public class PreviewRedactOptions: SentryRedactOptions {
maskAllImages: Bool = SentryReplayOptions.DefaultValues.maskAllImages,
maskedViewClasses: [AnyClass] = SentryReplayOptions.DefaultValues.maskedViewClasses,
unmaskedViewClasses: [AnyClass] = SentryReplayOptions.DefaultValues.unmaskedViewClasses,
excludedViewClasses: Set<String> = SentryReplayOptions.DefaultValues.excludedViewClasses,
includedViewClasses: Set<String> = SentryReplayOptions.DefaultValues.includedViewClasses,
enableViewRendererV2: Bool = SentryReplayOptions.DefaultValues.enableViewRendererV2
) {
self.maskAllText = maskAllText
self.maskAllImages = maskAllImages
self.maskedViewClasses = maskedViewClasses
self.unmaskedViewClasses = unmaskedViewClasses
self.excludedViewClasses = excludedViewClasses
self.includedViewClasses = includedViewClasses
self.enableViewRendererV2 = enableViewRendererV2
}
}
Expand Down
39 changes: 39 additions & 0 deletions Sources/Swift/Core/Protocol/SentryRedactOptions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ public protocol SentryRedactOptions {
var maskAllImages: Bool { get }
var maskedViewClasses: [AnyClass] { get }
var unmaskedViewClasses: [AnyClass] { get }
var excludedViewClasses: Set<String> { get }
var includedViewClasses: Set<String> { get }
}

@objcMembers
Expand All @@ -14,4 +16,41 @@ public protocol SentryRedactOptions {
public var maskAllImages: Bool = true
public var maskedViewClasses: [AnyClass] = []
public var unmaskedViewClasses: [AnyClass] = []

/**
* A set of view type identifier strings that should be excluded from subtree traversal.
*
* Views matching these types will have their subtrees skipped during redaction to avoid crashes
* caused by traversing problematic view hierarchies (e.g., views that activate internal CoreAnimation
* animations when their layers are accessed).
*
* Matching uses partial string containment: if a view's class name (from `type(of: view).description()`)
* contains any of these strings, the subtree will be ignored. For example, "MyView" will match
* "MyApp.MyView", "MyViewSubclass", "Some.MyView.Container", etc.
*
* - Note: The final set of excluded view types is computed by `SentryUIRedactBuilder` using the formula:
* **Default View Classes + Excluded View Classes - Included View Classes**
* Default view classes are defined in `SentryUIRedactBuilder` (e.g., `CameraUI.ChromeSwiftUIView` on iOS 26+).
*/
public var excludedViewClasses: Set<String> = []

/**
* A set of view type identifier strings that should be included in subtree traversal.
*
* View types exactly matching these strings will be removed from the excluded set, allowing their subtrees
* to be traversed even if they would otherwise be excluded by default or via `excludedViewClasses`.
*
* Matching uses exact string matching: the view's class name (from `type(of: view).description()`)
* must exactly equal one of these strings. For example, "MyApp.MyView" will only match exactly "MyApp.MyView",
* not "MyApp.MyViewSubclass".
*
* - Note: The final set of excluded view types is computed by `SentryUIRedactBuilder` using the formula:
* **Default View Classes + Excluded View Classes - Included View Classes**
* Default view classes are defined in `SentryUIRedactBuilder` (e.g., `CameraUI.ChromeSwiftUIView` on iOS 26+).
* For example, you can use this to re-enable traversal for `CameraUI.ChromeSwiftUIView` on iOS 26+.
* - Note: Included patterns use exact matching (not partial) to prevent accidental matches. For example,
* if "ChromeCameraUI" is excluded and "Camera" is included, "ChromeCameraUI" will still be excluded
* because "Camera" doesn't exactly match "ChromeCameraUI".
*/
public var includedViewClasses: Set<String> = []
}
Loading
Loading