From bc18c8b5c3883b63399346e268b53989620b807d Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Wed, 3 Jul 2024 14:07:47 +0200 Subject: [PATCH 1/4] feat(replay): Add `redactClasses` option --- CHANGELOG.md | 6 ++++++ .../replay/viewhierarchy/ViewHierarchyNode.kt | 2 +- .../java/io/sentry/SentryReplayOptions.java | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c8ee83a3d..905ff11743 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +### Features + +- Add `redactClasses` to Session Replay options ([#3546](https://github.com/getsentry/sentry-java/pull/3546)) + ## 7.11.0-alpha.2 - Session Replay for Android ([#3339](https://github.com/getsentry/sentry-java/pull/3339)) diff --git a/sentry-android-replay/src/main/java/io/sentry/android/replay/viewhierarchy/ViewHierarchyNode.kt b/sentry-android-replay/src/main/java/io/sentry/android/replay/viewhierarchy/ViewHierarchyNode.kt index 60014e8f64..888d489a1f 100644 --- a/sentry-android-replay/src/main/java/io/sentry/android/replay/viewhierarchy/ViewHierarchyNode.kt +++ b/sentry-android-replay/src/main/java/io/sentry/android/replay/viewhierarchy/ViewHierarchyNode.kt @@ -282,7 +282,7 @@ sealed class ViewHierarchyNode( (parent?.elevation ?: 0f) + view.elevation, distance = distance, parent = parent, - shouldRedact = false, + shouldRedact = options.experimental.sessionReplay.redactClasses.contains(view.javaClass.canonicalName), isImportantForContentCapture = false, /* will be set by children */ isVisible = isVisible, visibleRect = visibleRect diff --git a/sentry/src/main/java/io/sentry/SentryReplayOptions.java b/sentry/src/main/java/io/sentry/SentryReplayOptions.java index 54cabeaef6..da686b18c7 100644 --- a/sentry/src/main/java/io/sentry/SentryReplayOptions.java +++ b/sentry/src/main/java/io/sentry/SentryReplayOptions.java @@ -1,6 +1,8 @@ package io.sentry; import io.sentry.util.SampleRateUtils; +import java.util.HashSet; +import java.util.Set; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -64,6 +66,14 @@ public enum SentryReplayQuality { */ private boolean redactAllImages = true; + /** + * Redact all views with the specified class names. The class name is the fully qualified class + * name of the view, e.g. android.widget.TextView. + * + *

