Skip to content

Commit 9dddfbf

Browse files
authored
Load sentry-debug-meta.properties (#2734)
1 parent b056859 commit 9dddfbf

File tree

14 files changed

+456
-94
lines changed

14 files changed

+456
-94
lines changed

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@
55
### Features
66

77
- Add SentryWrapper for Callable and Supplier Interface ([#2720](https://github.com/getsentry/sentry-java/pull/2720))
8+
- Load sentry-debug-meta.properties ([#2734](https://github.com/getsentry/sentry-java/pull/2734))
9+
- This enables source context for Java
10+
- For more information on how to enable source context, please refer to [#633](https://github.com/getsentry/sentry-java/issues/633#issuecomment-1465599120)
11+
12+
### Fixes
13+
14+
- Finish WebFlux transaction before popping scope ([#2724](https://github.com/getsentry/sentry-java/pull/2724))
815

916
### Fixes
1017

@@ -33,7 +40,6 @@
3340
### Fixes
3441

3542
- Base64 encode internal Apollo3 Headers ([#2707](https://github.com/getsentry/sentry-java/pull/2707))
36-
- Finish WebFlux transaction before popping scope ([#2724](https://github.com/getsentry/sentry-java/pull/2724))
3743
- 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))
3844
- Fix `AndroidTransactionProfiler` crash when finishing a profile that happened due to race condition ([#2731](https://github.com/getsentry/sentry-java/pull/2731))
3945

sentry-android-core/src/main/java/io/sentry/android/core/AndroidOptionsInitializer.java

Lines changed: 2 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
import android.app.Application;
66
import android.content.Context;
77
import android.content.pm.PackageInfo;
8-
import android.content.res.AssetManager;
98
import android.os.Build;
109
import io.sentry.DefaultTransactionPerformanceCollector;
1110
import io.sentry.ILogger;
1211
import io.sentry.SendFireAndForgetEnvelopeSender;
1312
import io.sentry.SendFireAndForgetOutboxSender;
1413
import io.sentry.SentryLevel;
1514
import io.sentry.android.core.cache.AndroidEnvelopeCache;
15+
import io.sentry.android.core.internal.debugmeta.AssetsDebugMetaLoader;
1616
import io.sentry.android.core.internal.gestures.AndroidViewGestureTargetLocator;
1717
import io.sentry.android.core.internal.modules.AssetsModulesLoader;
1818
import io.sentry.android.core.internal.util.AndroidMainThreadChecker;
@@ -27,16 +27,10 @@
2727
import io.sentry.internal.viewhierarchy.ViewHierarchyExporter;
2828
import io.sentry.transport.NoOpEnvelopeCache;
2929
import io.sentry.util.Objects;
30-
import java.io.BufferedInputStream;
3130
import java.io.File;
32-
import java.io.FileNotFoundException;
33-
import java.io.IOException;
34-
import java.io.InputStream;
3531
import java.util.ArrayList;
3632
import java.util.List;
37-
import java.util.Properties;
3833
import org.jetbrains.annotations.NotNull;
39-
import org.jetbrains.annotations.Nullable;
4034
import org.jetbrains.annotations.TestOnly;
4135

4236
/**
@@ -153,6 +147,7 @@ static void initializeIntegrationsAndProcessors(
153147
options.setTransactionProfiler(
154148
new AndroidTransactionProfiler(context, options, buildInfoProvider, frameMetricsCollector));
155149
options.setModulesLoader(new AssetsModulesLoader(context, options.getLogger()));
150+
options.setDebugMetaLoader(new AssetsDebugMetaLoader(context, options.getLogger()));
156151

157152
final boolean isAndroidXScrollViewAvailable =
158153
loadClass.isClassAvailable("androidx.core.view.ScrollingView", options);
@@ -303,52 +298,6 @@ private static void readDefaultOptionValues(
303298
options.getLogger().log(SentryLevel.ERROR, "Could not generate distinct Id.", e);
304299
}
305300
}
306-
307-
final @Nullable Properties debugMetaProperties =
308-
loadDebugMetaProperties(context, options.getLogger());
309-
310-
if (debugMetaProperties != null) {
311-
if (options.getProguardUuid() == null) {
312-
final @Nullable String proguardUuid =
313-
debugMetaProperties.getProperty("io.sentry.ProguardUuids");
314-
options.getLogger().log(SentryLevel.DEBUG, "Proguard UUID found: %s", proguardUuid);
315-
options.setProguardUuid(proguardUuid);
316-
}
317-
318-
if (options.getBundleIds().isEmpty()) {
319-
final @Nullable String bundleIdStrings =
320-
debugMetaProperties.getProperty("io.sentry.bundle-ids");
321-
options.getLogger().log(SentryLevel.DEBUG, "Bundle IDs found: %s", bundleIdStrings);
322-
if (bundleIdStrings != null) {
323-
final @NotNull String[] bundleIds = bundleIdStrings.split(",", -1);
324-
for (final String bundleId : bundleIds) {
325-
options.addBundleId(bundleId);
326-
}
327-
}
328-
}
329-
}
330-
}
331-
332-
private static @Nullable Properties loadDebugMetaProperties(
333-
final @NotNull Context context, final @NotNull ILogger logger) {
334-
final AssetManager assets = context.getAssets();
335-
// one may have thousands of asset files and looking up this list might slow down the SDK init.
336-
// quite a bit, for this reason, we try to open the file directly and take care of errors
337-
// like FileNotFoundException
338-
try (final InputStream is =
339-
new BufferedInputStream(assets.open("sentry-debug-meta.properties"))) {
340-
final Properties properties = new Properties();
341-
properties.load(is);
342-
return properties;
343-
} catch (FileNotFoundException e) {
344-
logger.log(SentryLevel.INFO, "sentry-debug-meta.properties file was not found.");
345-
} catch (IOException e) {
346-
logger.log(SentryLevel.ERROR, "Error getting Proguard UUIDs.", e);
347-
} catch (RuntimeException e) {
348-
logger.log(SentryLevel.ERROR, "sentry-debug-meta.properties file is malformed.", e);
349-
}
350-
351-
return null;
352301
}
353302

354303
/**
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package io.sentry.android.core.internal.debugmeta;
2+
3+
import static io.sentry.util.DebugMetaPropertiesApplier.DEBUG_META_PROPERTIES_FILENAME;
4+
5+
import android.content.Context;
6+
import android.content.res.AssetManager;
7+
import io.sentry.ILogger;
8+
import io.sentry.SentryLevel;
9+
import io.sentry.internal.debugmeta.IDebugMetaLoader;
10+
import java.io.BufferedInputStream;
11+
import java.io.FileNotFoundException;
12+
import java.io.IOException;
13+
import java.io.InputStream;
14+
import java.util.Properties;
15+
import org.jetbrains.annotations.ApiStatus;
16+
import org.jetbrains.annotations.NotNull;
17+
import org.jetbrains.annotations.Nullable;
18+
19+
@ApiStatus.Internal
20+
public final class AssetsDebugMetaLoader implements IDebugMetaLoader {
21+
private final @NotNull Context context;
22+
private final @NotNull ILogger logger;
23+
24+
public AssetsDebugMetaLoader(final @NotNull Context context, final @NotNull ILogger logger) {
25+
this.context = context;
26+
this.logger = logger;
27+
}
28+
29+
@Override
30+
public @Nullable Properties loadDebugMeta() {
31+
final AssetManager assets = context.getAssets();
32+
// one may have thousands of asset files and looking up this list might slow down the SDK init.
33+
// quite a bit, for this reason, we try to open the file directly and take care of errors
34+
// like FileNotFoundException
35+
try (final InputStream is =
36+
new BufferedInputStream(assets.open(DEBUG_META_PROPERTIES_FILENAME))) {
37+
final Properties properties = new Properties();
38+
properties.load(is);
39+
return properties;
40+
} catch (FileNotFoundException e) {
41+
logger.log(SentryLevel.INFO, e, "%s file was not found.", DEBUG_META_PROPERTIES_FILENAME);
42+
} catch (IOException e) {
43+
logger.log(SentryLevel.ERROR, "Error getting Proguard UUIDs.", e);
44+
} catch (RuntimeException e) {
45+
logger.log(SentryLevel.ERROR, e, "%s file is malformed.", DEBUG_META_PROPERTIES_FILENAME);
46+
}
47+
48+
return null;
49+
}
50+
}

sentry-android-core/src/test/java/io/sentry/android/core/AndroidOptionsInitializerTest.kt

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -280,46 +280,6 @@ class AndroidOptionsInitializerTest {
280280
assertEquals("proguard-uuid", fixture.sentryOptions.proguardUuid)
281281
}
282282

283-
@Test
284-
fun `init should set proguard uuid from properties id on start`() {
285-
val assets = mock<AssetManager>()
286-
287-
whenever(assets.open("sentry-debug-meta.properties")).thenReturn(
288-
"""
289-
io.sentry.ProguardUuids=12ea7a02-46ac-44c0-a5bb-6d1fd9586411
290-
""".trimIndent().byteInputStream()
291-
)
292-
293-
fixture.initSut(
294-
Bundle(),
295-
hasAppContext = false,
296-
assets = assets
297-
)
298-
299-
assertNotNull(fixture.sentryOptions.proguardUuid)
300-
assertEquals("12ea7a02-46ac-44c0-a5bb-6d1fd9586411", fixture.sentryOptions.proguardUuid)
301-
}
302-
303-
@Test
304-
fun `init should set bundle IDs id on start`() {
305-
val assets = mock<AssetManager>()
306-
307-
whenever(assets.open("sentry-debug-meta.properties")).thenReturn(
308-
"""
309-
io.sentry.bundle-ids=12ea7a02-46ac-44c0-a5bb-6d1fd9586411, faa3ab42-b1bd-4659-af8e-1682324aa744
310-
""".trimIndent().byteInputStream()
311-
)
312-
313-
fixture.initSut(
314-
Bundle(),
315-
hasAppContext = false,
316-
assets = assets
317-
)
318-
319-
assertTrue(fixture.sentryOptions.bundleIds.size == 2)
320-
assertTrue(fixture.sentryOptions.bundleIds.containsAll(listOf("12ea7a02-46ac-44c0-a5bb-6d1fd9586411", "faa3ab42-b1bd-4659-af8e-1682324aa744")))
321-
}
322-
323283
@Test
324284
fun `init should set Android transport gate`() {
325285
fixture.initSut()
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package io.sentry.android.core.internal.debugmeta
2+
3+
import android.content.Context
4+
import android.content.res.AssetManager
5+
import io.sentry.ILogger
6+
import io.sentry.SentryOptions
7+
import io.sentry.util.DebugMetaPropertiesApplier
8+
import org.mockito.kotlin.mock
9+
import org.mockito.kotlin.whenever
10+
import java.io.FileNotFoundException
11+
import java.nio.charset.Charset
12+
import kotlin.test.Test
13+
import kotlin.test.assertEquals
14+
import kotlin.test.assertNotNull
15+
import kotlin.test.assertNull
16+
17+
class AssetsDebugMetaLoaderTest {
18+
19+
class Fixture {
20+
val context = mock<Context>()
21+
val assets = mock<AssetManager>()
22+
val logger = mock<ILogger>()
23+
24+
fun getSut(
25+
fileName: String = "sentry-debug-meta.properties",
26+
content: String? = null,
27+
throws: Boolean = false
28+
): AssetsDebugMetaLoader {
29+
if (content != null) {
30+
whenever(assets.open(fileName)).thenReturn(
31+
content.byteInputStream(Charset.defaultCharset())
32+
)
33+
}
34+
if (throws) {
35+
whenever(assets.open(fileName)).thenThrow(FileNotFoundException())
36+
}
37+
whenever(context.assets).thenReturn(assets)
38+
return AssetsDebugMetaLoader(context, logger)
39+
}
40+
}
41+
42+
private val fixture = Fixture()
43+
44+
@Test
45+
fun `reads from assets into properties and can be applied to options`() {
46+
val sut = fixture.getSut(
47+
content =
48+
"""
49+
#Generated by sentry-maven-plugin
50+
#Wed May 17 15:33:34 CEST 2023
51+
io.sentry.ProguardUuids=34077988-a0e5-4839-9618-7400e1616d1b
52+
io.sentry.bundle-ids=88ba82db-cd26-4c09-8b31-21461d286b68
53+
io.sentry.build-tool=maven
54+
""".trimIndent()
55+
)
56+
57+
val options = SentryOptions()
58+
59+
assertNotNull(sut.loadDebugMeta()) {
60+
DebugMetaPropertiesApplier.applyToOptions(options, it)
61+
}
62+
63+
assertEquals(options.bundleIds, setOf("88ba82db-cd26-4c09-8b31-21461d286b68"))
64+
assertEquals(options.proguardUuid, "34077988-a0e5-4839-9618-7400e1616d1b")
65+
}
66+
67+
@Test
68+
fun `reads multiple bundle IDs from assets into properties and can be applied to options`() {
69+
val sut = fixture.getSut(
70+
content =
71+
"""
72+
#Generated by sentry-maven-plugin
73+
#Wed May 17 15:33:34 CEST 2023
74+
io.sentry.ProguardUuids=34077988-a0e5-4839-9618-7400e1616d1b
75+
io.sentry.bundle-ids=88ba82db-cd26-4c09-8b31-21461d286b68,8d11a44a-facd-46c1-a49b-87d256227101
76+
io.sentry.build-tool=maven
77+
""".trimIndent()
78+
)
79+
80+
val options = SentryOptions()
81+
82+
assertNotNull(sut.loadDebugMeta()) {
83+
DebugMetaPropertiesApplier.applyToOptions(options, it)
84+
}
85+
86+
assertEquals(options.bundleIds, setOf("88ba82db-cd26-4c09-8b31-21461d286b68", "8d11a44a-facd-46c1-a49b-87d256227101"))
87+
assertEquals(options.proguardUuid, "34077988-a0e5-4839-9618-7400e1616d1b")
88+
}
89+
90+
@Test
91+
fun `when file does not exist, swallows exception and returns null`() {
92+
val sut = fixture.getSut(throws = true)
93+
94+
assertNull(sut.loadDebugMeta())
95+
}
96+
}

sentry/api/sentry.api

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1648,6 +1648,7 @@ public class io/sentry/SentryOptions {
16481648
public fun getConnectionTimeoutMillis ()I
16491649
public fun getContextTags ()Ljava/util/List;
16501650
public fun getDateProvider ()Lio/sentry/SentryDateProvider;
1651+
public fun getDebugMetaLoader ()Lio/sentry/internal/debugmeta/IDebugMetaLoader;
16511652
public fun getDiagnosticLevel ()Lio/sentry/SentryLevel;
16521653
public fun getDist ()Ljava/lang/String;
16531654
public fun getDistinctId ()Ljava/lang/String;
@@ -1740,6 +1741,7 @@ public class io/sentry/SentryOptions {
17401741
public fun setConnectionTimeoutMillis (I)V
17411742
public fun setDateProvider (Lio/sentry/SentryDateProvider;)V
17421743
public fun setDebug (Z)V
1744+
public fun setDebugMetaLoader (Lio/sentry/internal/debugmeta/IDebugMetaLoader;)V
17431745
public fun setDiagnosticLevel (Lio/sentry/SentryLevel;)V
17441746
public fun setDist (Ljava/lang/String;)V
17451747
public fun setDistinctId (Ljava/lang/String;)V
@@ -2653,6 +2655,20 @@ public final class io/sentry/instrumentation/file/SentryFileWriter : java/io/Out
26532655
public fun <init> (Ljava/lang/String;Z)V
26542656
}
26552657

2658+
public abstract interface class io/sentry/internal/debugmeta/IDebugMetaLoader {
2659+
public abstract fun loadDebugMeta ()Ljava/util/Properties;
2660+
}
2661+
2662+
public final class io/sentry/internal/debugmeta/NoOpDebugMetaLoader : io/sentry/internal/debugmeta/IDebugMetaLoader {
2663+
public static fun getInstance ()Lio/sentry/internal/debugmeta/NoOpDebugMetaLoader;
2664+
public fun loadDebugMeta ()Ljava/util/Properties;
2665+
}
2666+
2667+
public final class io/sentry/internal/debugmeta/ResourcesDebugMetaLoader : io/sentry/internal/debugmeta/IDebugMetaLoader {
2668+
public fun <init> (Lio/sentry/ILogger;)V
2669+
public fun loadDebugMeta ()Ljava/util/Properties;
2670+
}
2671+
26562672
public abstract interface class io/sentry/internal/gestures/GestureTargetLocator {
26572673
public abstract fun locate (Ljava/lang/Object;FFLio/sentry/internal/gestures/UiElement$Type;)Lio/sentry/internal/gestures/UiElement;
26582674
}
@@ -4006,6 +4022,12 @@ public abstract interface class io/sentry/util/CollectionUtils$Predicate {
40064022
public abstract fun test (Ljava/lang/Object;)Z
40074023
}
40084024

4025+
public final class io/sentry/util/DebugMetaPropertiesApplier {
4026+
public static field DEBUG_META_PROPERTIES_FILENAME Ljava/lang/String;
4027+
public fun <init> ()V
4028+
public static fun applyToOptions (Lio/sentry/SentryOptions;Ljava/util/Properties;)V
4029+
}
4030+
40094031
public final class io/sentry/util/ExceptionUtils {
40104032
public fun <init> ()V
40114033
public static fun findRootCause (Ljava/lang/Throwable;)Ljava/lang/Throwable;

sentry/src/main/java/io/sentry/Sentry.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import io.sentry.cache.EnvelopeCache;
44
import io.sentry.cache.IEnvelopeCache;
55
import io.sentry.config.PropertiesProviderFactory;
6+
import io.sentry.internal.debugmeta.NoOpDebugMetaLoader;
7+
import io.sentry.internal.debugmeta.ResourcesDebugMetaLoader;
68
import io.sentry.internal.modules.CompositeModulesLoader;
79
import io.sentry.internal.modules.IModulesLoader;
810
import io.sentry.internal.modules.ManifestModulesLoader;
@@ -11,6 +13,7 @@
1113
import io.sentry.protocol.SentryId;
1214
import io.sentry.protocol.User;
1315
import io.sentry.transport.NoOpEnvelopeCache;
16+
import io.sentry.util.DebugMetaPropertiesApplier;
1417
import io.sentry.util.FileUtils;
1518
import io.sentry.util.thread.IMainThreadChecker;
1619
import io.sentry.util.thread.MainThreadChecker;
@@ -19,6 +22,7 @@
1922
import java.lang.reflect.InvocationTargetException;
2023
import java.util.Arrays;
2124
import java.util.List;
25+
import java.util.Properties;
2226
import java.util.concurrent.RejectedExecutionException;
2327
import org.jetbrains.annotations.ApiStatus;
2428
import org.jetbrains.annotations.NotNull;
@@ -363,6 +367,12 @@ private static boolean initConfigurations(final @NotNull SentryOptions options)
363367
options.getLogger()));
364368
}
365369

370+
if (options.getDebugMetaLoader() instanceof NoOpDebugMetaLoader) {
371+
options.setDebugMetaLoader(new ResourcesDebugMetaLoader(options.getLogger()));
372+
}
373+
final @Nullable Properties properties = options.getDebugMetaLoader().loadDebugMeta();
374+
DebugMetaPropertiesApplier.applyToOptions(options, properties);
375+
366376
final IMainThreadChecker mainThreadChecker = options.getMainThreadChecker();
367377
// only override the MainThreadChecker if it's not already set by Android
368378
if (mainThreadChecker instanceof NoOpMainThreadChecker) {

0 commit comments

Comments
 (0)