Skip to content

Commit

Permalink
Merge 4d34601 into c9d0787
Browse files Browse the repository at this point in the history
  • Loading branch information
adinauer authored Apr 19, 2023
2 parents c9d0787 + 4d34601 commit e4bf816
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -279,11 +279,57 @@ private static void readDefaultOptionValues(
}
}

if (options.getProguardUuid() == null) {
options.setProguardUuid(getProguardUUID(context, options.getLogger()));
// TODO when to parse, when not?
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) {
// TODO really nullable?
final @Nullable String[] bundleIds = bundleIdStrings.split(",", -1);
if (bundleIds != null) {
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;
}

private static @Nullable String getProguardUUID(
final @NotNull Context context, final @NotNull ILogger logger) {
final AssetManager assets = context.getAssets();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,19 @@ class AndroidOptionsInitializerTest {
assertEquals("proguard-uuid", fixture.sentryOptions.proguardUuid)
}

@Test
fun `init should set bundle IDs id on start`() {
fixture.initSut(
Bundle().apply {
putString("io.sentry.bundle-ids", "12ea7a02-46ac-44c0-a5bb-6d1fd9586411, faa3ab42-b1bd-4659-af8e-1682324aa744")
},
hasAppContext = false
)

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
5 changes: 5 additions & 0 deletions sentry/api/sentry.api
Original file line number Diff line number Diff line change
Expand Up @@ -229,13 +229,15 @@ public abstract interface class io/sentry/EventProcessor {

public final class io/sentry/ExternalOptions {
public fun <init> ()V
public fun addBundleId (Ljava/lang/String;)V
public fun addContextTag (Ljava/lang/String;)V
public fun addIgnoredExceptionForType (Ljava/lang/Class;)V
public fun addInAppExclude (Ljava/lang/String;)V
public fun addInAppInclude (Ljava/lang/String;)V
public fun addTracePropagationTarget (Ljava/lang/String;)V
public fun addTracingOrigin (Ljava/lang/String;)V
public static fun from (Lio/sentry/config/PropertiesProvider;Lio/sentry/ILogger;)Lio/sentry/ExternalOptions;
public fun getBundleIds ()Ljava/util/Set;
public fun getContextTags ()Ljava/util/List;
public fun getDebug ()Ljava/lang/Boolean;
public fun getDist ()Ljava/lang/String;
Expand Down Expand Up @@ -1541,6 +1543,7 @@ public final class io/sentry/SentryNanotimeDateProvider : io/sentry/SentryDatePr

public class io/sentry/SentryOptions {
public fun <init> ()V
public fun addBundleId (Ljava/lang/String;)V
public fun addCollector (Lio/sentry/ICollector;)V
public fun addContextTag (Ljava/lang/String;)V
public fun addEventProcessor (Lio/sentry/EventProcessor;)V
Expand All @@ -1553,6 +1556,7 @@ public class io/sentry/SentryOptions {
public fun getBeforeBreadcrumb ()Lio/sentry/SentryOptions$BeforeBreadcrumbCallback;
public fun getBeforeSend ()Lio/sentry/SentryOptions$BeforeSendCallback;
public fun getBeforeSendTransaction ()Lio/sentry/SentryOptions$BeforeSendTransactionCallback;
public fun getBundleIds ()Ljava/util/Set;
public fun getCacheDirPath ()Ljava/lang/String;
public fun getClientReportRecorder ()Lio/sentry/clientreport/IClientReportRecorder;
public fun getCollectors ()Ljava/util/List;
Expand Down Expand Up @@ -2688,6 +2692,7 @@ public final class io/sentry/protocol/Contexts$Deserializer : io/sentry/JsonDese
}

public final class io/sentry/protocol/DebugImage : io/sentry/JsonSerializable, io/sentry/JsonUnknown {
public static final field JVM Ljava/lang/String;
public static final field PROGUARD Ljava/lang/String;
public fun <init> ()V
public fun getArch ()Ljava/lang/String;
Expand Down
12 changes: 12 additions & 0 deletions sentry/src/main/java/io/sentry/ExternalOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public final class ExternalOptions {
new CopyOnWriteArraySet<>();
private @Nullable Boolean printUncaughtStackTrace;
private @Nullable Boolean sendClientReports;
private @NotNull Set<String> bundleIds = new CopyOnWriteArraySet<>();

@SuppressWarnings("unchecked")
public static @NotNull ExternalOptions from(
Expand Down Expand Up @@ -109,6 +110,9 @@ public final class ExternalOptions {
options.addContextTag(contextTag);
}
options.setProguardUuid(propertiesProvider.getProperty("proguard-uuid"));
for (final String bundleId : propertiesProvider.getList("bundle-ids")) {
options.addBundleId(bundleId);
}
options.setIdleTimeout(propertiesProvider.getLongProperty("idle-timeout"));

for (final String ignoredExceptionType :
Expand Down Expand Up @@ -335,4 +339,12 @@ public void setIdleTimeout(final @Nullable Long idleTimeout) {
public void setSendClientReports(final @Nullable Boolean sendClientReports) {
this.sendClientReports = sendClientReports;
}

public @NotNull Set<String> getBundleIds() {
return bundleIds;
}

public void addBundleId(final @NotNull String bundleId) {
bundleIds.add(bundleId);
}
}
31 changes: 22 additions & 9 deletions sentry/src/main/java/io/sentry/MainEventProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
Expand Down Expand Up @@ -66,23 +67,35 @@ public MainEventProcessor(final @NotNull SentryOptions options) {
}

private void setDebugMeta(final @NotNull SentryBaseEvent event) {
final @NotNull List<DebugImage> debugImages = new CopyOnWriteArrayList<>();

if (options.getProguardUuid() != null) {
final DebugImage proguardMappingImage = new DebugImage();
proguardMappingImage.setType(DebugImage.PROGUARD);
proguardMappingImage.setUuid(options.getProguardUuid());
debugImages.add(proguardMappingImage);
}

for (final @NotNull String bundleId : options.getBundleIds()) {
final DebugImage sourceBundleImage = new DebugImage();
sourceBundleImage.setType(DebugImage.JVM);
sourceBundleImage.setDebugId(bundleId);
debugImages.add(sourceBundleImage);
}

if (!debugImages.isEmpty()) {
DebugMeta debugMeta = event.getDebugMeta();

if (debugMeta == null) {
debugMeta = new DebugMeta();
}
if (debugMeta.getImages() == null) {
debugMeta.setImages(new ArrayList<>());
}
List<DebugImage> images = debugMeta.getImages();
if (images != null) {
final DebugImage debugImage = new DebugImage();
debugImage.setType(DebugImage.PROGUARD);
debugImage.setUuid(options.getProguardUuid());
images.add(debugImage);
event.setDebugMeta(debugMeta);
debugMeta.setImages(debugImages);
} else {
debugMeta.getImages().addAll(debugImages);
}

event.setDebugMeta(debugMeta);
}
}

Expand Down
31 changes: 31 additions & 0 deletions sentry/src/main/java/io/sentry/SentryOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ public class SentryOptions {
*/
private final @NotNull List<Integration> integrations = new CopyOnWriteArrayList<>();

/** List of bundle IDs representing source bundles. */
private final @NotNull Set<String> bundleIds = new CopyOnWriteArraySet<>();

/**
* The DSN tells the SDK where to send the events to. If this value is not provided, the SDK will
* just not send any events.
Expand Down Expand Up @@ -1776,6 +1779,31 @@ public void setProguardUuid(final @Nullable String proguardUuid) {
this.proguardUuid = proguardUuid;
}

/**
* Adds a bundle ID (also known as debugId) representing a source bundle that contains sources for
* this application. These sources will be used to source code for frames of an exceptions stack
* trace.
*
* @param bundleId Bundle ID generated by sentry-cli or the sentry-android-gradle-plugin
*/
public void addBundleId(final @Nullable String bundleId) {
if (bundleId != null) {
final @NotNull String trimmedBundleId = bundleId.trim();
if (!trimmedBundleId.isEmpty()) {
this.bundleIds.add(trimmedBundleId);
}
}
}

/**
* Returns all configured bundle IDs referencing source code bundles.
*
* @return list of bundle IDs
*/
public @NotNull Set<String> getBundleIds() {
return bundleIds;
}

/**
* Returns Context tags names applied to Sentry events as Sentry tags.
*
Expand Down Expand Up @@ -2229,6 +2257,9 @@ public void merge(final @NotNull ExternalOptions options) {
if (options.getIdleTimeout() != null) {
setIdleTimeout(options.getIdleTimeout());
}
for (String bundleId : options.getBundleIds()) {
addBundleId(bundleId);
}
}

private @NotNull SdkVersion createSdkVersion() {
Expand Down
1 change: 1 addition & 0 deletions sentry/src/main/java/io/sentry/protocol/DebugImage.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
*/
public final class DebugImage implements JsonUnknown, JsonSerializable {
public static final String PROGUARD = "proguard";
public static final String JVM = "jvm";

/**
* The unique UUID of the image.
Expand Down
31 changes: 31 additions & 0 deletions sentry/src/test/java/io/sentry/ExternalOptionsTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,37 @@ class ExternalOptionsTest {
}
}

@Test
fun `creates options with single bundle ID using external properties`() {
withPropertiesFile("bundle-ids=12ea7a02-46ac-44c0-a5bb-6d1fd9586411") { options ->
assertTrue(options.bundleIds.containsAll(listOf("12ea7a02-46ac-44c0-a5bb-6d1fd9586411")))
}
}

@Test
fun `creates options with multiple bundle IDs using external properties`() {
withPropertiesFile("bundle-ids=12ea7a02-46ac-44c0-a5bb-6d1fd9586411,faa3ab42-b1bd-4659-af8e-1682324aa744") { options ->
assertTrue(options.bundleIds.containsAll(listOf("12ea7a02-46ac-44c0-a5bb-6d1fd9586411", "faa3ab42-b1bd-4659-af8e-1682324aa744")))
}
}

@Test
fun `creates options with empty bundle IDs using external properties`() {
withPropertiesFile("bundle-ids=") { options ->
assertTrue(options.bundleIds.size == 1)
// trimming is tested in SentryOptionsTest so even though there's an empty string here
// it will be filtered when being merged with SentryOptions
assertTrue(options.bundleIds.containsAll(listOf("")))
}
}

@Test
fun `creates options with missing bundle IDs using external properties`() {
withPropertiesFile("") { options ->
assertTrue(options.bundleIds.isEmpty())
}
}

private fun withPropertiesFile(textLines: List<String> = emptyList(), logger: ILogger = mock(), fn: (ExternalOptions) -> Unit) {
// create a sentry.properties file in temporary folder
val temporaryFolder = TemporaryFolder()
Expand Down
2 changes: 2 additions & 0 deletions sentry/src/test/java/io/sentry/SentryOptionsTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,7 @@ class SentryOptionsTest {
externalOptions.addContextTag("requestId")
externalOptions.proguardUuid = "1234"
externalOptions.idleTimeout = 1500L
externalOptions.bundleIds.addAll(listOf("12ea7a02-46ac-44c0-a5bb-6d1fd9586411 ", " faa3ab42-b1bd-4659-af8e-1682324aa744"))
val options = SentryOptions()

options.merge(externalOptions)
Expand All @@ -380,6 +381,7 @@ class SentryOptionsTest {
assertEquals(listOf("userId", "requestId"), options.contextTags)
assertEquals("1234", options.proguardUuid)
assertEquals(1500L, options.idleTimeout)
assertEquals(setOf("12ea7a02-46ac-44c0-a5bb-6d1fd9586411", "faa3ab42-b1bd-4659-af8e-1682324aa744"), options.bundleIds)
}

@Test
Expand Down

0 comments on commit e4bf816

Please sign in to comment.