Skip to content
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ class ReplayTest : BaseUiTest() {
// we can't run on GH actions emulator, because they don't allow capturing screenshots properly
@Suppress("KotlinConstantConditions")
assumeThat(BuildConfig.ENVIRONMENT != "github", `is`(true))
// crash on swallowed Compose masking errors (e.g. broken obfuscated internals) so regressions
// fail this on-device test instead of silently under-masking (see SentryReplayDebug)
System.setProperty("io.sentry.replay.compose.fail-fast", "true")
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ class ReplaySnapshotTest : BaseUiTest() {
// GH Actions emulators don't support capturing screenshots for replay
@Suppress("KotlinConstantConditions")
assumeThat(BuildConfig.ENVIRONMENT != "github", `is`(true))
// crash on swallowed Compose masking errors (e.g. broken obfuscated internals) so regressions
// fail this on-device test instead of silently under-masking (see SentryReplayDebug)
System.setProperty("io.sentry.replay.compose.fail-fast", "true")
}

@Test
Expand Down
6 changes: 6 additions & 0 deletions sentry-android-replay/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,9 @@
# Rules to detect a PreviewView view to later mask it
-dontwarn androidx.camera.view.PreviewView
-keepnames class androidx.camera.view.PreviewView
# Rules to walk the Compose Node tree.
-keep class androidx.compose.ui.node.LayoutNode {
*** getChildren*(...);
*** getOuterCoordinator*(...);
*** getCollapsedSemantics*(...);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package io.sentry.android.replay.util

/**
* Internal, undocumented escape hatch used to make Session Replay fail fast instead of silently
* degrading masking when an exception is swallowed (e.g. unsupported/obfuscated Compose internals).
*
* It is intended to be enabled only in our own sample/UI-test apps that run on real devices in CI
* (which are release/obfuscated builds, so [io.sentry.android.replay.BuildConfig.DEBUG] can't be
* used), so that regressions surface as crashes rather than under-masked replays. Customers should
* never set this.
*
* Enable via:
* ```
* System.setProperty("io.sentry.replay.compose.fail-fast", "true")
* ```
*/
internal object SentryReplayDebug {
private const val FAIL_FAST_PROPERTY = "io.sentry.replay.compose.fail-fast"

/**
* Read live (not cached) so it's only evaluated on the error path and unit tests can toggle it
* between cases.
*/
val failFast: Boolean
get() = "true".equals(System.getProperty(FAIL_FAST_PROPERTY), ignoreCase = true)
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import io.sentry.SentryLevel
import io.sentry.SentryMaskingOptions
import io.sentry.android.replay.SentryReplayModifiers
import io.sentry.android.replay.util.ComposeTextLayout
import io.sentry.android.replay.util.SentryReplayDebug
import io.sentry.android.replay.util.boundsInWindow
import io.sentry.android.replay.util.findPainter
import io.sentry.android.replay.util.findTextColor
Expand Down Expand Up @@ -147,6 +148,12 @@ internal object ComposeViewHierarchyNode {
)
}

// fail fast in our own sample/UI-test apps (see SentryReplayDebug), so regressions surface
// as crashes instead of silently degrading masking
if (SentryReplayDebug.failFast) {
throw t
}

// If we're unable to retrieve the semantics configuration
// we should play safe and mask the whole node.
return GenericViewHierarchyNode(
Expand Down Expand Up @@ -291,6 +298,11 @@ internal object ComposeViewHierarchyNode {
"""
.trimIndent(),
)
// fail fast in our own sample/UI-test apps (see SentryReplayDebug), so regressions surface
// as crashes instead of silently skipping the whole Compose subtree (i.e. not masking it)
if (SentryReplayDebug.failFast) {
throw e
}
return false
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ public class MyApplication extends Application {

@Override
public void onCreate() {
// Make Session Replay fail fast instead of silently degrading masking when an exception is
// swallowed (e.g. unsupported/obfuscated Compose internals). This way regressions surface as
// crashes in our release/obfuscated builds that run on real devices in CI. Only meant for our
// own sample/UI-test apps, customers should never set this.
System.setProperty("io.sentry.replay.compose.fail-fast", "true");
Sentry.startProfiler();
strictMode();
super.onCreate();
Expand Down
Loading