Skip to content
Prev Previous commit
Next Next commit
Offload app components breadcrumbs to background thread
  • Loading branch information
markushi committed Oct 8, 2024
commit fd2bc62041be800df5b04288a8b26a11533643f5
Original file line number Diff line number Diff line change
Expand Up @@ -85,41 +85,20 @@ public void close() throws IOException {
@SuppressWarnings("deprecation")
@Override
public void onConfigurationChanged(@NotNull Configuration newConfig) {
if (hub != null) {
final Device.DeviceOrientation deviceOrientation =
DeviceOrientations.getOrientation(context.getResources().getConfiguration().orientation);

String orientation;
if (deviceOrientation != null) {
orientation = deviceOrientation.name().toLowerCase(Locale.ROOT);
} else {
orientation = "undefined";
}

final Breadcrumb breadcrumb = new Breadcrumb();
breadcrumb.setType("navigation");
breadcrumb.setCategory("device.orientation");
breadcrumb.setData("position", orientation);
breadcrumb.setLevel(SentryLevel.INFO);

final Hint hint = new Hint();
hint.set(ANDROID_CONFIGURATION, newConfig);

hub.addBreadcrumb(breadcrumb, hint);
}
executeInBackground(() -> captureConfigurationChangedBreadcrumb(newConfig));
Copy link
Member

Choose a reason for hiding this comment

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

i'm a little bit worried how this would work with session replay, because we're listening to orientation changes and change the replay orientation, but if the queue is busy here, the breadcrumb will be out-of-sync. Can we maybe keep this breadcrumb on the main thread still?

Copy link
Member Author

Choose a reason for hiding this comment

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

Let me switch to the new breadcrumb ctor with timestamp instead, then it should be fine.

}

@Override
public void onLowMemory() {
createLowMemoryBreadcrumb(null);
executeInBackground(() -> captureLowMemoryBreadcrumb(null));
}

@Override
public void onTrimMemory(final int level) {
createLowMemoryBreadcrumb(level);
executeInBackground(() -> captureLowMemoryBreadcrumb(level));
}

private void createLowMemoryBreadcrumb(final @Nullable Integer level) {
private void captureLowMemoryBreadcrumb(final @Nullable Integer level) {
if (hub != null) {
final Breadcrumb breadcrumb = new Breadcrumb();
if (level != null) {
Expand Down Expand Up @@ -147,4 +126,41 @@ private void createLowMemoryBreadcrumb(final @Nullable Integer level) {
hub.addBreadcrumb(breadcrumb);
}
}

private void captureConfigurationChangedBreadcrumb(final @NotNull Configuration newConfig) {
if (hub != null) {
final Device.DeviceOrientation deviceOrientation =
DeviceOrientations.getOrientation(context.getResources().getConfiguration().orientation);

String orientation;
if (deviceOrientation != null) {
orientation = deviceOrientation.name().toLowerCase(Locale.ROOT);
} else {
orientation = "undefined";
}

final Breadcrumb breadcrumb = new Breadcrumb();
breadcrumb.setType("navigation");
breadcrumb.setCategory("device.orientation");
breadcrumb.setData("position", orientation);
breadcrumb.setLevel(SentryLevel.INFO);

final Hint hint = new Hint();
hint.set(ANDROID_CONFIGURATION, newConfig);

hub.addBreadcrumb(breadcrumb, hint);
}
}

private void executeInBackground(final @NotNull Runnable runnable) {
if (options != null) {
try {
options.getExecutorService().submit(runnable);
} catch (Throwable t) {
options
.getLogger()
.log(SentryLevel.ERROR, t, "Failed to submit app components breadcrumb task");
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import io.sentry.Breadcrumb
import io.sentry.IHub
import io.sentry.SentryLevel
import io.sentry.test.ImmediateExecutorService
import org.junit.runner.RunWith
import org.mockito.kotlin.any
import org.mockito.kotlin.anyOrNull
Expand Down Expand Up @@ -88,7 +89,9 @@ class AppComponentsBreadcrumbsIntegrationTest {
@Test
fun `When low memory event, a breadcrumb with type, category and level should be set`() {
val sut = fixture.getSut()
val options = SentryAndroidOptions()
val options = SentryAndroidOptions().apply {
executorService = ImmediateExecutorService()
}
val hub = mock<IHub>()
sut.register(hub, options)
sut.onLowMemory()
Expand All @@ -104,7 +107,9 @@ class AppComponentsBreadcrumbsIntegrationTest {
@Test
fun `When trim memory event with level, a breadcrumb with type, category and level should be set`() {
val sut = fixture.getSut()
val options = SentryAndroidOptions()
val options = SentryAndroidOptions().apply {
executorService = ImmediateExecutorService()
}
val hub = mock<IHub>()
sut.register(hub, options)
sut.onTrimMemory(ComponentCallbacks2.TRIM_MEMORY_BACKGROUND)
Expand Down