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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
```
- Parse ART memory and garbage collector info from ANR tombstones into ART context ([#5428](https://github.com/getsentry/sentry-java/pull/5428))

### Improvements

- Improve SDK init performance by deferring `ReplayIntegration.start()` off the main thread ([#5474](https://github.com/getsentry/sentry-java/pull/5474))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • ๐Ÿšซ The changelog entry seems to be part of an already released section ## 8.43.0.
    Consider moving the entry to the ## Unreleased section, please.


## 8.42.0

### Features
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ public class ReplayIntegration(
lifecycle.currentState >= STARTED && lifecycle.currentState < STOPPED

override fun start() {
val isFullSession: Boolean
lifecycleLock.acquire().use {
if (!isEnabled.get()) {
return
Expand All @@ -174,7 +175,7 @@ public class ReplayIntegration(
return
}

val isFullSession = random.sample(options.sessionReplay.sessionSampleRate)
isFullSession = random.sample(options.sessionReplay.sessionSampleRate)
if (!isFullSession && !options.sessionReplay.isSessionReplayForErrorsEnabled) {
options.logger.log(
INFO,
Expand All @@ -184,30 +185,39 @@ public class ReplayIntegration(
}

lifecycle.currentState = STARTED
captureStrategy =
replayCaptureStrategyProvider?.invoke(isFullSession)
?: if (isFullSession) {
SessionCaptureStrategy(
options,
scopes,
dateProvider,
replayExecutor,
replayCacheProvider,
)
} else {
BufferCaptureStrategy(
options,
scopes,
dateProvider,
random,
replayExecutor,
replayCacheProvider,
)
}
recorder?.start()
captureStrategy?.start()
}

// Defer the expensive work (strategy creation, recorder start, listener registration)
// off the calling thread to avoid blocking SentryAndroid.init() on the main thread.
options.executorService.submitSafely(options, "ReplayIntegration.start") {
lifecycleLock.acquire().use {
captureStrategy =
replayCaptureStrategyProvider?.invoke(isFullSession)
?: if (isFullSession) {
SessionCaptureStrategy(
options,
scopes,
dateProvider,
replayExecutor,
replayCacheProvider,
)
} else {
BufferCaptureStrategy(
options,
scopes,
dateProvider,
random,
replayExecutor,
replayCacheProvider,
)
}
recorder?.start()
captureStrategy?.start()
}

registerRootViewListeners()
// Post to main thread since registerRootViewListeners triggers View operations
// (e.g. addOnLayoutChangeListener) via the OnRootViewsChangedListener callback
mainLooperHandler.post { registerRootViewListeners() }
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import io.sentry.android.replay.ReplayIntegrationWithRecorderTest.LifecycleState
import io.sentry.android.replay.util.ReplayShadowMediaCodec
import io.sentry.rrweb.RRWebMetaEvent
import io.sentry.rrweb.RRWebVideoEvent
import io.sentry.test.ImmediateExecutorService
import io.sentry.transport.CurrentDateProvider
import io.sentry.transport.ICurrentDateProvider
import io.sentry.util.thread.NoOpThreadChecker
Expand All @@ -44,7 +45,11 @@ class ReplayIntegrationWithRecorderTest {
@get:Rule val tmpDir = TemporaryFolder()

internal class Fixture {
val options = SentryOptions().apply { threadChecker = NoOpThreadChecker.getInstance() }
val options =
SentryOptions().apply {
threadChecker = NoOpThreadChecker.getInstance()
executorService = ImmediateExecutorService()
}
val scopes = mock<IScopes>()

fun getSut(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import io.sentry.SentryReplayEvent.ReplayType
import io.sentry.android.replay.util.ReplayShadowMediaCodec
import io.sentry.rrweb.RRWebMetaEvent
import io.sentry.rrweb.RRWebVideoEvent
import io.sentry.test.ImmediateExecutorService
import io.sentry.transport.CurrentDateProvider
import io.sentry.transport.ICurrentDateProvider
import java.time.Duration
Expand Down Expand Up @@ -59,7 +60,7 @@ class ReplaySmokeTest {
@get:Rule val tmpDir = TemporaryFolder()

internal class Fixture {
val options = SentryOptions()
val options = SentryOptions().apply { executorService = ImmediateExecutorService() }
val scope = Scope(options)
val scopes =
mock<IScopes> {
Expand Down
Loading