Skip to content

Commit 935fb7f

Browse files
authored
Merge 896d1f9 into 334f7a8
2 parents 334f7a8 + 896d1f9 commit 935fb7f

File tree

4 files changed

+61
-3
lines changed

4 files changed

+61
-3
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121

2222
### Fixes
2323

24-
- Fix `NoSuchElementException` in `BufferCaptureStrategy` ([#4717](https://github.com/getsentry/sentry-java/pull/4717))
24+
- Session Replay: Fix `NoSuchElementException` in `BufferCaptureStrategy` ([#4717](https://github.com/getsentry/sentry-java/pull/4717))
25+
- Session Replay: Fix continue recording in Session mode after Buffer is triggered ([#4719](https://github.com/getsentry/sentry-java/pull/4719))
2526

2627
## 8.21.1
2728

sentry-android-replay/src/main/java/io/sentry/android/replay/capture/BaseCaptureStrategy.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ internal abstract class BaseCaptureStrategy(
6060

6161
protected val isTerminating = AtomicBoolean(false)
6262
protected var cache: ReplayCache? = null
63-
protected var recorderConfig: ScreenshotRecorderConfig? by
63+
internal var recorderConfig: ScreenshotRecorderConfig? by
6464
persistableAtomicNullable(propertyName = "") { _, _, newValue ->
6565
if (newValue == null) {
6666
// recorderConfig is only nullable on init, but never after

sentry-android-replay/src/main/java/io/sentry/android/replay/capture/BufferCaptureStrategy.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ internal class BufferCaptureStrategy(
146146
}
147147
// we hand over replayExecutor to the new strategy to preserve order of execution
148148
val captureStrategy = SessionCaptureStrategy(options, scopes, dateProvider, replayExecutor)
149+
captureStrategy.recorderConfig = recorderConfig
149150
captureStrategy.start(
150151
segmentId = currentSegment,
151152
replayId = currentReplayId,

sentry-android-replay/src/test/java/io/sentry/android/replay/ReplayIntegrationTest.kt

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,12 @@ import io.sentry.android.replay.ReplayCache.Companion.SEGMENT_KEY_REPLAY_RECORDI
2727
import io.sentry.android.replay.ReplayCache.Companion.SEGMENT_KEY_REPLAY_TYPE
2828
import io.sentry.android.replay.ReplayCache.Companion.SEGMENT_KEY_TIMESTAMP
2929
import io.sentry.android.replay.ReplayCache.Companion.SEGMENT_KEY_WIDTH
30+
import io.sentry.android.replay.capture.BufferCaptureStrategy
3031
import io.sentry.android.replay.capture.CaptureStrategy
3132
import io.sentry.android.replay.capture.SessionCaptureStrategy
3233
import io.sentry.android.replay.capture.SessionCaptureStrategyTest.Fixture.Companion.VIDEO_DURATION
3334
import io.sentry.android.replay.gestures.GestureRecorder
35+
import io.sentry.android.replay.util.ReplayShadowMediaCodec
3436
import io.sentry.cache.PersistingScopeObserver
3537
import io.sentry.cache.tape.QueueFile
3638
import io.sentry.protocol.SentryException
@@ -43,6 +45,7 @@ import io.sentry.rrweb.RRWebVideoEvent
4345
import io.sentry.transport.CurrentDateProvider
4446
import io.sentry.transport.ICurrentDateProvider
4547
import io.sentry.transport.RateLimiter
48+
import io.sentry.util.Random
4649
import java.io.ByteArrayOutputStream
4750
import java.io.File
4851
import kotlin.test.BeforeTest
@@ -63,13 +66,14 @@ import org.mockito.kotlin.doAnswer
6366
import org.mockito.kotlin.eq
6467
import org.mockito.kotlin.mock
6568
import org.mockito.kotlin.never
69+
import org.mockito.kotlin.reset
6670
import org.mockito.kotlin.times
6771
import org.mockito.kotlin.verify
6872
import org.mockito.kotlin.whenever
6973
import org.robolectric.annotation.Config
7074

7175
@RunWith(AndroidJUnit4::class)
72-
@Config(sdk = [26])
76+
@Config(sdk = [26], shadows = [ReplayShadowMediaCodec::class])
7377
class ReplayIntegrationTest {
7478
@get:Rule val tmpDir = TemporaryFolder()
7579

@@ -726,6 +730,58 @@ class ReplayIntegrationTest {
726730
verify(recorder).resume()
727731
}
728732

733+
@Test
734+
fun `continues recording after converting to session strategy without extra config change`() {
735+
// Force buffer mode at start, but enable onError sample so captureReplay triggers
736+
val recorder = mock<Recorder>()
737+
val replay =
738+
fixture.getSut(
739+
context,
740+
recorderProvider = { recorder },
741+
replayCaptureStrategyProvider = { isFullSession ->
742+
// Always start with buffer strategy regardless of sampling
743+
BufferCaptureStrategy(
744+
fixture.options,
745+
fixture.scopes,
746+
// make time jump so session strategy will immediately cut a segment on next frame
747+
ICurrentDateProvider {
748+
System.currentTimeMillis() + fixture.options.sessionReplay.sessionSegmentDuration
749+
},
750+
Random(),
751+
// run tasks synchronously in tests
752+
mock {
753+
doAnswer { (it.arguments[0] as Runnable).run() }
754+
.whenever(mock)
755+
.submit(any<Runnable>())
756+
},
757+
) { _ ->
758+
fixture.replayCache
759+
}
760+
},
761+
)
762+
763+
fixture.options.sessionReplay.sessionSampleRate = 0.0 // ensure buffer mode initially
764+
fixture.options.sessionReplay.onErrorSampleRate = 1.0
765+
fixture.options.cacheDirPath = tmpDir.newFolder().absolutePath
766+
767+
replay.register(fixture.scopes, fixture.options)
768+
replay.start()
769+
770+
val config = ScreenshotRecorderConfig(100, 200, 1f, 1f, 1, 20_000)
771+
replay.onConfigurationChanged(config)
772+
773+
// Trigger convert() via captureReplay
774+
replay.captureReplay(false)
775+
776+
// Now, without invoking another config change, record a frame
777+
// Reset interactions to assert only post-convert capture
778+
reset(fixture.scopes)
779+
replay.onScreenshotRecorded(mock())
780+
781+
// Should capture a session segment after conversion without additional config changes
782+
verify(fixture.scopes).captureReplay(any(), any())
783+
}
784+
729785
@Test
730786
fun `closed replay cannot be started`() {
731787
val replay = fixture.getSut(context)

0 commit comments

Comments
 (0)