From 54f75f4a68449695d3e0e5f63136fb92dfd0f344 Mon Sep 17 00:00:00 2001 From: Dhiogo Brustolin Date: Wed, 9 Oct 2024 09:22:31 +0200 Subject: [PATCH 1/7] fix: Improve SR masking performance --- Sources/Swift/Tools/SentryViewPhotographer.swift | 6 ++++++ Sources/Swift/Tools/UIRedactBuilder.swift | 6 +++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Sources/Swift/Tools/SentryViewPhotographer.swift b/Sources/Swift/Tools/SentryViewPhotographer.swift index 192585ff21..2e4705177c 100644 --- a/Sources/Swift/Tools/SentryViewPhotographer.swift +++ b/Sources/Swift/Tools/SentryViewPhotographer.swift @@ -45,6 +45,7 @@ class SentryViewPhotographer: NSObject, SentryViewScreenshotProvider { dispatchQueue.dispatchAsync { let screenshot = UIGraphicsImageRenderer(size: imageSize, format: .init(for: .init(displayScale: 1))).image { context in + let imageRect = CGRect(origin: .zero, size: imageSize) context.cgContext.addRect(CGRect(origin: CGPoint.zero, size: imageSize)) context.cgContext.clip(using: .evenOdd) UIColor.blue.setStroke() @@ -52,11 +53,16 @@ class SentryViewPhotographer: NSObject, SentryViewScreenshotProvider { context.cgContext.interpolationQuality = .none image.draw(at: .zero) + var latestRegion: RedactRegion? for region in redact { let rect = CGRect(origin: CGPoint.zero, size: region.size) var transform = region.transform let path = CGPath(rect: rect, transform: &transform) + defer { latestRegion = region } + + guard region != latestRegion && imageRect.contains(path.boundingBoxOfPath) else { continue } + switch region.type { case .redact: (region.color ?? UIImageHelper.averageColor(of: context.currentImage, at: rect.applying(region.transform))).setFill() diff --git a/Sources/Swift/Tools/UIRedactBuilder.swift b/Sources/Swift/Tools/UIRedactBuilder.swift index 01b99a3e29..f4771063ac 100644 --- a/Sources/Swift/Tools/UIRedactBuilder.swift +++ b/Sources/Swift/Tools/UIRedactBuilder.swift @@ -24,7 +24,7 @@ enum RedactRegionType { case clipEnd } -struct RedactRegion { +struct RedactRegion: Equatable { let size: CGSize let transform: CGAffineTransform let type: RedactRegionType @@ -36,6 +36,10 @@ struct RedactRegion { self.type = type self.color = color } + + static func == (lhs: RedactRegion, rhs: RedactRegion) -> Bool { + lhs.size == rhs.size && lhs.transform == rhs.transform && lhs.type == rhs.type + } } class UIRedactBuilder { From abf50f587d93d91c918fc6fb3c45ff2b593f221d Mon Sep 17 00:00:00 2001 From: Dhiogo Brustolin Date: Wed, 9 Oct 2024 15:09:38 +0200 Subject: [PATCH 2/7] Update SentryViewPhotographerTests.swift --- .../SentryTests/SentryViewPhotographerTests.swift | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Tests/SentryTests/SentryViewPhotographerTests.swift b/Tests/SentryTests/SentryViewPhotographerTests.swift index 3217e9dca7..69643f483d 100644 --- a/Tests/SentryTests/SentryViewPhotographerTests.swift +++ b/Tests/SentryTests/SentryViewPhotographerTests.swift @@ -180,6 +180,21 @@ class SentryViewPhotographerTests: XCTestCase { assertColor(pixel2, .white) } + func testSkipSameRegion() throws { + let label1 = UILabel(frame: CGRect(x: 0, y: 0, width: 50, height: 25)) + label1.text = "Test" + label1.textColor = .red + + let label2 = UILabel(frame: CGRect(x: 0, y: 0, width: 50, height: 25)) + label2.text = "Test" + label2.textColor = .green + + let image = try XCTUnwrap(prepare(views: [label1, label2])) + let pixel1 = color(at: CGPoint(x: 10, y: 10), in: image) + + assertColor(pixel1, .green) + } + private func assertColor(_ color1: UIColor, _ color2: UIColor) { let sRGBColor1 = color1.cgColor.converted(to: CGColorSpace(name: CGColorSpace.sRGB)!, intent: .defaultIntent, options: nil) let sRGBColor2 = color2.cgColor.converted(to: CGColorSpace(name: CGColorSpace.sRGB)!, intent: .defaultIntent, options: nil) From b11302be69d78477a50f5331a342901ecb2e13ad Mon Sep 17 00:00:00 2001 From: Dhiogo Brustolin Date: Wed, 9 Oct 2024 15:10:52 +0200 Subject: [PATCH 3/7] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a3e5f06ca..d27d7a1e7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ via the option `swizzleClassNameExclude`. ### Improvements - Serializing profile on a BG Thread (#4377) to avoid potentially slightly blocking the main thread. +- Session Replay performance for SwiftUI () ## 8.38.0-beta.1 From 8407dc7cdc9359a84e4a67d1e311ddd74454b44b Mon Sep 17 00:00:00 2001 From: Dhiogo Brustolin Date: Wed, 9 Oct 2024 15:12:11 +0200 Subject: [PATCH 4/7] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d27d7a1e7a..57019afa93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,7 @@ via the option `swizzleClassNameExclude`. ### Improvements - Serializing profile on a BG Thread (#4377) to avoid potentially slightly blocking the main thread. -- Session Replay performance for SwiftUI () +- Session Replay performance for SwiftUI (#4419) ## 8.38.0-beta.1 From ff1263715e106a467fe9243063e0a63b8cb7467f Mon Sep 17 00:00:00 2001 From: Dhiogo Brustolin Date: Wed, 9 Oct 2024 17:01:46 +0200 Subject: [PATCH 5/7] Update SentrySessionReplayIntegration.m --- Sources/Sentry/SentrySessionReplayIntegration.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Sentry/SentrySessionReplayIntegration.m b/Sources/Sentry/SentrySessionReplayIntegration.m index cd6df2e838..e2db6fc3c8 100644 --- a/Sources/Sentry/SentrySessionReplayIntegration.m +++ b/Sources/Sentry/SentrySessionReplayIntegration.m @@ -295,7 +295,7 @@ - (void)startWithOptions:(SentryReplayOptions *)replayOptions [self.sessionReplay startWithRootView:SentryDependencyContainer.sharedInstance.application.windows.firstObject - fullSession:[self shouldReplayFullSession:replayOptions.sessionSampleRate]]; + fullSession:shouldReplayFullSession]; [_notificationCenter addObserver:self selector:@selector(pause) From 9c3e2974cf69b006ae3901a688b7f1a313443f55 Mon Sep 17 00:00:00 2001 From: Dhiogo Brustolin Date: Thu, 10 Oct 2024 08:49:29 +0200 Subject: [PATCH 6/7] canReplace --- Sources/Swift/Tools/SentryViewPhotographer.swift | 2 +- Sources/Swift/Tools/UIRedactBuilder.swift | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Sources/Swift/Tools/SentryViewPhotographer.swift b/Sources/Swift/Tools/SentryViewPhotographer.swift index 4b93a4ab05..cf65b97a81 100644 --- a/Sources/Swift/Tools/SentryViewPhotographer.swift +++ b/Sources/Swift/Tools/SentryViewPhotographer.swift @@ -61,7 +61,7 @@ class SentryViewPhotographer: NSObject, SentryViewScreenshotProvider { defer { latestRegion = region } - guard region != latestRegion && imageRect.contains(path.boundingBoxOfPath) else { continue } + guard latestRegion?.canReplace(as: region) != true && imageRect.contains(path.boundingBoxOfPath) else { continue } switch region.type { case .redact, .redactSwiftUI: diff --git a/Sources/Swift/Tools/UIRedactBuilder.swift b/Sources/Swift/Tools/UIRedactBuilder.swift index c558680067..f0c8168f81 100644 --- a/Sources/Swift/Tools/UIRedactBuilder.swift +++ b/Sources/Swift/Tools/UIRedactBuilder.swift @@ -27,7 +27,7 @@ enum RedactRegionType { case redactSwiftUI } -struct RedactRegion: Equatable { +struct RedactRegion { let size: CGSize let transform: CGAffineTransform let type: RedactRegionType @@ -40,8 +40,8 @@ struct RedactRegion: Equatable { self.color = color } - static func == (lhs: RedactRegion, rhs: RedactRegion) -> Bool { - lhs.size == rhs.size && lhs.transform == rhs.transform && lhs.type == rhs.type + func canReplace(as other: RedactRegion) -> Bool { + size == other.size && transform == other.transform && type == other.type } } From 1ca9f1c7cdcd754a244e876df1cfee86db22e4df Mon Sep 17 00:00:00 2001 From: Dhiogo Brustolin Date: Thu, 10 Oct 2024 10:48:11 +0200 Subject: [PATCH 7/7] fix --- Sources/Swift/Tools/SentryViewPhotographer.swift | 2 +- Sources/Swift/Tools/UIRedactBuilder.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Swift/Tools/SentryViewPhotographer.swift b/Sources/Swift/Tools/SentryViewPhotographer.swift index cf65b97a81..d553e4ea17 100644 --- a/Sources/Swift/Tools/SentryViewPhotographer.swift +++ b/Sources/Swift/Tools/SentryViewPhotographer.swift @@ -61,7 +61,7 @@ class SentryViewPhotographer: NSObject, SentryViewScreenshotProvider { defer { latestRegion = region } - guard latestRegion?.canReplace(as: region) != true && imageRect.contains(path.boundingBoxOfPath) else { continue } + guard latestRegion?.canReplace(as: region) != true && imageRect.intersects(path.boundingBoxOfPath) else { continue } switch region.type { case .redact, .redactSwiftUI: diff --git a/Sources/Swift/Tools/UIRedactBuilder.swift b/Sources/Swift/Tools/UIRedactBuilder.swift index f0c8168f81..cd3f0f3442 100644 --- a/Sources/Swift/Tools/UIRedactBuilder.swift +++ b/Sources/Swift/Tools/UIRedactBuilder.swift @@ -174,7 +174,7 @@ class UIRedactBuilder { } //The swiftUI type needs to appear first in the list so it always get masked - return swiftUIRedact + otherRegions.reversed() + return (otherRegions + swiftUIRedact).reversed() } private func shouldIgnore(view: UIView) -> Bool {