Skip to content
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

[SR] ANR with buffered Replay integration test #3612

Merged
merged 255 commits into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
255 commits
Select commit Hold shift + click to select a range
dd0e9a4
Api dump
romtsn Feb 13, 2024
d34ddee
Formatting
romtsn Feb 13, 2024
0cca47c
Lint
romtsn Feb 13, 2024
0a26e8d
Merge branch 'rz/feat/session-replay' into rz/feat/session-replay-sou…
romtsn Feb 13, 2024
5ebdfed
Format code
getsentry-bot Feb 13, 2024
04f43ed
More comments
romtsn Feb 13, 2024
b461847
Disable detekt plugin for now
romtsn Feb 13, 2024
f8419d1
Merge branch 'rz/feat/session-replay-sources' into rz/feat/session-re…
romtsn Feb 13, 2024
a63cac1
WIP
romtsn Feb 15, 2024
fa72057
Add replay envelopes
romtsn Feb 19, 2024
6cfb511
Remove jsonValue
romtsn Feb 19, 2024
0d031d7
Remove
romtsn Feb 19, 2024
07e6b26
Fix json
romtsn Feb 19, 2024
18af924
Finalize replay envelopes
romtsn Feb 20, 2024
64cedfa
Introduce MapObjectReader
romtsn Feb 20, 2024
b8cb924
Add missing test
romtsn Feb 20, 2024
28d341f
Merge branch 'rz/feat/session-replay-envelopes' into rz/feat/session-…
romtsn Feb 20, 2024
1e76fc7
Add test for MapObjectReader
romtsn Feb 22, 2024
13c1971
Add MapObjectWriter change
romtsn Feb 22, 2024
a14e090
Merge branch 'rz/feat/session-replay-envelopes' into rz/feat/session-…
romtsn Feb 22, 2024
86baf7f
Add finals
romtsn Feb 22, 2024
f1ca9f6
Fix test
romtsn Feb 22, 2024
fbbe0d9
Fix test
romtsn Feb 22, 2024
688233f
Merge branch 'rz/feat/session-replay-envelopes' into rz/feat/session-…
romtsn Feb 22, 2024
fd63960
Address review
romtsn Feb 28, 2024
93785cc
Add finals and annotations
romtsn Feb 28, 2024
4db19e0
Merge pull request #3215 from getsentry/rz/feat/session-replay-map-ob…
romtsn Feb 28, 2024
4e55ec0
Specify SHA for license headers
romtsn Feb 28, 2024
9603672
Address review from Dhiogo
romtsn Feb 28, 2024
1ce57cb
Address review from Markus
romtsn Mar 1, 2024
62477b4
Remove public captureReplay method
romtsn Mar 1, 2024
af42fb3
Fix test
romtsn Mar 1, 2024
1951891
api dump
romtsn Mar 1, 2024
cd09739
Merge branch 'rz/feat/session-replay-sources' into rz/feat/session-re…
romtsn Mar 1, 2024
4e54c77
api dump
romtsn Mar 1, 2024
b2940c4
Address review from Markus
romtsn Mar 4, 2024
002a0f3
Api dump
romtsn Mar 4, 2024
64f70c5
Merge pull request #3203 from getsentry/rz/feat/session-replay-sources
romtsn Mar 4, 2024
fb14ecb
Merge branch 'rz/feat/session-replay' into rz/feat/session-replay-env…
romtsn Mar 4, 2024
79151e9
Merge pull request #3214 from getsentry/rz/feat/session-replay-envelopes
romtsn Mar 4, 2024
9e87fe8
Add replay integration
romtsn Mar 19, 2024
2e954f7
Uncomment redacting
romtsn Mar 19, 2024
8bc6219
Update proguard rules
romtsn Mar 20, 2024
a5aa4be
Add missing rule for AndroidTest
romtsn Mar 20, 2024
f72e45f
Add ReplayCache tests
romtsn Mar 21, 2024
545712c
Add tests
romtsn Mar 21, 2024
2df34a3
Add SessionReplayOptions
romtsn Mar 25, 2024
c02f1db
Call listeners when installing RootViewsSpy
romtsn Mar 25, 2024
bee240b
Call listeners when installing RootViewsSpy
romtsn Mar 25, 2024
e2a821c
Merge branch 'rz/feat/session-replay-integration' into rz/feat/sessio…
romtsn Mar 25, 2024
d6bb9ab
SessionReplayOptions -> SentryReplayOptions
romtsn Mar 25, 2024
7854e4f
Fix test
romtsn Mar 26, 2024
2cddcc4
Add AndroidManifest options for replays
romtsn Mar 26, 2024
ef3d62c
Add buffer mode and link replays with events/transactions
romtsn Mar 28, 2024
f7ac74f
Pass hint to captureReplay
romtsn Mar 28, 2024
5faeb4e
Better error handling
romtsn Mar 28, 2024
65d35ec
recycler lastScreenshot before re-assigning
romtsn Mar 28, 2024
0f4e718
Expose ReplayCache as public api
romtsn Mar 28, 2024
fd6e633
Fix redacting out of sync
romtsn Mar 28, 2024
915bd29
Merge branch 'rz/feat/session-replay-integration' into rz/feat/sessio…
romtsn Mar 28, 2024
1a5c4da
_experimental -> experimental
romtsn Mar 28, 2024
fd92dc7
Merge branch 'rz/feat/session-replay-options' into rz/feat/session-re…
romtsn Mar 28, 2024
da37c89
Merge conflicts
romtsn Mar 28, 2024
c53a975
Fix tests
romtsn Apr 2, 2024
18eb67e
Add more tests
romtsn Apr 2, 2024
a7ae2b7
Improve ReplayCache logic
romtsn Apr 2, 2024
bf14d83
frameUsec -> frameDurationUsec
romtsn Apr 2, 2024
82fe21a
bottom/right -> height/width
romtsn Apr 2, 2024
de56e35
add todos
romtsn Apr 2, 2024
fa8c527
duration -> durationMs
romtsn Apr 2, 2024
dfbb992
replaId non-nullable
romtsn Apr 2, 2024
4ada96f
Merge branch 'rz/feat/session-replay-integration' into rz/feat/sessio…
romtsn Apr 2, 2024
c6a993f
Merge branch 'rz/feat/session-replay-options' into rz/feat/session-re…
romtsn Apr 2, 2024
ad7d78d
More conflicts
romtsn Apr 2, 2024
ab00547
More conflicts
romtsn Apr 2, 2024
7f78fee
Fix tests
romtsn Apr 2, 2024
9f252bc
Address PR review
romtsn Apr 3, 2024
27b15d7
Add kdoc
romtsn Apr 3, 2024
5278c86
Merge branch 'rz/feat/session-replay-integration' into rz/feat/sessio…
romtsn Apr 3, 2024
27674b1
Merge branch 'rz/feat/session-replay-options' into rz/feat/session-re…
romtsn Apr 3, 2024
957f0cf
Add kdoc
romtsn Apr 3, 2024
da3560d
Fix tests
romtsn Apr 3, 2024
b04aaf2
Merge pull request #3272 from getsentry/rz/feat/session-replay-integr…
romtsn Apr 3, 2024
023cb5f
Merge pull request #3283 from getsentry/rz/feat/session-replay-options
romtsn Apr 3, 2024
1a77d17
Add comment for experimental options
romtsn Apr 3, 2024
b88b1b9
Do not run recorder if full session was not sampled
romtsn Apr 3, 2024
4d533fb
Add more tests
romtsn Apr 3, 2024
4276264
Add session deadline of 1h
romtsn Apr 3, 2024
3fe5e0f
Clean up older replays when starting a new one
romtsn Apr 3, 2024
ca9f9d4
Remove unnecessary extension fun
romtsn Apr 3, 2024
7079d7a
[SR] Add buffer mode and link replays with events/transactions
romtsn Apr 4, 2024
ea417e4
Safe executors
romtsn Apr 4, 2024
f994ac9
Merge branch 'rz/feat/session-replay' into rz/feat/session-replay-cle…
romtsn Apr 4, 2024
0c5e4b0
Fix crashing MediaCodec and use density to determine recording resolu…
romtsn Apr 5, 2024
3e0894d
Add redact options and align naming
romtsn Apr 5, 2024
1fc9aa2
Fix tests
romtsn Apr 5, 2024
15e61dd
Merge branch 'rz/fix/session-replay-media-codec' into rz/feat/session…
romtsn Apr 5, 2024
ad98acd
Fix tests
romtsn Apr 5, 2024
5b8ed7c
Merge branch 'rz/fix/session-replay-media-codec' into rz/feat/session…
romtsn Apr 5, 2024
227c22a
WIP
romtsn Apr 5, 2024
0fca8ad
Try-catch release of encoder
romtsn Apr 5, 2024
5e37622
Support orientation change for session mode
romtsn Apr 8, 2024
d0b4d5c
WIP
romtsn Apr 8, 2024
f0fcf5d
Merge branch 'rz/fix/session-replay-media-codec' into rz/feat/session…
romtsn Apr 8, 2024
d7a7123
Merge branch 'rz/feat/session-replay-redact-options' into rz/feat/ses…
romtsn Apr 8, 2024
236ee2c
Spotless
romtsn Apr 8, 2024
e9bf0b3
TODO
romtsn Apr 8, 2024
bf8f49a
[SR] Cleanups and session deadline
romtsn Apr 9, 2024
71837c1
Update sentry/src/main/java/io/sentry/SentryReplayOptions.java
romtsn Apr 9, 2024
1430e7e
[SR] Fix crashing MediaCodec and use density to determine recording r…
romtsn Apr 9, 2024
a0c2678
[SR] Handle orientation change
romtsn Apr 9, 2024
3ef9f06
[SR] Add redact options and align naming
romtsn Apr 9, 2024
59b63e0
More gates
romtsn Apr 9, 2024
a9e3405
Merge branch 'rz/feat/session-replay' into rz/feat/session-replay-gates
romtsn Apr 9, 2024
21239ca
Revert addAll
romtsn Apr 9, 2024
b27a905
[SR] More gates
romtsn Apr 9, 2024
b83a894
Merge branch 'main' into rz/feat/session-replay
romtsn Apr 9, 2024
9cafe43
Fix conflicts
romtsn Apr 9, 2024
6c9baea
fix test
romtsn Apr 9, 2024
62a0984
Merge branch 'main' into rz/feat/session-replay
romtsn Apr 9, 2024
2057e22
release: 7.8.0-alpha.0
getsentry-bot Apr 9, 2024
7b24e7c
Merge branch 'release/7.8.0-alpha.0' into rz/feat/session-replay
Apr 9, 2024
5e33e95
Merge branch 'rz/feat/session-replay' into rz/feat/session-replay-cap…
romtsn Apr 9, 2024
f8f5698
Introduce CaptureStrategy for buffer and session modes
romtsn Apr 15, 2024
5c59bf7
Formatting
romtsn Apr 15, 2024
247f1c9
WIP
romtsn Apr 16, 2024
c2be16f
Expose public API for flutter
romtsn Apr 16, 2024
06d4b6d
Spotless
romtsn Apr 16, 2024
59056ef
Spotless
romtsn Apr 16, 2024
06495d8
Merge branch 'rz/feat/session-replay-breadcrumbs' into rz/feat/sessio…
romtsn Apr 16, 2024
0e951eb
Remove breadcrumb import
romtsn Apr 16, 2024
9686a74
Merge branch 'rz/feat/session-replay-breadcrumbs' into rz/feat/sessio…
romtsn Apr 16, 2024
e33b29c
Send temporary breadcrumbs and add test
romtsn Apr 18, 2024
27e17c1
Formatting
romtsn Apr 18, 2024
51cc432
Sort rrweb events
romtsn Apr 18, 2024
82680fb
Merge branch 'rz/feat/session-replay-breadcrumbs' into rz/feat/sessio…
romtsn Apr 18, 2024
4c7d1a0
Formatting
romtsn Apr 18, 2024
32fb5f0
Merge branch 'rz/feat/session-replay-breadcrumbs' into rz/feat/sessio…
romtsn Apr 18, 2024
c6b16ed
Expose replayCacheDir
romtsn Apr 18, 2024
6f3dc0a
Capture network requests
romtsn Apr 22, 2024
4c562fb
Change op name to resource.http
romtsn Apr 22, 2024
cd4fd9e
feat(replay): Add `sendReplay` method for Hybrid SDKs
krystofwoldrich Apr 23, 2024
e836f49
fix apiDump
krystofwoldrich Apr 23, 2024
4f240d4
Address PR review
romtsn Apr 23, 2024
12c0eb7
Merge pull request #3357 from getsentry/rz/feat/session-replay-captur…
romtsn Apr 25, 2024
db66737
[SR] Capture breadcrumbs (temporary)
romtsn Apr 25, 2024
33cd776
[SR] Expose public API for flutter
romtsn Apr 25, 2024
bdd9db5
[SR] Capture network requests
romtsn Apr 25, 2024
9295f0f
[SR] Add `sendReplay` method for Hybrid SDKs
romtsn Apr 25, 2024
f6b464b
Capture motion events as incremental rrweb events
romtsn Apr 25, 2024
2d508c9
Spotless
romtsn Apr 25, 2024
c0158eb
Merge branch 'rz/feat/session-replay' into rz/feat/session-replay-tou…
romtsn Apr 25, 2024
234b789
Revert
romtsn Apr 25, 2024
a68e88e
Merge branch 'main' into rz/feat/session-replay
romtsn Apr 26, 2024
b3ee659
Changelog
romtsn Apr 26, 2024
e89a3ef
release: 7.9.0-alpha.1
getsentry-bot Apr 26, 2024
2c0977b
Fix test
romtsn Apr 26, 2024
d4ac484
Merge branch 'release/7.9.0-alpha.1' into rz/feat/session-replay
Apr 26, 2024
5c05b6f
WIP
romtsn May 1, 2024
0476132
Adhere to rrweb move event expectations
romtsn May 2, 2024
7823d87
formatting
romtsn May 2, 2024
9596bb9
Align breadcrumbs with frontend and iOS
romtsn May 3, 2024
733b490
Add tests and fix deserialization
romtsn May 6, 2024
1217bb1
Rotate buffered motion events in buffer mode
romtsn May 6, 2024
647822c
Merge branch 'rz/feat/session-replay' into rz/feat/session-replay-tou…
romtsn May 6, 2024
6f83386
Merge branch 'rz/feat/session-replay-touch-events' into rz/feat/sessi…
romtsn May 6, 2024
69e5144
Add Nullables
romtsn May 29, 2024
a3d581c
Address PR feedback
romtsn May 29, 2024
d93e609
Formatting
romtsn May 29, 2024
0af0984
[SR] Capture gestures/motion events
romtsn May 29, 2024
5e119af
Merge branch 'rz/feat/session-replay' into rz/feat/session-replay-bre…
romtsn May 29, 2024
b9b78df
Rotate current events until segment end exclusively
romtsn May 29, 2024
50443a4
[SR] Align breadcrumbs with frontend (#3406)
romtsn May 29, 2024
f37c593
Allow rrweb breadcrumb customization from hybrid SDKs
romtsn May 30, 2024
730dc66
Fix proguard rules
romtsn Jun 3, 2024
69b23cc
WIP
romtsn Jun 3, 2024
c2dcad5
Add tests
romtsn Jun 3, 2024
d8fda33
Detect obscured views
romtsn Jun 7, 2024
26df8c6
revert some thigns
romtsn Jun 7, 2024
9c874d7
Remove commented code
romtsn Jun 7, 2024
db4ed1b
Merge branch 'rz/feat/session-replay-breadcrumbs-customizer' into rz/…
romtsn Jun 7, 2024
7b01de3
Suppress lint
romtsn Jun 10, 2024
aa2a5a9
Support multi-touch gestures
romtsn Jun 11, 2024
4aa50c2
Address PR feedback
romtsn Jun 18, 2024
11437d4
[SR] Allow RRWeb breadcrumb customization from hybrid SDKs
romtsn Jun 18, 2024
e3623e5
[SR] Redaction fixes part 1
romtsn Jun 18, 2024
5b412ae
Merge branch 'main' into rz/feat/session-replay
romtsn Jun 18, 2024
522b586
Changelog
romtsn Jun 18, 2024
263e147
release: 7.11.0-alpha.2
getsentry-bot Jun 18, 2024
a83b5d9
Merge branch 'release/7.11.0-alpha.2' into rz/feat/session-replay
Jun 18, 2024
9444da9
Make multi-touch work
romtsn Jun 18, 2024
54056cb
Fix tests
romtsn Jun 19, 2024
587b6d0
Merge branch 'rz/feat/session-replay' into rz/feat/session-replay-mul…
romtsn Jun 19, 2024
df7270e
WIP
romtsn Jun 20, 2024
53d5fbc
Capture screen names as urls for replay
romtsn Jun 21, 2024
a783326
Fix
romtsn Jun 21, 2024
01b7d67
Ignore warning
romtsn Jun 22, 2024
c832416
Address PR feedback
romtsn Jun 22, 2024
cfc52d9
[SR] Support multi-touch gestures
romtsn Jun 22, 2024
eef3c11
Tests
romtsn Jun 24, 2024
97d530c
Add quality settings
romtsn Jun 24, 2024
5557450
Fix redacting out of sync
romtsn Jun 24, 2024
213ff9e
Remove time measuring
romtsn Jul 2, 2024
fc7138b
Mark isEnableScreenTracking as experimental
romtsn Jul 2, 2024
d655d52
Format code
getsentry-bot Jul 2, 2024
a154cd0
Address PR feedback
romtsn Jul 2, 2024
2f727bc
[SR] Capture screen names as urls
romtsn Jul 2, 2024
17a4d22
[SR] Add quality settings
romtsn Jul 2, 2024
402587d
Clean up
romtsn Jul 2, 2024
71bdb5a
Spotless
romtsn Jul 2, 2024
a54f92f
[SR] Redaction fixes pt. 2
romtsn Jul 3, 2024
bc18c8b
feat(replay): Add `redactClasses` option
krystofwoldrich Jul 3, 2024
8f9a6d3
update api dump
krystofwoldrich Jul 3, 2024
da59406
Merge branch 'main' into rz/feat/session-replay
romtsn Jul 3, 2024
67efa10
Format code
getsentry-bot Jul 3, 2024
89f5186
Changelog
romtsn Jul 3, 2024
befe3fe
release: 7.12.0-alpha.3
getsentry-bot Jul 3, 2024
4866d54
Update CHANGELOG.md
krystofwoldrich Jul 3, 2024
615bb0e
Merge branch 'release/7.12.0-alpha.3' into rz/feat/session-replay
Jul 3, 2024
837e911
[SR] Add `redactClasses` option (#3546)
krystofwoldrich Jul 8, 2024
50c1d50
misc(changelog): Prepare for next alpha
krystofwoldrich Jul 9, 2024
361f73a
fix(changelog): Bump alpha version number
krystofwoldrich Jul 9, 2024
061ac4b
release: 7.12.0-alpha.4
getsentry-bot Jul 9, 2024
092f714
Merge branch 'release/7.12.0-alpha.4' into rz/feat/session-replay
Jul 9, 2024
c9b0804
Capture replay in session mode for ANRs
romtsn Jul 11, 2024
641a434
Tests
romtsn Jul 11, 2024
d5b213f
Merge branch 'rz/feat/session-replay' into rz/feat/session-replay-anrs
romtsn Jul 11, 2024
8cf2d1c
Api dump
romtsn Jul 11, 2024
ff1e3fe
Merge branch 'main' into rz/feat/session-replay-anrs
romtsn Jul 16, 2024
544bd00
Format code
getsentry-bot Jul 16, 2024
c0ebbed
Resolve merge conflicts
romtsn Jul 17, 2024
7fd180a
Fix tests
romtsn Jul 17, 2024
eced6ae
Format code
getsentry-bot Jul 17, 2024
09fb0e4
Add SessionCaptureStrategyTest
romtsn Jul 23, 2024
78b08b1
Infer duration from last frame for the unsent segment
romtsn Jul 24, 2024
d7dd9c4
Support replays for crashes in buffer and session modes
romtsn Jul 26, 2024
b303380
Fix breadcrumb http timestamps type
romtsn Jul 26, 2024
dffa4a9
Always do partial updates to the video
romtsn Jul 26, 2024
8d86dab
Make buffer mode work for ANRs
romtsn Jul 29, 2024
2267b1d
Add tests
romtsn Jul 29, 2024
4e4a437
Add buffer strategy test
romtsn Jul 29, 2024
c124e9a
Refactor robolectric tests to use custom ReplayShadowMediaCodec
romtsn Jul 30, 2024
e0277a9
Merge branch 'main' into rz/chore/session-replay-shadow-codec
romtsn Jul 31, 2024
e219190
Revert
romtsn Jul 31, 2024
35ef0c9
Add ANR with Replay integration test
romtsn Jul 31, 2024
2373011
Merge branch 'main' into rz/chore/session-replay-shadow-codec
romtsn Aug 1, 2024
ad817b6
Changelog
romtsn Aug 1, 2024
4b85e0d
Changelog and fix tests
romtsn Aug 1, 2024
1180635
Formatting
romtsn Aug 1, 2024
d076ab2
Merge branch 'main' into rz/chore/session-replay-shadow-codec
romtsn Aug 2, 2024
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
2 changes: 1 addition & 1 deletion .github/workflows/system-tests-backend.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:

- name: Exclude android modules from build
run: |
sed -i -e '/.*"sentry-android-ndk",/d' -e '/.*"sentry-android",/d' -e '/.*"sentry-compose",/d' -e '/.*"sentry-android-core",/d' -e '/.*"sentry-android-fragment",/d' -e '/.*"sentry-android-navigation",/d' -e '/.*"sentry-android-okhttp",/d' -e '/.*"sentry-android-sqlite",/d' -e '/.*"sentry-android-timber",/d' -e '/.*"sentry-android-integration-tests:sentry-uitest-android-benchmark",/d' -e '/.*"sentry-android-integration-tests:sentry-uitest-android",/d' -e '/.*"sentry-android-integration-tests:test-app-sentry",/d' -e '/.*"sentry-samples:sentry-samples-android",/d' settings.gradle.kts
sed -i -e '/.*"sentry-android-ndk",/d' -e '/.*"sentry-android",/d' -e '/.*"sentry-compose",/d' -e '/.*"sentry-android-core",/d' -e '/.*"sentry-android-fragment",/d' -e '/.*"sentry-android-navigation",/d' -e '/.*"sentry-android-okhttp",/d' -e '/.*"sentry-android-sqlite",/d' -e '/.*"sentry-android-timber",/d' -e '/.*"sentry-android-integration-tests:sentry-uitest-android-benchmark",/d' -e '/.*"sentry-android-integration-tests:sentry-uitest-android",/d' -e '/.*"sentry-android-integration-tests:test-app-sentry",/d' -e '/.*"sentry-samples:sentry-samples-android",/d' -e '/.*"sentry-android-replay",/d' settings.gradle.kts

- name: Exclude android modules from ignore list
run: |
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
- Avoid ArrayIndexOutOfBoundsException on Android cpu data collection ([#3598](https://github.com/getsentry/sentry-java/pull/3598))
- Fix lazy select queries instrumentation ([#3604](https://github.com/getsentry/sentry-java/pull/3604))

### Chores

- Introduce `ReplayShadowMediaCodec` and refactor tests using custom encoder ([#3612](https://github.com/getsentry/sentry-java/pull/3612))

## 7.13.0

### Features
Expand Down
1 change: 1 addition & 0 deletions sentry-android-replay/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ dependencies {

// tests
testImplementation(projects.sentryTestSupport)
testImplementation(projects.sentryAndroidCore)
testImplementation(Config.TestLibs.robolectric)
testImplementation(Config.TestLibs.kotlinTestJunit)
testImplementation(Config.TestLibs.androidxRunner)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,30 +36,12 @@ import java.util.concurrent.atomic.AtomicBoolean
* @param replayId the current replay id, used for giving a unique name to the replay folder
* @param recorderConfig ScreenshotRecorderConfig, used for video resolution and frame-rate
*/
public class ReplayCache internal constructor(
public class ReplayCache(
private val options: SentryOptions,
private val replayId: SentryId,
private val recorderConfig: ScreenshotRecorderConfig,
private val encoderProvider: (videoFile: File, height: Int, width: Int) -> SimpleVideoEncoder
private val recorderConfig: ScreenshotRecorderConfig
) : Closeable {

public constructor(
options: SentryOptions,
replayId: SentryId,
recorderConfig: ScreenshotRecorderConfig
) : this(options, replayId, recorderConfig, encoderProvider = { videoFile, height, width ->
SimpleVideoEncoder(
options,
MuxerConfig(
file = videoFile,
recordingHeight = height,
recordingWidth = width,
frameRate = recorderConfig.frameRate,
bitRate = recorderConfig.bitRate
)
).also { it.start() }
})

private val isClosed = AtomicBoolean(false)
private val encoderLock = Any()
private var encoder: SimpleVideoEncoder? = null
Expand Down Expand Up @@ -164,7 +146,18 @@ public class ReplayCache internal constructor(
}

// TODO: reuse instance of encoder and just change file path to create a different muxer
encoder = synchronized(encoderLock) { encoderProvider(videoFile, height, width) }
encoder = synchronized(encoderLock) {
SimpleVideoEncoder(
options,
MuxerConfig(
file = videoFile,
recordingHeight = height,
recordingWidth = width,
frameRate = recorderConfig.frameRate,
bitRate = recorderConfig.bitRate
)
).also { it.start() }
}

val step = 1000 / recorderConfig.frameRate.toLong()
var frameCount = 0
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
package io.sentry.android.replay

import android.app.ActivityManager
import android.app.ApplicationExitInfo
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Bitmap.CompressFormat.JPEG
import android.graphics.Bitmap.Config.ARGB_8888
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import io.sentry.EventProcessor
import io.sentry.Hint
import io.sentry.Sentry
import io.sentry.SentryOptions
import io.sentry.SentryReplayEvent
import io.sentry.SentryReplayEvent.ReplayType
import io.sentry.SystemOutLogger
import io.sentry.android.core.SentryAndroid
import io.sentry.android.core.performance.AppStartMetrics
import io.sentry.android.replay.ReplayCache.Companion.ONGOING_SEGMENT
import io.sentry.android.replay.ReplayCache.Companion.SEGMENT_KEY_BIT_RATE
import io.sentry.android.replay.ReplayCache.Companion.SEGMENT_KEY_FRAME_RATE
import io.sentry.android.replay.ReplayCache.Companion.SEGMENT_KEY_HEIGHT
import io.sentry.android.replay.ReplayCache.Companion.SEGMENT_KEY_ID
import io.sentry.android.replay.ReplayCache.Companion.SEGMENT_KEY_REPLAY_TYPE
import io.sentry.android.replay.ReplayCache.Companion.SEGMENT_KEY_TIMESTAMP
import io.sentry.android.replay.ReplayCache.Companion.SEGMENT_KEY_WIDTH
import io.sentry.android.replay.util.ReplayShadowMediaCodec
import io.sentry.cache.PersistingOptionsObserver.OPTIONS_CACHE
import io.sentry.cache.PersistingOptionsObserver.REPLAY_ERROR_SAMPLE_RATE_FILENAME
import io.sentry.protocol.Contexts
import io.sentry.protocol.SentryId
import io.sentry.rrweb.RRWebMetaEvent
import io.sentry.rrweb.RRWebVideoEvent
import org.awaitility.kotlin.await
import org.awaitility.kotlin.withAlias
import org.junit.Rule
import org.junit.rules.TemporaryFolder
import org.junit.runner.RunWith
import org.mockito.kotlin.spy
import org.mockito.kotlin.whenever
import org.robolectric.annotation.Config
import org.robolectric.shadow.api.Shadow
import org.robolectric.shadows.ShadowActivityManager
import org.robolectric.shadows.ShadowActivityManager.ApplicationExitInfoBuilder
import java.io.File
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.assertEquals

@RunWith(AndroidJUnit4::class)
@Config(
sdk = [30],
shadows = [ReplayShadowMediaCodec::class]
)
class AnrWithReplayIntegrationTest {

@get:Rule
val tmpDir = TemporaryFolder()

private class Fixture {
lateinit var shadowActivityManager: ShadowActivityManager

fun addAppExitInfo(
reason: Int? = ApplicationExitInfo.REASON_ANR,
timestamp: Long? = null,
importance: Int? = null
) {
val builder = ApplicationExitInfoBuilder.newBuilder()
if (reason != null) {
builder.setReason(reason)
}
if (timestamp != null) {
builder.setTimestamp(timestamp)
}
if (importance != null) {
builder.setImportance(importance)
}
val exitInfo = spy(builder.build()) {
whenever(mock.traceInputStream).thenReturn(
"""
"main" prio=5 tid=1 Blocked
| group="main" sCount=1 ucsCount=0 flags=1 obj=0x72a985e0 self=0xb400007cabc57380
| sysTid=28941 nice=-10 cgrp=top-app sched=0/0 handle=0x7deceb74f8
| state=S schedstat=( 324804784 183300334 997 ) utm=23 stm=8 core=3 HZ=100
| stack=0x7ff93a9000-0x7ff93ab000 stackSize=8188KB
| held mutexes=
at io.sentry.samples.android.MainActivity${'$'}2.run(MainActivity.java:177)
- waiting to lock <0x0d3a2f0a> (a java.lang.Object) held by thread 5
at android.os.Handler.handleCallback(Handler.java:942)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:201)
at android.os.Looper.loop(Looper.java:288)
at android.app.ActivityThread.main(ActivityThread.java:7872)
at java.lang.reflect.Method.invoke(Native method)
at com.android.internal.os.RuntimeInit${'$'}MethodAndArgsCaller.run(RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)

"perfetto_hprof_listener" prio=10 tid=7 Native (still starting up)
| group="" sCount=1 ucsCount=0 flags=1 obj=0x0 self=0xb400007cabc5ab20
| sysTid=28959 nice=-20 cgrp=top-app sched=0/0 handle=0x7b2021bcb0
| state=S schedstat=( 72750 1679167 1 ) utm=0 stm=0 core=3 HZ=100
| stack=0x7b20124000-0x7b20126000 stackSize=991KB
| held mutexes=
native: #00 pc 00000000000a20f4 /apex/com.android.runtime/lib64/bionic/libc.so (read+4) (BuildId: 01331f74b0bb2cb958bdc15282b8ec7b)
native: #01 pc 000000000001d840 /apex/com.android.art/lib64/libperfetto_hprof.so (void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, ArtPlugin_Initialize::${'$'}_34> >(void*)+260) (BuildId: 525cc92a7dc49130157aeb74f6870364)
native: #02 pc 00000000000b63b0 /apex/com.android.runtime/lib64/bionic/libc.so (__pthread_start(void*)+208) (BuildId: 01331f74b0bb2cb958bdc15282b8ec7b)
native: #03 pc 00000000000530b8 /apex/com.android.runtime/lib64/bionic/libc.so (__start_thread+64) (BuildId: 01331f74b0bb2cb958bdc15282b8ec7b)
(no managed stack frames)
""".trimIndent().byteInputStream()
)
}
shadowActivityManager.addApplicationExitInfo(exitInfo)
}

fun prefillOptionsCache(cacheDir: String) {
val optionsDir = File(cacheDir, OPTIONS_CACHE).also { it.mkdirs() }
File(optionsDir, REPLAY_ERROR_SAMPLE_RATE_FILENAME).writeText("\"1.0\"")
}
}

private val fixture = Fixture()
private lateinit var context: Context

@BeforeTest
fun `set up`() {
ReplayShadowMediaCodec.framesToEncode = 5
Sentry.close()
AppStartMetrics.getInstance().clear()
context = ApplicationProvider.getApplicationContext()
val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager?
fixture.shadowActivityManager = Shadow.extract(activityManager)
}

@Test
fun `replay is being captured for ANRs in buffer mode`() {
ReplayShadowMediaCodec.framesToEncode = 1

val cacheDir = tmpDir.newFolder().absolutePath
val oneDayAgo = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1)
fixture.addAppExitInfo(timestamp = oneDayAgo)
val asserted = AtomicBoolean(false)

val replayId1 = SentryId()
val replayId2 = SentryId()

SentryAndroid.init(context) {
it.dsn = "https://key@sentry.io/123"
it.cacheDirPath = cacheDir
it.isDebug = true
it.setLogger(SystemOutLogger())
it.experimental.sessionReplay.errorSampleRate = 1.0
// beforeSend is called after event processors are applied, so we can assert here
// against the enriched ANR event
it.beforeSend = SentryOptions.BeforeSendCallback { event, _ ->
assertEquals(replayId2.toString(), event.contexts[Contexts.REPLAY_ID])
event
}
it.addEventProcessor(object : EventProcessor {
override fun process(event: SentryReplayEvent, hint: Hint): SentryReplayEvent {
assertEquals(replayId2, event.replayId)
assertEquals(ReplayType.BUFFER, event.replayType)
assertEquals("0.mp4", event.videoFile?.name)

val metaEvents =
hint.replayRecording?.payload?.filterIsInstance<RRWebMetaEvent>()
assertEquals(912, metaEvents?.first()?.height)
assertEquals(416, metaEvents?.first()?.width) // clamped to power of 16

val videoEvents =
hint.replayRecording?.payload?.filterIsInstance<RRWebVideoEvent>()
assertEquals(912, videoEvents?.first()?.height)
assertEquals(416, videoEvents?.first()?.width) // clamped to power of 16
assertEquals(1000, videoEvents?.first()?.durationMs)
assertEquals(1, videoEvents?.first()?.frameCount)
assertEquals(1, videoEvents?.first()?.frameRate)
assertEquals(0, videoEvents?.first()?.segmentId)
asserted.set(true)
return event
}
})

// have to do it after the cacheDir is set to options, because it adds a dsn hash after
fixture.prefillOptionsCache(it.cacheDirPath!!)

val replayFolder1 = File(it.cacheDirPath!!, "replay_$replayId1").also { it.mkdirs() }
val replayFolder2 = File(it.cacheDirPath!!, "replay_$replayId2").also { it.mkdirs() }

File(replayFolder2, ONGOING_SEGMENT).also { file ->
file.writeText(
"""
$SEGMENT_KEY_HEIGHT=912
$SEGMENT_KEY_WIDTH=416
$SEGMENT_KEY_FRAME_RATE=1
$SEGMENT_KEY_BIT_RATE=75000
$SEGMENT_KEY_ID=0
$SEGMENT_KEY_TIMESTAMP=2024-07-11T10:25:21.454Z
$SEGMENT_KEY_REPLAY_TYPE=BUFFER
""".trimIndent()
)
}

val screenshot = File(replayFolder2, "1720693523997.jpg").also { it.createNewFile() }
screenshot.outputStream().use { os ->
Bitmap.createBitmap(1, 1, ARGB_8888).compress(JPEG, 80, os)
os.flush()
}

replayFolder1.setLastModified(oneDayAgo - 1000)
replayFolder2.setLastModified(oneDayAgo - 500)
}

await.withAlias("Failed because of BeforeSend callback above, but we swallow BeforeSend exceptions, hence the timeout")
.untilTrue(asserted)
}
}
Loading
Loading