Default is empty. + */ + private Set redactClasses = new HashSet<>(); + /** * Defines the quality of the session replay. The higher the quality, the more accurate the replay * will be, but also more data to transfer and more CPU load, defaults to MEDIUM. @@ -147,6 +157,14 @@ public void setRedactAllImages(final boolean redactAllImages) { this.redactAllImages = redactAllImages; } + public Set getRedactClasses() { + return this.redactClasses; + } + + public void setRedactClasses(final Set redactClasses) { + this.redactClasses = redactClasses; + } + @ApiStatus.Internal public @NotNull SentryReplayQuality getQuality() { return quality; From 8f9a6d34ca8e7055fe6bb0a0e97e9754110af0e3 Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Wed, 3 Jul 2024 17:01:51 +0200 Subject: [PATCH 2/4] update api dump --- sentry/api/sentry.api | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sentry/api/sentry.api b/sentry/api/sentry.api index 6df0c9f3c1..48b1bfe622 100644 --- a/sentry/api/sentry.api +++ b/sentry/api/sentry.api @@ -2701,6 +2701,7 @@ public final class io/sentry/SentryReplayOptions { public fun getQuality ()Lio/sentry/SentryReplayOptions$SentryReplayQuality; public fun getRedactAllImages ()Z public fun getRedactAllText ()Z + public fun getRedactClasses ()Ljava/util/Set; public fun getSessionDuration ()J public fun getSessionSampleRate ()Ljava/lang/Double; public fun getSessionSegmentDuration ()J @@ -2710,6 +2711,7 @@ public final class io/sentry/SentryReplayOptions { public fun setQuality (Lio/sentry/SentryReplayOptions$SentryReplayQuality;)V public fun setRedactAllImages (Z)V public fun setRedactAllText (Z)V + public fun setRedactClasses (Ljava/util/Set;)V public fun setSessionSampleRate (Ljava/lang/Double;)V } From 4866d5400f1d20ae0cc678b40d816d3f25fad3ec Mon Sep 17 00:00:00 2001 From: Krystof Woldrich <31292499+krystofwoldrich@users.noreply.github.com> Date: Wed, 3 Jul 2024 19:58:31 +0200 Subject: [PATCH 3/4] Update CHANGELOG.md Co-authored-by: Roman Zavarnitsyn --- CHANGELOG.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 905ff11743..6c8ee83a3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,5 @@ # Changelog -## Unreleased - -### Features - -- Add `redactClasses` to Session Replay options ([#3546](https://github.com/getsentry/sentry-java/pull/3546)) - ## 7.11.0-alpha.2 - Session Replay for Android ([#3339](https://github.com/getsentry/sentry-java/pull/3339)) From 742e81b1aad4a8f1162976ed007e3bb59b6e4c69 Mon Sep 17 00:00:00 2001 From: Krystof Woldrich Date: Thu, 4 Jul 2024 16:44:43 +0200 Subject: [PATCH 4/4] fix review comments --- .../android/replay/viewhierarchy/ViewHierarchyNode.kt | 6 +++++- sentry/api/sentry.api | 2 +- sentry/src/main/java/io/sentry/SentryReplayOptions.java | 8 ++++---- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/sentry-android-replay/src/main/java/io/sentry/android/replay/viewhierarchy/ViewHierarchyNode.kt b/sentry-android-replay/src/main/java/io/sentry/android/replay/viewhierarchy/ViewHierarchyNode.kt index 888d489a1f..1a94b295f7 100644 --- a/sentry-android-replay/src/main/java/io/sentry/android/replay/viewhierarchy/ViewHierarchyNode.kt +++ b/sentry-android-replay/src/main/java/io/sentry/android/replay/viewhierarchy/ViewHierarchyNode.kt @@ -232,6 +232,10 @@ sealed class ViewHierarchyNode( } } + private fun shouldRedact(view: View, options: SentryOptions): Boolean { + return options.experimental.sessionReplay.redactClasses.contains(view.javaClass.canonicalName) + } + fun fromView(view: View, parent: ViewHierarchyNode?, distance: Int, options: SentryOptions): ViewHierarchyNode { val (isVisible, visibleRect) = view.isVisibleToUser() when { @@ -282,7 +286,7 @@ sealed class ViewHierarchyNode( (parent?.elevation ?: 0f) + view.elevation, distance = distance, parent = parent, - shouldRedact = options.experimental.sessionReplay.redactClasses.contains(view.javaClass.canonicalName), + shouldRedact = isVisible && shouldRedact(view, options), isImportantForContentCapture = false, /* will be set by children */ isVisible = isVisible, visibleRect = visibleRect diff --git a/sentry/api/sentry.api b/sentry/api/sentry.api index 48b1bfe622..5007d28a68 100644 --- a/sentry/api/sentry.api +++ b/sentry/api/sentry.api @@ -2695,6 +2695,7 @@ public final class io/sentry/SentryReplayEvent$ReplayType$Deserializer : io/sent public final class io/sentry/SentryReplayOptions { public fun ()V public fun (Ljava/lang/Double;Ljava/lang/Double;)V + public fun addClassToRedact (Ljava/lang/String;)V public fun getErrorReplayDuration ()J public fun getErrorSampleRate ()Ljava/lang/Double; public fun getFrameRate ()I @@ -2711,7 +2712,6 @@ public final class io/sentry/SentryReplayOptions { public fun setQuality (Lio/sentry/SentryReplayOptions$SentryReplayQuality;)V public fun setRedactAllImages (Z)V public fun setRedactAllText (Z)V - public fun setRedactClasses (Ljava/util/Set;)V public fun setSessionSampleRate (Ljava/lang/Double;)V } diff --git a/sentry/src/main/java/io/sentry/SentryReplayOptions.java b/sentry/src/main/java/io/sentry/SentryReplayOptions.java index da686b18c7..db230f2a30 100644 --- a/sentry/src/main/java/io/sentry/SentryReplayOptions.java +++ b/sentry/src/main/java/io/sentry/SentryReplayOptions.java @@ -1,8 +1,8 @@ package io.sentry; import io.sentry.util.SampleRateUtils; -import java.util.HashSet; import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -72,7 +72,7 @@ public enum SentryReplayQuality { * *

Default is empty. */ - private Set redactClasses = new HashSet<>(); + private Set redactClasses = new CopyOnWriteArraySet<>(); /** * Defines the quality of the session replay. The higher the quality, the more accurate the replay @@ -161,8 +161,8 @@ public Set getRedactClasses() { return this.redactClasses; } - public void setRedactClasses(final Set redactClasses) { - this.redactClasses = redactClasses; + public void addClassToRedact(final String className) { + this.redactClasses.add(className); } @ApiStatus.Internal