Skip to content

Commit

Permalink
Merge branch 'main' into feat/6.7.x
Browse files Browse the repository at this point in the history
  • Loading branch information
adinauer committed Nov 4, 2022
2 parents 4ab6fc4 + 2826e76 commit d741807
Show file tree
Hide file tree
Showing 23 changed files with 595 additions and 20 deletions.
4 changes: 2 additions & 2 deletions .sauce/sentry-uitest-android-benchmark.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ suites:
- name: "Android 12 (api 31)"
devices:
- id: Google_Pixel_6_Pro_real_us # Google Pixel 6 Pro - api 31 (12) - high end
- id: Google_Pixel_3_12_real_us # Google Pixel 3 - api 31 (12) - low end
- id: Google_Pixel_6a_real_us # Google Pixel 6a - api 31 (12) - low end

- name: "Android 11 (api 30)"
devices:
Expand All @@ -32,7 +32,7 @@ suites:

- name: "Android 10 (api 29)"
devices:
- id: Google_Pixel_4_XL_real_us1 # Google Pixel 4 XL - api 29 (10)
- id: OnePlus_7_Pro_real # OnePlus 7 Pro - api 29 (10)
- id: Nokia_7_1_real_us # Nokia 7.1 - api 29 (10)

# At the time of writing (July, 4, 2022), the market share per android version is:
Expand Down
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
### Fixes

