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

Load sentry-debug-meta.properties #2734

Merged
merged 6 commits into from
May 30, 2023
Merged
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
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@
### Features

- Add SentryWrapper for Callable and Supplier Interface ([#2720](https://github.com/getsentry/sentry-java/pull/2720))
- Load sentry-debug-meta.properties ([#2734](https://github.com/getsentry/sentry-java/pull/2734))
- This enables source context for Java
- For more information on how to enable source context, please refer to [#633](https://github.com/getsentry/sentry-java/issues/633#issuecomment-1465599120)

### Fixes

- Finish WebFlux transaction before popping scope ([#2724](https://github.com/getsentry/sentry-java/pull/2724))

## 6.20.0

Expand All @@ -29,7 +36,6 @@
### Fixes

- Base64 encode internal Apollo3 Headers ([#2707](https://github.com/getsentry/sentry-java/pull/2707))
- Finish WebFlux transaction before popping scope ([#2724](https://github.com/getsentry/sentry-java/pull/2724))
- Fix `SentryTracer` crash when scheduling auto-finish of a transaction, but the timer has already been cancelled ([#2731](https://github.com/getsentry/sentry-java/pull/2731))
- Fix `AndroidTransactionProfiler` crash when finishing a profile that happened due to race condition ([#2731](https://github.com/getsentry/sentry-java/pull/2731))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
import android.app.Application;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.res.AssetManager;
import android.os.Build;
import io.sentry.DefaultTransactionPerformanceCollector;
import io.sentry.ILogger;
import io.sentry.SendFireAndForgetEnvelopeSender;
import io.sentry.SendFireAndForgetOutboxSender;
import io.sentry.SentryLevel;
import io.sentry.android.core.cache.AndroidEnvelopeCache;
import io.sentry.android.core.internal.debugmeta.AssetsDebugMetaLoader;
import io.sentry.android.core.internal.gestures.AndroidViewGestureTargetLocator;
import io.sentry.android.core.internal.modules.AssetsModulesLoader;
import io.sentry.android.core.internal.util.AndroidMainThreadChecker;
Expand All @@ -27,16 +27,10 @@
import io.sentry.internal.viewhierarchy.ViewHierarchyExporter;
import io.sentry.transport.NoOpEnvelopeCache;
import io.sentry.util.Objects;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;

/**
Expand Down Expand Up @@ -153,6 +147,7 @@ static void initializeIntegrationsAndProcessors(
options.setTransactionProfiler(
new AndroidTransactionProfiler(context, options, buildInfoProvider, frameMetricsCollector));
options.setModulesLoader(new AssetsModulesLoader(context, options.getLogger()));
options.setDebugMetaLoader(new AssetsDebugMetaLoader(context, options.getLogger()));

final boolean isAndroidXScrollViewAvailable =
loadClass.isClassAvailable("androidx.core.view.ScrollingView", options);
Expand Down Expand Up @@ -303,52 +298,6 @@ private static void readDefaultOptionValues(
options.getLogger().log(SentryLevel.ERROR, "Could not generate distinct Id.", e);
}
}

final @Nullable Properties debugMetaProperties =
loadDebugMetaProperties(context, options.getLogger());

if (debugMetaProperties != null) {
if (options.getProguardUuid() == null) {
final @Nullable String proguardUuid =
debugMetaProperties.getProperty("io.sentry.ProguardUuids");
options.getLogger().log(SentryLevel.DEBUG, "Proguard UUID found: %s", proguardUuid);
options.setProguardUuid(proguardUuid);
}

if (options.getBundleIds().isEmpty()) {
final @Nullable String bundleIdStrings =
debugMetaProperties.getProperty("io.sentry.bundle-ids");
options.getLogger().log(SentryLevel.DEBUG, "Bundle IDs found: %s", bundleIdStrings);
if (bundleIdStrings != null) {
final @NotNull String[] bundleIds = bundleIdStrings.split(",", -1);
for (final String bundleId : bundleIds) {
options.addBundleId(bundleId);
}
}
}
}
}

private static @Nullable Properties loadDebugMetaProperties(
final @NotNull Context context, final @NotNull ILogger logger) {
final AssetManager assets = context.getAssets();
// one may have thousands of asset files and looking up this list might slow down the SDK init.
// quite a bit, for this reason, we try to open the file directly and take care of errors
// like FileNotFoundException
try (final InputStream is =
new BufferedInputStream(assets.open("sentry-debug-meta.properties"))) {
final Properties properties = new Properties();
properties.load(is);
return properties;
} catch (FileNotFoundException e) {
logger.log(SentryLevel.INFO, "sentry-debug-meta.properties file was not found.");
} catch (IOException e) {
logger.log(SentryLevel.ERROR, "Error getting Proguard UUIDs.", e);
} catch (RuntimeException e) {
logger.log(SentryLevel.ERROR, "sentry-debug-meta.properties file is malformed.", e);
}

return null;
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package io.sentry.android.core.internal.debugmeta;

import static io.sentry.util.DebugMetaPropertiesApplier.DEBUG_META_PROPERTIES_FILENAME;

import android.content.Context;
import android.content.res.AssetManager;
import io.sentry.ILogger;
import io.sentry.SentryLevel;
import io.sentry.internal.debugmeta.IDebugMetaLoader;
import java.io.BufferedInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

@ApiStatus.Internal
public final class AssetsDebugMetaLoader implements IDebugMetaLoader {
private final @NotNull Context context;
private final @NotNull ILogger logger;

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

@Override
public @Nullable Properties loadDebugMeta() {
final AssetManager assets = context.getAssets();
// one may have thousands of asset files and looking up this list might slow down the SDK init.
// quite a bit, for this reason, we try to open the file directly and take care of errors
// like FileNotFoundException
try (final InputStream is =
new BufferedInputStream(assets.open(DEBUG_META_PROPERTIES_FILENAME))) {
final Properties properties = new Properties();
properties.load(is);
return properties;
} catch (FileNotFoundException e) {
logger.log(SentryLevel.INFO, e, "%s file was not found.", DEBUG_META_PROPERTIES_FILENAME);
} catch (IOException e) {
logger.log(SentryLevel.ERROR, "Error getting Proguard UUIDs.", e);
} catch (RuntimeException e) {
logger.log(SentryLevel.ERROR, e, "%s file is malformed.", DEBUG_META_PROPERTIES_FILENAME);
}

return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -280,46 +280,6 @@ class AndroidOptionsInitializerTest {
assertEquals("proguard-uuid", fixture.sentryOptions.proguardUuid)
}

@Test
fun `init should set proguard uuid from properties id on start`() {
val assets = mock<AssetManager>()

whenever(assets.open("sentry-debug-meta.properties")).thenReturn(
"""
io.sentry.ProguardUuids=12ea7a02-46ac-44c0-a5bb-6d1fd9586411
""".trimIndent().byteInputStream()
)

fixture.initSut(
Bundle(),
hasAppContext = false,
assets = assets
)

assertNotNull(fixture.sentryOptions.proguardUuid)
assertEquals("12ea7a02-46ac-44c0-a5bb-6d1fd9586411", fixture.sentryOptions.proguardUuid)
}

@Test
fun `init should set bundle IDs id on start`() {
val assets = mock<AssetManager>()

whenever(assets.open("sentry-debug-meta.properties")).thenReturn(
"""
io.sentry.bundle-ids=12ea7a02-46ac-44c0-a5bb-6d1fd9586411, faa3ab42-b1bd-4659-af8e-1682324aa744
""".trimIndent().byteInputStream()
)

fixture.initSut(
Bundle(),
hasAppContext = false,
assets = assets
)

assertTrue(fixture.sentryOptions.bundleIds.size == 2)
assertTrue(fixture.sentryOptions.bundleIds.containsAll(listOf("12ea7a02-46ac-44c0-a5bb-6d1fd9586411", "faa3ab42-b1bd-4659-af8e-1682324aa744")))
}

@Test
fun `init should set Android transport gate`() {
fixture.initSut()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package io.sentry.android.core.internal.debugmeta

import android.content.Context
import android.content.res.AssetManager
import io.sentry.ILogger
import io.sentry.SentryOptions
import io.sentry.util.DebugMetaPropertiesApplier
import org.mockito.kotlin.mock
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.assertNotNull
import kotlin.test.assertNull

class AssetsDebugMetaLoaderTest {

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

fun getSut(
fileName: String = "sentry-debug-meta.properties",
content: String? = null,
throws: Boolean = false
): AssetsDebugMetaLoader {
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 AssetsDebugMetaLoader(context, logger)
}
}

private val fixture = Fixture()

@Test
fun `reads from assets into properties and can be applied to options`() {
val sut = fixture.getSut(
content =
"""
#Generated by sentry-maven-plugin
#Wed May 17 15:33:34 CEST 2023
io.sentry.ProguardUuids=34077988-a0e5-4839-9618-7400e1616d1b
io.sentry.bundle-ids=88ba82db-cd26-4c09-8b31-21461d286b68
io.sentry.build-tool=maven
""".trimIndent()
)

val options = SentryOptions()

assertNotNull(sut.loadDebugMeta()) {
DebugMetaPropertiesApplier.applyToOptions(options, it)
}

assertEquals(options.bundleIds, setOf("88ba82db-cd26-4c09-8b31-21461d286b68"))
assertEquals(options.proguardUuid, "34077988-a0e5-4839-9618-7400e1616d1b")
}

@Test
fun `reads multiple bundle IDs from assets into properties and can be applied to options`() {
val sut = fixture.getSut(
content =
"""
#Generated by sentry-maven-plugin
#Wed May 17 15:33:34 CEST 2023
io.sentry.ProguardUuids=34077988-a0e5-4839-9618-7400e1616d1b
io.sentry.bundle-ids=88ba82db-cd26-4c09-8b31-21461d286b68,8d11a44a-facd-46c1-a49b-87d256227101
io.sentry.build-tool=maven
""".trimIndent()
)

val options = SentryOptions()

assertNotNull(sut.loadDebugMeta()) {
DebugMetaPropertiesApplier.applyToOptions(options, it)
}

assertEquals(options.bundleIds, setOf("88ba82db-cd26-4c09-8b31-21461d286b68", "8d11a44a-facd-46c1-a49b-87d256227101"))
assertEquals(options.proguardUuid, "34077988-a0e5-4839-9618-7400e1616d1b")
}

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

assertNull(sut.loadDebugMeta())
}
}
22 changes: 22 additions & 0 deletions sentry/api/sentry.api
Original file line number Diff line number Diff line change
Expand Up @@ -1648,6 +1648,7 @@ public class io/sentry/SentryOptions {
public fun getConnectionTimeoutMillis ()I
public fun getContextTags ()Ljava/util/List;
public fun getDateProvider ()Lio/sentry/SentryDateProvider;
public fun getDebugMetaLoader ()Lio/sentry/internal/debugmeta/IDebugMetaLoader;
public fun getDiagnosticLevel ()Lio/sentry/SentryLevel;
public fun getDist ()Ljava/lang/String;
public fun getDistinctId ()Ljava/lang/String;
Expand Down Expand Up @@ -1740,6 +1741,7 @@ public class io/sentry/SentryOptions {
public fun setConnectionTimeoutMillis (I)V
public fun setDateProvider (Lio/sentry/SentryDateProvider;)V
public fun setDebug (Z)V
public fun setDebugMetaLoader (Lio/sentry/internal/debugmeta/IDebugMetaLoader;)V
public fun setDiagnosticLevel (Lio/sentry/SentryLevel;)V
public fun setDist (Ljava/lang/String;)V
public fun setDistinctId (Ljava/lang/String;)V
Expand Down Expand Up @@ -2653,6 +2655,20 @@ 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/debugmeta/IDebugMetaLoader {
public abstract fun loadDebugMeta ()Ljava/util/Properties;
}

public final class io/sentry/internal/debugmeta/NoOpDebugMetaLoader : io/sentry/internal/debugmeta/IDebugMetaLoader {
public static fun getInstance ()Lio/sentry/internal/debugmeta/NoOpDebugMetaLoader;
public fun loadDebugMeta ()Ljava/util/Properties;
}

public final class io/sentry/internal/debugmeta/ResourcesDebugMetaLoader : io/sentry/internal/debugmeta/IDebugMetaLoader {
public fun <init> (Lio/sentry/ILogger;)V
public fun loadDebugMeta ()Ljava/util/Properties;
}

public abstract interface class io/sentry/internal/gestures/GestureTargetLocator {
public abstract fun locate (Ljava/lang/Object;FFLio/sentry/internal/gestures/UiElement$Type;)Lio/sentry/internal/gestures/UiElement;
}
Expand Down Expand Up @@ -4006,6 +4022,12 @@ public abstract interface class io/sentry/util/CollectionUtils$Predicate {
public abstract fun test (Ljava/lang/Object;)Z
}

public final class io/sentry/util/DebugMetaPropertiesApplier {
public static field DEBUG_META_PROPERTIES_FILENAME Ljava/lang/String;
public fun <init> ()V
public static fun applyToOptions (Lio/sentry/SentryOptions;Ljava/util/Properties;)V
}

public final class io/sentry/util/ExceptionUtils {
public fun <init> ()V
public static fun findRootCause (Ljava/lang/Throwable;)Ljava/lang/Throwable;
Expand Down
10 changes: 10 additions & 0 deletions sentry/src/main/java/io/sentry/Sentry.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import io.sentry.cache.EnvelopeCache;
import io.sentry.cache.IEnvelopeCache;
import io.sentry.config.PropertiesProviderFactory;
import io.sentry.internal.debugmeta.NoOpDebugMetaLoader;
import io.sentry.internal.debugmeta.ResourcesDebugMetaLoader;
import io.sentry.internal.modules.CompositeModulesLoader;
import io.sentry.internal.modules.IModulesLoader;
import io.sentry.internal.modules.ManifestModulesLoader;
Expand All @@ -11,6 +13,7 @@
import io.sentry.protocol.SentryId;
import io.sentry.protocol.User;
import io.sentry.transport.NoOpEnvelopeCache;
import io.sentry.util.DebugMetaPropertiesApplier;
import io.sentry.util.FileUtils;
import io.sentry.util.thread.IMainThreadChecker;
import io.sentry.util.thread.MainThreadChecker;
Expand All @@ -19,6 +22,7 @@
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.RejectedExecutionException;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
Expand Down Expand Up @@ -363,6 +367,12 @@ private static boolean initConfigurations(final @NotNull SentryOptions options)
options.getLogger()));
}

if (options.getDebugMetaLoader() instanceof NoOpDebugMetaLoader) {
options.setDebugMetaLoader(new ResourcesDebugMetaLoader(options.getLogger()));
}
final @Nullable Properties properties = options.getDebugMetaLoader().loadDebugMeta();
DebugMetaPropertiesApplier.applyToOptions(options, properties);

final IMainThreadChecker mainThreadChecker = options.getMainThreadChecker();
// only override the MainThreadChecker if it's not already set by Android
if (mainThreadChecker instanceof NoOpMainThreadChecker) {
Expand Down
Loading