-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
feat(android): Add custom masking options for session replay #11624
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
romtsn
merged 27 commits into
master
from
rz/chore/session-replay-custom-redaction-android
Oct 23, 2024
Merged
Changes from 6 commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
649b485
feat(android): Add custom masking options for session replay
romtsn 877f5d4
feat(android): Add custom masking options for session replay
romtsn 5f73956
Add missing imports
romtsn 82d92b7
Rearrange folders
romtsn 0a7bab9
Add required version
romtsn fca534d
Add masking example images
romtsn db409c4
Update docs/platforms/android/session-replay/index.mdx
romtsn 9126d2a
Update docs/platforms/android/session-replay/index.mdx
romtsn 2095c52
Update docs/platforms/android/session-replay/index.mdx
romtsn 69797d3
Update docs/platforms/android/session-replay/privacy/index.mdx
romtsn da7f3ea
Update docs/platforms/android/session-replay/privacy/index.mdx
romtsn 830fb64
Update docs/platforms/android/session-replay/privacy/index.mdx
romtsn c5e7929
Update docs/platforms/android/session-replay/privacy/index.mdx
romtsn 5acb078
Update docs/platforms/android/session-replay/privacy/index.mdx
romtsn 80788c4
Fix formatting
romtsn 887136a
Fix and add masking behavior section
romtsn ed730bc
Add missing images
romtsn 73c4161
Update docs/platforms/android/session-replay/privacy/index.mdx
romtsn e5c7f5e
Update docs/platforms/android/session-replay/privacy/index.mdx
romtsn 7a304db
Update docs/platforms/android/session-replay/privacy/index.mdx
romtsn 0a751a9
Update docs/platforms/android/session-replay/privacy/index.mdx
romtsn 57bca3a
Update docs/platforms/android/session-replay/privacy/index.mdx
romtsn 10c599e
Update docs/platforms/android/session-replay/privacy/index.mdx
romtsn 45bf9c8
Update docs/platforms/android/session-replay/privacy/index.mdx
romtsn 3ddf363
Update docs/platforms/android/session-replay/privacy/index.mdx
romtsn 0ba684d
Update docs/platforms/android/session-replay/privacy/index.mdx
romtsn 81008d5
Add old way of disabling redaction
romtsn File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -94,20 +94,20 @@ Sampling begins as soon as a session starts. `sessionSampleRate` is evaluated fi | |
|
|
||
| ## Privacy | ||
|
|
||
| The SDK is recording and aggressively redacting all text and images. We plan to add fine controls for redacting, but in this version, we just allow either on or off. The default is on. Please don’t turn it off if you have sensitive data in your app. Before the Beta is complete, we'll give you the controls you need. | ||
| The SDK is recording and aggressively masking all text, images and webviews. Please don’t turn it off if you have sensitive data in your app. | ||
| However, if you're working on a mobile app that's free of PII or other types of private data, you can opt out of the default text and image masking settings. To learn more about Session Replay privacy, [read our docs](/platforms/android/session-replay/privacy/). | ||
|
|
||
| <Note> | ||
|
|
||
| Jetpack Compose views are not yet redacted. This is being [tracked here](https://github.com/getsentry/sentry-java/issues/3577). | ||
| If you encounter any other data not being redacted with the default settings, please let us know through a [GitHub issue](https://github.com/getsentry/sentry-java/issues/new?assignees=&labels=Platform%3A+Android%2CType%3A+Bug&projects=&template=bug_report_android.yml). | ||
| If you encounter any other data not being masked with the default settings, please let us know through a [GitHub issue](https://github.com/getsentry/sentry-java/issues/new?assignees=&labels=Platform%3A+Android%2CType%3A+Bug&projects=&template=bug_report_android.yml). | ||
|
|
||
| </Note> | ||
|
|
||
| To disable redaction altogether (not to be used on applications with sensitive data): | ||
| To disable masking altogether (not to be used on applications with sensitive data): | ||
|
|
||
| ```kotlin | ||
| options.experimental.sessionReplay.redactAllText = false | ||
| options.experimental.sessionReplay.redactAllImages = false | ||
| options.experimental.sessionReplay.maskAllText = false | ||
romtsn marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| options.experimental.sessionReplay.maskAllImages = false | ||
| ``` | ||
romtsn marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| ## Error Linking | ||
|
|
@@ -120,8 +120,12 @@ Errors that happen on the page while a replay is running will be linked to the r | |
|
|
||
| ## FAQ | ||
|
|
||
| Q: Why are parts of my replay not masked? | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you for adding this. We should have this on iOS, React Native and Flutter too! |
||
| A: Text fields, input fields, images, video players and webviews are all masked by default. Local assets, such as colors or vector drawables, are not masked due to their low likelihood of containing PII. If you encounter a view/component that should be masked by default, consider opening a [GitHub issue](https://github.com/getsentry/sentry-java/issues). | ||
|
|
||
romtsn marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| Q: Does Session Replay work with Jetpack Compose? | ||
| A: Yes, but we're still adding support for redaction for Jetpack Compose views. Redaction will be added during the Beta program and after GA these views will be masked by default. | ||
| A: Yes, by default text, input field and image composables should be masked. Masking within embedded android views (`AndroidView`) | ||
| in Compose is currently not supported. If you encounter composables that are not masked but should be, consider opening a [GitHub issue](https://github.com/getsentry/sentry-java/issues). | ||
romtsn marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| Q: What's the lowest version of Android supported? | ||
| A: Recording only happens on Android 8 (API level 26) or newer. For devices running an older version, SDK features other than recording work normally. | ||
130 changes: 130 additions & 0 deletions
130
docs/platforms/android/session-replay/privacy/index.mdx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,130 @@ | ||
| --- | ||
| title: Privacy | ||
| sidebar_order: 5501 | ||
| notSupported: | ||
| description: "Learn how to mask parts of your app's data in Session Replay." | ||
| --- | ||
|
|
||
| <Alert> | ||
|
|
||
| Before publising an App with Session Replay enabled, make sure to test it thoroughly to ensure that no sensitive data is exposed. | ||
|
|
||
| If you choose to use custom masking in your Session Replays, you may accidentally expose sensitive customer data. Be sure to double-check what you choose to expose. | ||
romtsn marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| </Alert> | ||
|
|
||
| By default, our Session Replay SDK masks all text content, images, webviews and user input. This helps ensure that no sensitive data will be exposed. You can also manually choose which parts of your app's data you want to mask by using the different options listed below. | ||
|
|
||
romtsn marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| To disable the default masking behavior (not to be used on applications with sensitive data): | ||
|
|
||
| ```kotlin | ||
| options.experimental.sessionReplay.maskAllText = false | ||
| options.experimental.sessionReplay.maskAllImages = false | ||
| ``` | ||
|
|
||
|   | ||
|
|
||
| _Make sure your Sentry Android SDK version is at least 7.15.0._ | ||
|
|
||
| ## Mask by View Class | ||
|
|
||
| You can choose which type of view you want to mask or unmask by using the `addMaskViewClass` or `addUnmaskViewClass` options. | ||
|
|
||
| Let's say you have: | ||
| - A custom view that you want to mask | ||
| - A `TextView` subclass (which normally would be masked) that you don't want to mask. | ||
romtsn marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| You can set the options like this: | ||
|
|
||
| ```kotlin | ||
| options.experimental.sessionReplay.addMaskViewClass("com.example.MyCustomView") | ||
| options.experimental.sessionReplay.addUnmaskViewClass("com.example.MyCustomTextView") | ||
| ``` | ||
|
|
||
| <Note> | ||
|
|
||
| If you're using a code obfuscation tool (R8/ProGuard), adjust your proguard rules accordingly so your custom view class names are not minified. | ||
romtsn marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| </Note> | ||
|
|
||
| ### Class Hierarchy | ||
|
|
||
| The masking behavior applies to classes and their subclasses. This means if you add a view via `addMaskViewClass` (for example, `TextView`, which is the default behavior), its respective subclasses (`RadioButton`, `CheckBox`, `EditText`, etc.) will also be masked. For example, you can do the following: | ||
romtsn marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ```kotlin | ||
| options.experimental.sessionReplay.addMaskViewClass("android.widget.TextView") // mask TextView and all its subclasses | ||
| options.experimental.sessionReplay.addUnmaskViewClass("android.widget.RadioButton") // but unmask RadioButton and all its subclasses | ||
| ``` | ||
|
|
||
| ## Mask by View Instance | ||
|
|
||
| You can also choose to mask or unmask a specific view instance by using tags like this: | ||
|
|
||
| ```xml | ||
| <View | ||
| android:id="@+id/my_view" | ||
| android:layout_width="wrap_content" | ||
| android:layout_height="wrap_content" | ||
| android:tag="sentry-mask|sentry-unmask"/> | ||
| ``` | ||
|
|
||
| ```kotlin | ||
| view.tag = "sentry-mask|sentry-unmask" | ||
| ``` | ||
|
|
||
| If your view already has a tag assigned, you can set the masking tag by a sentry-specific id: | ||
|
|
||
| ```xml | ||
| <View | ||
| android:id="@+id/my_view" | ||
| android:layout_width="wrap_content" | ||
| android:layout_height="wrap_content"> | ||
| <tag android:id="@id/sentry_privacy" android:value="mask|unmask"/> | ||
| </View> | ||
| ``` | ||
|
|
||
| ```kotlin | ||
| view.setTag(io.sentry.android.replay.R.id.sentry_privacy, "mask|unmask") | ||
| ``` | ||
|
|
||
| We also provide convenient extension functions for Kotlin: | ||
|
|
||
| ```kotlin | ||
| view.sentryReplayMask() | ||
| // or | ||
| view.sentryReplayUnmask() | ||
| ``` | ||
|
|
||
| ## Jetpack Compose | ||
|
|
||
| We only support masking specific composables in Jetpack Compose. Since composables don't have a concept of classes (they are all composable functions), masking by view class is not supported. | ||
|
|
||
| In this example, we want the "Hello" message to be captured in the replay (by default, all text composables are masked), but not the custom composable: | ||
romtsn marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ```kotlin | ||
| import io.sentry.android.replay.sentryReplayMask | ||
| import io.sentry.android.replay.sentryReplayUnmask | ||
|
|
||
| Column( | ||
| verticalArrangement = Arrangement.Center, | ||
| horizontalAlignment = Alignment.CenterHorizontally, | ||
| modifier = Modifier.fillMaxSize() | ||
| ) { | ||
| MyCustomComposable( | ||
| modifier = Modifier.fillMaxWidth().sentryReplayMask() | ||
| ... | ||
| ) | ||
| Text("Hello", modifier = Modifier.sentryReplayUnmask()) | ||
| } | ||
| ``` | ||
|
|
||
| Currently, we don't support masking anything within embedded android views (`AndroidView`), but you can still mask the entire view as follows: | ||
romtsn marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| ```kotlin | ||
| import io.sentry.android.replay.sentryReplayMask | ||
|
|
||
| AndroidView( | ||
| modifier = Modifier.sentryReplayMask(), | ||
| factory = { context -> ... } | ||
| ) | ||
| ``` | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.