- Use correct set-cookie for the HTTP Client response object ([#2326](https://github.com/getsentry/sentry-java/pull/2326))
- Fix NoSuchElementException in CircularFifoQueue when cloning a Scope ([#2328](https://github.com/getsentry/sentry-java/pull/2328))

### Features

- Customizable fragment lifecycle breadcrumbs ([#2299](https://github.com/getsentry/sentry-java/pull/2299))
- Provide hook for Jetpack Compose navigation instrumentation ([#2320](https://github.com/getsentry/sentry-java/pull/2320))
- Populate `event.modules` with dependencies metadata ([#2324](https://github.com/getsentry/sentry-java/pull/2324))
- Support Spring 6 and Spring Boot 3 ([#2289](https://github.com/getsentry/sentry-java/pull/2289))

### Dependencies
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import io.sentry.SendFireAndForgetOutboxSender;
import io.sentry.SentryLevel;
import io.sentry.android.core.cache.AndroidEnvelopeCache;
import io.sentry.android.core.internal.modules.AssetsModulesLoader;
import io.sentry.android.fragment.FragmentLifecycleIntegration;
import io.sentry.android.timber.SentryTimberIntegration;
import io.sentry.util.Objects;
Expand Down Expand Up @@ -155,6 +156,7 @@ static void init(
options.setTransportGate(new AndroidTransportGate(context, options.getLogger()));
options.setTransactionProfiler(
new AndroidTransactionProfiler(context, options, buildInfoProvider));
options.setModulesLoader(new AssetsModulesLoader(context, options.getLogger()));
}

private static void installDefaultIntegrations(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package io.sentry.android.core.internal.modules;

import android.content.Context;
import io.sentry.ILogger;
import io.sentry.SentryLevel;
import io.sentry.internal.modules.ModulesLoader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.TreeMap;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;

@ApiStatus.Internal
public final class AssetsModulesLoader extends ModulesLoader {

private final @NotNull Context context;

public AssetsModulesLoader(final @NotNull Context context, final @NotNull ILogger logger) {
super(logger);
this.context = context;
}

@Override
protected Map<String, String> loadModules() {
final Map<String, String> modules = new TreeMap<>();

try {
final InputStream stream = context.getAssets().open(EXTERNAL_MODULES_FILENAME);
return parseStream(stream);
} catch (FileNotFoundException e) {
logger.log(SentryLevel.INFO, "%s file was not found.", EXTERNAL_MODULES_FILENAME);
} catch (IOException e) {
logger.log(SentryLevel.ERROR, "Error extracting modules.", e);
}
return modules;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import io.sentry.ILogger
import io.sentry.MainEventProcessor
import io.sentry.SentryOptions
import io.sentry.android.core.cache.AndroidEnvelopeCache
import io.sentry.android.core.internal.modules.AssetsModulesLoader
import io.sentry.android.fragment.FragmentLifecycleIntegration
import io.sentry.android.timber.SentryTimberIntegration
import org.junit.runner.RunWith
Expand Down Expand Up @@ -420,4 +421,11 @@ class AndroidOptionsInitializerTest {
(activityLifeCycleIntegration as ActivityLifecycleIntegration).activityFramesTracker.isFrameMetricsAggregatorAvailable
)
}

@Test
fun `AssetsModulesLoader is set to options`() {
fixture.initSut()

assertTrue { fixture.sentryOptions.modulesLoader is AssetsModulesLoader }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package io.sentry.android.core.internal.modules

import android.content.Context
import android.content.res.AssetManager
import io.sentry.ILogger
import org.mockito.kotlin.mock
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
import java.io.FileNotFoundException
import java.nio.charset.Charset
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue

class AssetsModulesLoaderTest {

class Fixture {
val context = mock<Context>()
val assets = mock<AssetManager>()
val logger = mock<ILogger>()

fun getSut(
fileName: String = "sentry-external-modules.txt",
content: String? = null,
throws: Boolean = false
): AssetsModulesLoader {
if (content != null) {
whenever(assets.open(fileName)).thenReturn(
content.byteInputStream(Charset.defaultCharset())
)
}
if (throws) {
whenever(assets.open(fileName)).thenThrow(FileNotFoundException())
}
whenever(context.assets).thenReturn(assets)
return AssetsModulesLoader(context, logger)
}
}

private val fixture = Fixture()

@Test
fun `reads modules from assets into map`() {
val sut = fixture.getSut(
content =
"""
com.squareup.okhttp3:okhttp:3.14.9
com.squareup.okio:okio:1.17.2
""".trimIndent()
)

assertEquals(
mapOf(
"com.squareup.okhttp3:okhttp" to "3.14.9",
"com.squareup.okio:okio" to "1.17.2"
),
sut.orLoadModules
)
}

@Test
fun `caches modules after first read`() {
val sut = fixture.getSut(
content =
"""
com.squareup.okhttp3:okhttp:3.14.9
com.squareup.okio:okio:1.17.2
""".trimIndent()
)

// first, call method to get modules cached
sut.orLoadModules

// then call it second time
assertEquals(
mapOf(
"com.squareup.okhttp3:okhttp" to "3.14.9",
"com.squareup.okio:okio" to "1.17.2"
),
sut.orLoadModules
)
// the context only called once when there's no in-memory cache
verify(fixture.context).assets
}

@Test
fun `when file does not exist, swallows exception and returns empty map`() {
val sut = fixture.getSut(throws = true)

assertTrue(sut.orLoadModules!!.isEmpty())
}

@Test
fun `when content is malformed, swallows exception and returns empty map`() {
val sut = fixture.getSut(
content =
"""
com.squareup.okhttp3;3.14.9
""".trimIndent()
)

assertTrue(sut.orLoadModules!!.isEmpty())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ package io.sentry.uitest.android
import android.content.Context
import androidx.test.core.app.ApplicationProvider
import androidx.test.espresso.Espresso
import androidx.test.espresso.IdlingPolicies
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.idling.CountingIdlingResource
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.runner.AndroidJUnitRunner
import io.sentry.Sentry
import io.sentry.SentryOptions
import io.sentry.android.core.SentryAndroid
import io.sentry.android.core.SentryAndroidOptions
import io.sentry.uitest.android.mockservers.MockRelay
import java.util.concurrent.TimeUnit
import kotlin.test.AfterTest
import kotlin.test.BeforeTest

Expand Down Expand Up @@ -40,6 +42,7 @@ abstract class BaseUiTest {
@BeforeTest
fun baseSetUp() {
runner = InstrumentationRegistry.getInstrumentation() as AndroidJUnitRunner
IdlingPolicies.setIdlingResourceTimeout(10, TimeUnit.SECONDS)
context = ApplicationProvider.getApplicationContext()
context.cacheDir.deleteRecursively()
relay.start()
Expand All @@ -61,7 +64,7 @@ abstract class BaseUiTest {
*/
protected fun initSentry(
relayWaitForRequests: Boolean = false,
optionsConfiguration: ((options: SentryOptions) -> Unit)? = null
optionsConfiguration: ((options: SentryAndroidOptions) -> Unit)? = null
) {
relay.waitForRequests = relayWaitForRequests
if (relayWaitForRequests) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import io.sentry.ProfilingTraceData
import io.sentry.Sentry
import io.sentry.SentryEvent
import io.sentry.SentryOptions
import io.sentry.android.core.SentryAndroidOptions
import io.sentry.protocol.SentryTransaction
import org.junit.runner.RunWith
import java.io.File
Expand Down Expand Up @@ -45,7 +45,7 @@ class EnvelopeTests : BaseUiTest() {

@Test
fun checkEnvelopeProfiledTransaction() {
initSentry(true) { options: SentryOptions ->
initSentry(true) { options: SentryAndroidOptions ->
options.tracesSampleRate = 1.0
options.profilesSampleRate = 1.0
}
Expand Down Expand Up @@ -80,7 +80,7 @@ class EnvelopeTests : BaseUiTest() {

@Test
fun checkEnvelopeConcurrentTransactions() {
initSentry(true) { options: SentryOptions ->
initSentry(true) { options: SentryAndroidOptions ->
options.tracesSampleRate = 1.0
options.profilesSampleRate = 1.0
}
Expand Down Expand Up @@ -154,7 +154,7 @@ class EnvelopeTests : BaseUiTest() {

@Test
fun checkProfileNotSentIfEmpty() {
initSentry(true) { options: SentryOptions ->
initSentry(true) { options: SentryAndroidOptions ->
options.tracesSampleRate = 1.0
options.profilesSampleRate = 1.0
}
Expand Down Expand Up @@ -187,11 +187,11 @@ class EnvelopeTests : BaseUiTest() {
}
}

@Test
// @Test
fun checkTimedOutProfile() {
// We increase the IdlingResources timeout to exceed the profiling timeout
IdlingPolicies.setIdlingResourceTimeout(1, TimeUnit.MINUTES)
initSentry(true) { options: SentryOptions ->
initSentry(true) { options: SentryAndroidOptions ->
options.tracesSampleRate = 1.0
options.profilesSampleRate = 1.0
}
Expand All @@ -215,7 +215,7 @@ class EnvelopeTests : BaseUiTest() {
fun sendProfiledTransaction() {
// This is a dogfooding test
IdlingRegistry.getInstance().register(ProfilingSampleActivity.scrollingIdlingResource)
initSentry(false) { options: SentryOptions ->
initSentry(false) { options: SentryAndroidOptions ->
options.dsn = "https://640fae2f19ac4ba78ad740175f50195f@o1137848.ingest.sentry.io/6191083"
options.tracesSampleRate = 1.0
options.profilesSampleRate = 1.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package io.sentry.uitest.android

import android.graphics.Bitmap
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.view.LayoutInflater
import android.view.ViewGroup
Expand Down Expand Up @@ -32,6 +33,10 @@ class ProfilingSampleActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
window.setSustainedPerformanceMode(true)
}

binding = ActivityProfilingSampleBinding.inflate(layoutInflater)
setContentView(binding.root)

Expand Down
24 changes: 24 additions & 0 deletions sentry/api/sentry.api
Original file line number Diff line number Diff line change
Expand Up @@ -1379,6 +1379,7 @@ public class io/sentry/SentryOptions {
public fun getMaxRequestBodySize ()Lio/sentry/SentryOptions$RequestSize;
public fun getMaxSpans ()I
public fun getMaxTraceFileSize ()J
public fun getModulesLoader ()Lio/sentry/internal/modules/IModulesLoader;
public fun getOutboxPath ()Ljava/lang/String;
public fun getProfilesSampleRate ()Ljava/lang/Double;
public fun getProfilesSampler ()Lio/sentry/SentryOptions$ProfilesSamplerCallback;
Expand Down Expand Up @@ -1457,6 +1458,7 @@ public class io/sentry/SentryOptions {
public fun setMaxRequestBodySize (Lio/sentry/SentryOptions$RequestSize;)V
public fun setMaxSpans (I)V
public fun setMaxTraceFileSize (J)V
public fun setModulesLoader (Lio/sentry/internal/modules/IModulesLoader;)V
public fun setPrintUncaughtStackTrace (Z)V
public fun setProfilesSampleRate (Ljava/lang/Double;)V
public fun setProfilesSampler (Lio/sentry/SentryOptions$ProfilesSamplerCallback;)V
Expand Down Expand Up @@ -2190,6 +2192,28 @@ public final class io/sentry/instrumentation/file/SentryFileWriter : java/io/Out
public fun <init> (Ljava/lang/String;Z)V
}

public abstract interface class io/sentry/internal/modules/IModulesLoader {
public abstract fun getOrLoadModules ()Ljava/util/Map;
}

public abstract class io/sentry/internal/modules/ModulesLoader : io/sentry/internal/modules/IModulesLoader {
public static final field EXTERNAL_MODULES_FILENAME Ljava/lang/String;
protected final field logger Lio/sentry/ILogger;
public fun <init> (Lio/sentry/ILogger;)V
public fun getOrLoadModules ()Ljava/util/Map;
protected abstract fun loadModules ()Ljava/util/Map;
protected fun parseStream (Ljava/io/InputStream;)Ljava/util/Map;
}

public final class io/sentry/internal/modules/NoOpModulesLoader : io/sentry/internal/modules/IModulesLoader {
public static fun getInstance ()Lio/sentry/internal/modules/NoOpModulesLoader;
public fun getOrLoadModules ()Ljava/util/Map;
}

public final class io/sentry/internal/modules/ResourcesModulesLoader : io/sentry/internal/modules/ModulesLoader {
public fun <init> (Lio/sentry/ILogger;)V
}

public final class io/sentry/protocol/App : io/sentry/JsonSerializable, io/sentry/JsonUnknown {
public static final field TYPE Ljava/lang/String;
public fun <init> ()V
Expand Down
15 changes: 15 additions & 0 deletions sentry/src/main/java/io/sentry/MainEventProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public MainEventProcessor(final @NotNull SentryOptions options) {
setCommons(event);
setExceptions(event);
setDebugMeta(event);
setModules(event);

if (shouldApplyScopeData(event, hint)) {
processNonCachedEvent(event);
Expand Down Expand Up @@ -90,6 +91,20 @@ private void setDebugMeta(final @NotNull SentryEvent event) {
}
}

private void setModules(final @NotNull SentryEvent event) {
final Map<String, String> modules = options.getModulesLoader().getOrLoadModules();
if (modules == null) {
return;
}

final Map<String, String> eventModules = event.getModules();
if (eventModules == null) {
event.setModules(modules);
} else {
eventModules.putAll(modules);
}
}

private boolean shouldApplyScopeData(
final @NotNull SentryBaseEvent event, final @NotNull Hint hint) {
if (HintUtils.shouldApplyScopeData(hint)) {
Expand Down

0 comments on commit d741807

Please sign in to comment.