Skip to content

Commit 629a327

Browse files
authored
Merge 7982674 into 84f0ef1
2 parents 84f0ef1 + 7982674 commit 629a327

File tree

6 files changed

+104
-86
lines changed

6 files changed

+104
-86
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
### Fixes
6+
7+
- Fix ensure all options are processed before integrations are loaded ([#2377](https://github.com/getsentry/sentry-java/pull/2377))
8+
39
## 6.7.1
410

511
### Fixes

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

Lines changed: 30 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import android.content.pm.PackageInfo;
88
import android.content.res.AssetManager;
99
import android.os.Build;
10+
import androidx.annotation.NonNull;
1011
import io.sentry.ILogger;
1112
import io.sentry.SendFireAndForgetEnvelopeSender;
1213
import io.sentry.SendFireAndForgetOutboxSender;
@@ -24,6 +25,7 @@
2425
import java.util.Properties;
2526
import org.jetbrains.annotations.NotNull;
2627
import org.jetbrains.annotations.Nullable;
28+
import org.jetbrains.annotations.TestOnly;
2729

2830
/**
2931
* Android Options initializer, it reads configurations from AndroidManifest and sets to the
@@ -41,35 +43,10 @@ private AndroidOptionsInitializer() {}
4143
* @param options the SentryAndroidOptions
4244
* @param context the Application context
4345
*/
44-
static void init(final @NotNull SentryAndroidOptions options, final @NotNull Context context) {
45-
Objects.requireNonNull(context, "The application context is required.");
46-
Objects.requireNonNull(options, "The options object is required.");
47-
48-
init(options, context, new AndroidLogger(), false, false);
49-
}
50-
51-
/**
52-
* Init method of the Android Options initializer
53-
*
54-
* @param options the SentryAndroidOptions
55-
* @param context the Application context
56-
* @param logger the ILogger interface
57-
* @param isFragmentAvailable whether the Fragment integration is available on the classpath
58-
* @param isTimberAvailable whether the Timber integration is available on the classpath
59-
*/
60-
static void init(
61-
final @NotNull SentryAndroidOptions options,
62-
@NotNull Context context,
63-
final @NotNull ILogger logger,
64-
final boolean isFragmentAvailable,
65-
final boolean isTimberAvailable) {
66-
init(
67-
options,
68-
context,
69-
logger,
70-
new BuildInfoProvider(logger),
71-
isFragmentAvailable,
72-
isTimberAvailable);
46+
static void loadDefaultAndMetadataOptions(
47+
final @NotNull SentryAndroidOptions options, @NotNull Context context) {
48+
final ILogger logger = new AndroidLogger();
49+
loadDefaultAndMetadataOptions(options, context, logger, new BuildInfoProvider(logger));
7350
}
7451

7552
/**
@@ -79,45 +56,12 @@ static void init(
7956
* @param context the Application context
8057
* @param logger the ILogger interface
8158
* @param buildInfoProvider the BuildInfoProvider interface
82-
* @param isFragmentAvailable whether the Fragment integration is available on the classpath
83-
* @param isTimberAvailable whether the Timber integration is available on the classpath
8459
*/
85-
static void init(
60+
static void loadDefaultAndMetadataOptions(
8661
final @NotNull SentryAndroidOptions options,
8762
@NotNull Context context,
8863
final @NotNull ILogger logger,
89-
final @NotNull BuildInfoProvider buildInfoProvider,
90-
final boolean isFragmentAvailable,
91-
final boolean isTimberAvailable) {
92-
init(
93-
options,
94-
context,
95-
logger,
96-
buildInfoProvider,
97-
new LoadClass(),
98-
isFragmentAvailable,
99-
isTimberAvailable);
100-
}
101-
102-
/**
103-
* Init method of the Android Options initializer
104-
*
105-
* @param options the SentryAndroidOptions
106-
* @param context the Application context
107-
* @param logger the ILogger interface
108-
* @param buildInfoProvider the BuildInfoProvider interface
109-
* @param loadClass the LoadClass wrapper
110-
* @param isFragmentAvailable whether the Fragment integration is available on the classpath
111-
* @param isTimberAvailable whether the Timber integration is available on the classpath
112-
*/
113-
static void init(
114-
final @NotNull SentryAndroidOptions options,
115-
@NotNull Context context,
116-
final @NotNull ILogger logger,
117-
final @NotNull BuildInfoProvider buildInfoProvider,
118-
final @NotNull LoadClass loadClass,
119-
final boolean isFragmentAvailable,
120-
final boolean isTimberAvailable) {
64+
final @NotNull BuildInfoProvider buildInfoProvider) {
12165
Objects.requireNonNull(context, "The context is required.");
12266

12367
// it returns null if ContextImpl, so let's check for nullability
@@ -135,6 +79,28 @@ static void init(
13579
initializeCacheDirs(context, options);
13680
options.setEnvelopeDiskCache(new AndroidEnvelopeCache(options));
13781

82+
readDefaultOptionValues(options, context, buildInfoProvider);
83+
}
84+
85+
@TestOnly
86+
static void initializeIntegrationsAndProcessors(
87+
@NonNull SentryAndroidOptions options, @NonNull Context context) {
88+
initializeIntegrationsAndProcessors(
89+
options,
90+
context,
91+
new BuildInfoProvider(new AndroidLogger()),
92+
new LoadClass(),
93+
false,
94+
false);
95+
}
96+
97+
static void initializeIntegrationsAndProcessors(
98+
@NonNull SentryAndroidOptions options,
99+
@NonNull Context context,
100+
@NonNull BuildInfoProvider buildInfoProvider,
101+
@NonNull LoadClass loadClass,
102+
boolean isFragmentAvailable,
103+
boolean isTimberAvailable) {
138104
final ActivityFramesTracker activityFramesTracker =
139105
new ActivityFramesTracker(loadClass, options);
140106

@@ -147,8 +113,6 @@ static void init(
147113
isFragmentAvailable,
148114
isTimberAvailable);
149115

150-
readDefaultOptionValues(options, context, buildInfoProvider);
151-
152116
options.addEventProcessor(
153117
new DefaultAndroidEventProcessor(context, buildInfoProvider, options));
154118
options.addEventProcessor(new PerformanceAndroidEventProcessor(options, activityFramesTracker));

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

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -102,11 +102,24 @@ public static synchronized void init(
102102
(isTimberUpstreamAvailable
103103
&& classLoader.isClassAvailable(SENTRY_TIMBER_INTEGRATION_CLASS_NAME, options));
104104

105-
AndroidOptionsInitializer.init(
106-
options, context, logger, isFragmentAvailable, isTimberAvailable);
105+
final BuildInfoProvider buildInfoProvider = new BuildInfoProvider(logger);
106+
final LoadClass loadClass = new LoadClass();
107+
108+
AndroidOptionsInitializer.loadDefaultAndMetadataOptions(
109+
options, context, logger, buildInfoProvider);
110+
107111
configuration.configure(options);
108-
deduplicateIntegrations(options, isFragmentAvailable, isTimberAvailable);
109112
resetEnvelopeCacheIfNeeded(options);
113+
114+
AndroidOptionsInitializer.initializeIntegrationsAndProcessors(
115+
options,
116+
context,
117+
buildInfoProvider,
118+
loadClass,
119+
isFragmentAvailable,
120+
isTimberAvailable);
121+
122+
deduplicateIntegrations(options, isFragmentAvailable, isTimberAvailable);
110123
},
111124
true);
112125
} catch (IllegalAccessException e) {
@@ -132,7 +145,8 @@ public static synchronized void init(
132145

133146
/**
134147
* Deduplicate potentially duplicated Fragment and Timber integrations, which can be added
135-
* automatically by our SDK as well as by the user. The user's ones win over ours.
148+
* automatically by our SDK as well as by the user. The user's ones (provided first in the
149+
* options.integrations list) win over ours.
136150
*
137151
* @param options SentryOptions to retrieve integrations from
138152
*/
@@ -158,14 +172,14 @@ private static void deduplicateIntegrations(
158172
}
159173

160174
if (fragmentIntegrations.size() > 1) {
161-
for (int i = 0; i < fragmentIntegrations.size() - 1; i++) {
175+
for (int i = 1; i < fragmentIntegrations.size(); i++) {
162176
final Integration integration = fragmentIntegrations.get(i);
163177
options.getIntegrations().remove(integration);
164178
}
165179
}
166180

167181
if (timberIntegrations.size() > 1) {
168-
for (int i = 0; i < timberIntegrations.size() - 1; i++) {
182+
for (int i = 1; i < timberIntegrations.size(); i++) {
169183
final Integration integration = timberIntegrations.get(i);
170184
options.getIntegrations().remove(integration);
171185
}

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

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,12 @@ class AndroidOptionsInitializerTest {
5252
whenever(mockContext.applicationContext.cacheDir).thenReturn(file)
5353
}
5454
mockContext.configureContext()
55+
AndroidOptionsInitializer.loadDefaultAndMetadataOptions(
56+
sentryOptions,
57+
if (useRealContext) context else mockContext
58+
)
5559
sentryOptions.configureOptions()
56-
AndroidOptionsInitializer.init(
60+
AndroidOptionsInitializer.initializeIntegrationsAndProcessors(
5761
sentryOptions,
5862
if (useRealContext) context else mockContext
5963
)
@@ -71,12 +75,19 @@ class AndroidOptionsInitializerTest {
7175
putString(ManifestMetadataReader.DSN, "https://[email protected]/123")
7276
}
7377
)
74-
sentryOptions.setDebug(true)
75-
AndroidOptionsInitializer.init(
78+
sentryOptions.isDebug = true
79+
val buildInfo = createBuildInfo(minApi)
80+
81+
AndroidOptionsInitializer.loadDefaultAndMetadataOptions(
7682
sentryOptions,
77-
mockContext,
83+
context,
7884
logger,
79-
createBuildInfo(minApi),
85+
buildInfo
86+
)
87+
AndroidOptionsInitializer.initializeIntegrationsAndProcessors(
88+
sentryOptions,
89+
context,
90+
buildInfo,
8091
createClassMock(classToLoad),
8192
isFragmentAvailable,
8293
isTimberAvailable
@@ -381,9 +392,13 @@ class AndroidOptionsInitializerTest {
381392

382393
@Test
383394
fun `When Activity Frames Tracking is enabled, the Activity Frames Tracker should be available`() {
384-
fixture.initSut(hasAppContext = true, configureOptions = {
385-
isEnableFramesTracking = true
386-
})
395+
fixture.initSut(
396+
hasAppContext = true,
397+
useRealContext = true,
398+
configureOptions = {
399+
isEnableFramesTracking = true
400+
}
401+
)
387402

388403
val activityLifeCycleIntegration = fixture.sentryOptions.integrations
389404
.first { it is ActivityLifecycleIntegration }
@@ -395,7 +410,7 @@ class AndroidOptionsInitializerTest {
395410

396411
@Test
397412
fun `When Frames Tracking is disabled, the Activity Frames Tracker should not be available`() {
398-
fixture.initSut(hasAppContext = true, configureOptions = {
413+
fixture.initSut(hasAppContext = true, useRealContext = true, configureOptions = {
399414
isEnableFramesTracking = false
400415
})
401416

@@ -410,9 +425,13 @@ class AndroidOptionsInitializerTest {
410425
@Test
411426
fun `When Frames Tracking is initially disabled, but enabled via configureOptions it should be available`() {
412427
fixture.sentryOptions.isEnableFramesTracking = false
413-
fixture.initSut(hasAppContext = true, configureOptions = {
414-
isEnableFramesTracking = true
415-
})
428+
fixture.initSut(
429+
hasAppContext = true,
430+
useRealContext = true,
431+
configureOptions = {
432+
isEnableFramesTracking = true
433+
}
434+
)
416435

417436
val activityLifeCycleIntegration = fixture.sentryOptions.integrations
418437
.first { it is ActivityLifecycleIntegration }

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

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,21 @@ class AndroidTransactionProfilerTest {
7171
@BeforeTest
7272
fun `set up`() {
7373
context = ApplicationProvider.getApplicationContext()
74-
AndroidOptionsInitializer.init(fixture.options, context, fixture.mockLogger, false, false)
74+
val buildInfoProvider = BuildInfoProvider(fixture.mockLogger)
75+
AndroidOptionsInitializer.loadDefaultAndMetadataOptions(
76+
fixture.options,
77+
context,
78+
fixture.mockLogger,
79+
buildInfoProvider
80+
)
81+
AndroidOptionsInitializer.initializeIntegrationsAndProcessors(
82+
fixture.options,
83+
context,
84+
buildInfoProvider,
85+
LoadClass(),
86+
false,
87+
false
88+
)
7589
// Profiler doesn't start if the folder doesn't exists.
7690
// Usually it's generated when calling Sentry.init, but for tests we can create it manually.
7791
File(fixture.options.profilingTracesDirPath!!).mkdirs()

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,8 @@ class SentryInitProviderTest {
132132
val mockContext = ContextUtilsTest.mockMetaData(metaData = metaData)
133133
metaData.putBoolean(ManifestMetadataReader.NDK_ENABLE, false)
134134

135-
AndroidOptionsInitializer.init(sentryOptions, mockContext)
135+
AndroidOptionsInitializer.loadDefaultAndMetadataOptions(sentryOptions, mockContext)
136+
AndroidOptionsInitializer.initializeIntegrationsAndProcessors(sentryOptions, mockContext)
136137

137138
assertFalse(sentryOptions.isEnableNdk)
138139
}

0 commit comments

Comments
 (0)