Skip to content

Commit ee4e8d3

Browse files
authored
Merge 1169294 into 5583fa5
2 parents 5583fa5 + 1169294 commit ee4e8d3

File tree

12 files changed

+269
-39
lines changed

12 files changed

+269
-39
lines changed

sentry-spring-boot-jakarta/src/test/kotlin/io/sentry/spring/boot/jakarta/SentryAutoConfigurationTest.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ class SentryAutoConfigurationTest {
172172
"sentry.send-modules=false",
173173
"sentry.ignored-checkins=slug1,slugB",
174174
"sentry.enable-backpressure-handling=false",
175+
"sentry.force-init=true",
175176
"sentry.cron.default-checkin-margin=10",
176177
"sentry.cron.default-max-runtime=30",
177178
"sentry.cron.default-timezone=America/New_York",
@@ -209,6 +210,7 @@ class SentryAutoConfigurationTest {
209210
assertThat(options.isSendModules).isEqualTo(false)
210211
assertThat(options.ignoredCheckIns).containsOnly("slug1", "slugB")
211212
assertThat(options.isEnableBackpressureHandling).isEqualTo(false)
213+
assertThat(options.isForceInit).isEqualTo(true)
212214
assertThat(options.cron).isNotNull
213215
assertThat(options.cron!!.defaultCheckinMargin).isEqualTo(10L)
214216
assertThat(options.cron!!.defaultMaxRuntime).isEqualTo(30L)

sentry-spring-boot/src/test/kotlin/io/sentry/spring/boot/SentryAutoConfigurationTest.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ class SentryAutoConfigurationTest {
171171
"sentry.send-modules=false",
172172
"sentry.ignored-checkins=slug1,slugB",
173173
"sentry.enable-backpressure-handling=false",
174+
"sentry.force-init=true",
174175
"sentry.cron.default-checkin-margin=10",
175176
"sentry.cron.default-max-runtime=30",
176177
"sentry.cron.default-timezone=America/New_York",
@@ -208,6 +209,7 @@ class SentryAutoConfigurationTest {
208209
assertThat(options.isSendModules).isEqualTo(false)
209210
assertThat(options.ignoredCheckIns).containsOnly("slug1", "slugB")
210211
assertThat(options.isEnableBackpressureHandling).isEqualTo(false)
212+
assertThat(options.isForceInit).isEqualTo(true)
211213
assertThat(options.cron).isNotNull
212214
assertThat(options.cron!!.defaultCheckinMargin).isEqualTo(10L)
213215
assertThat(options.cron!!.defaultMaxRuntime).isEqualTo(30L)

sentry/api/sentry.api

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,7 @@ public final class io/sentry/ExternalOptions {
459459
public fun isEnableBackpressureHandling ()Ljava/lang/Boolean;
460460
public fun isEnablePrettySerializationOutput ()Ljava/lang/Boolean;
461461
public fun isEnabled ()Ljava/lang/Boolean;
462+
public fun isForceInit ()Ljava/lang/Boolean;
462463
public fun isSendDefaultPii ()Ljava/lang/Boolean;
463464
public fun isSendModules ()Ljava/lang/Boolean;
464465
public fun setCron (Lio/sentry/SentryOptions$Cron;)V
@@ -472,6 +473,7 @@ public final class io/sentry/ExternalOptions {
472473
public fun setEnableUncaughtExceptionHandler (Ljava/lang/Boolean;)V
473474
public fun setEnabled (Ljava/lang/Boolean;)V
474475
public fun setEnvironment (Ljava/lang/String;)V
476+
public fun setForceInit (Ljava/lang/Boolean;)V
475477
public fun setIdleTimeout (Ljava/lang/Long;)V
476478
public fun setIgnoredCheckIns (Ljava/util/List;)V
477479
public fun setMaxRequestBodySize (Lio/sentry/SentryOptions$RequestSize;)V
@@ -1028,6 +1030,16 @@ public abstract interface class io/sentry/ITransportFactory {
10281030
public abstract fun create (Lio/sentry/SentryOptions;Lio/sentry/RequestDetails;)Lio/sentry/transport/ITransport;
10291031
}
10301032

1033+
public final class io/sentry/InitPriority : java/lang/Enum {
1034+
public static final field HIGH Lio/sentry/InitPriority;
1035+
public static final field HIGHEST Lio/sentry/InitPriority;
1036+
public static final field LOW Lio/sentry/InitPriority;
1037+
public static final field LOWEST Lio/sentry/InitPriority;
1038+
public static final field MEDIUM Lio/sentry/InitPriority;
1039+
public static fun valueOf (Ljava/lang/String;)Lio/sentry/InitPriority;
1040+
public static fun values ()[Lio/sentry/InitPriority;
1041+
}
1042+
10311043
public final class io/sentry/Instrumenter : java/lang/Enum {
10321044
public static final field OTEL Lio/sentry/Instrumenter;
10331045
public static final field SENTRY Lio/sentry/Instrumenter;
@@ -2706,6 +2718,7 @@ public class io/sentry/SentryOptions {
27062718
public fun getIgnoredSpanOrigins ()Ljava/util/List;
27072719
public fun getInAppExcludes ()Ljava/util/List;
27082720
public fun getInAppIncludes ()Ljava/util/List;
2721+
public fun getInitPriority ()Lio/sentry/InitPriority;
27092722
public fun getInstrumenter ()Lio/sentry/Instrumenter;
27102723
public fun getIntegrations ()Ljava/util/List;
27112724
public fun getInternalTracesSampler ()Lio/sentry/TracesSampler;
@@ -2775,6 +2788,7 @@ public class io/sentry/SentryOptions {
27752788
public fun isEnableUserInteractionBreadcrumbs ()Z
27762789
public fun isEnableUserInteractionTracing ()Z
27772790
public fun isEnabled ()Z
2791+
public fun isForceInit ()Z
27782792
public fun isPrintUncaughtStackTrace ()Z
27792793
public fun isProfilingEnabled ()Z
27802794
public fun isSendClientReports ()Z
@@ -2828,10 +2842,12 @@ public class io/sentry/SentryOptions {
28282842
public fun setEnvironment (Ljava/lang/String;)V
28292843
public fun setExecutorService (Lio/sentry/ISentryExecutorService;)V
28302844
public fun setFlushTimeoutMillis (J)V
2845+
public fun setForceInit (Z)V
28312846
public fun setGestureTargetLocators (Ljava/util/List;)V
28322847
public fun setIdleTimeout (Ljava/lang/Long;)V
28332848
public fun setIgnoredCheckIns (Ljava/util/List;)V
28342849
public fun setIgnoredSpanOrigins (Ljava/util/List;)V
2850+
public fun setInitPriority (Lio/sentry/InitPriority;)V
28352851
public fun setInstrumenter (Lio/sentry/Instrumenter;)V
28362852
public fun setLogger (Lio/sentry/ILogger;)V
28372853
public fun setMainThreadChecker (Lio/sentry/util/thread/IMainThreadChecker;)V
@@ -5548,6 +5564,11 @@ public final class io/sentry/util/HttpUtils {
55485564
public static fun isSecurityCookie (Ljava/lang/String;Ljava/util/List;)Z
55495565
}
55505566

5567+
public final class io/sentry/util/InitUtil {
5568+
public fun <init> ()V
5569+
public static fun shouldInit (Lio/sentry/SentryOptions;Lio/sentry/SentryOptions;Z)Z
5570+
}
5571+
55515572
public final class io/sentry/util/IntegrationUtils {
55525573
public fun <init> ()V
55535574
public static fun addIntegrationToSdkVersion (Ljava/lang/Class;)V

sentry/src/main/java/io/sentry/ExternalOptions.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public final class ExternalOptions {
5151
private @Nullable Boolean sendModules;
5252
private @Nullable Boolean sendDefaultPii;
5353
private @Nullable Boolean enableBackpressureHandling;
54+
private @Nullable Boolean forceInit;
5455

5556
private @Nullable SentryOptions.Cron cron;
5657

@@ -73,6 +74,7 @@ public final class ExternalOptions {
7374
options.setDebug(propertiesProvider.getBooleanProperty("debug"));
7475
options.setEnableDeduplication(propertiesProvider.getBooleanProperty("enable-deduplication"));
7576
options.setSendClientReports(propertiesProvider.getBooleanProperty("send-client-reports"));
77+
options.setForceInit(propertiesProvider.getBooleanProperty("force-init"));
7678
final String maxRequestBodySize = propertiesProvider.getProperty("max-request-body-size");
7779
if (maxRequestBodySize != null) {
7880
options.setMaxRequestBodySize(
@@ -451,6 +453,14 @@ public void setEnableBackpressureHandling(final @Nullable Boolean enableBackpres
451453
return enableBackpressureHandling;
452454
}
453455

456+
public void setForceInit(final @Nullable Boolean forceInit) {
457+
this.forceInit = forceInit;
458+
}
459+
460+
public @Nullable Boolean isForceInit() {
461+
return forceInit;
462+
}
463+
454464
@ApiStatus.Experimental
455465
public @Nullable SentryOptions.Cron getCron() {
456466
return cron;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package io.sentry;
2+
3+
import org.jetbrains.annotations.ApiStatus;
4+
5+
@ApiStatus.Internal
6+
public enum InitPriority {
7+
LOWEST,
8+
LOW,
9+
MEDIUM,
10+
HIGH,
11+
HIGHEST;
12+
}

sentry/src/main/java/io/sentry/Scope.java

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1055,17 +1055,15 @@ public void setSpanContext(
10551055
@ApiStatus.Internal
10561056
@Override
10571057
public void replaceOptions(final @NotNull SentryOptions options) {
1058-
if (!getClient().isEnabled()) {
1059-
this.options = options;
1060-
final Queue<Breadcrumb> oldBreadcrumbs = breadcrumbs;
1061-
breadcrumbs = createBreadcrumbsList(options.getMaxBreadcrumbs());
1062-
for (Breadcrumb breadcrumb : oldBreadcrumbs) {
1063-
/*
1064-
this should trigger beforeBreadcrumb
1065-
and notify observers for breadcrumbs added before options where customized in Sentry.init
1066-
*/
1067-
addBreadcrumb(breadcrumb);
1068-
}
1058+
this.options = options;
1059+
final Queue<Breadcrumb> oldBreadcrumbs = breadcrumbs;
1060+
breadcrumbs = createBreadcrumbsList(options.getMaxBreadcrumbs());
1061+
for (Breadcrumb breadcrumb : oldBreadcrumbs) {
1062+
/*
1063+
this should trigger beforeBreadcrumb
1064+
and notify observers for breadcrumbs added before options where customized in Sentry.init
1065+
*/
1066+
addBreadcrumb(breadcrumb);
10691067
}
10701068
}
10711069

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

Lines changed: 43 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import io.sentry.transport.NoOpEnvelopeCache;
1818
import io.sentry.util.DebugMetaPropertiesApplier;
1919
import io.sentry.util.FileUtils;
20+
import io.sentry.util.InitUtil;
2021
import io.sentry.util.LoadClass;
2122
import io.sentry.util.Platform;
2223
import io.sentry.util.thread.IMainThreadChecker;
@@ -279,43 +280,55 @@ private static synchronized void init(
279280
"Sentry has been already initialized. Previous configuration will be overwritten.");
280281
}
281282

282-
if (!initConfigurations(options)) {
283+
if (!preInitConfigurations(options)) {
283284
return;
284285
}
285286

286287
options.getLogger().log(SentryLevel.INFO, "GlobalHubMode: '%s'", String.valueOf(globalHubMode));
287288
Sentry.globalHubMode = globalHubMode;
288-
globalScope.replaceOptions(options);
289+
final boolean shouldInit = InitUtil.shouldInit(globalScope.getOptions(), options, isEnabled());
290+
if (shouldInit) {
291+
globalScope.replaceOptions(options);
289292

290-
final IScopes scopes = getCurrentScopes();
291-
final IScope rootScope = new Scope(options);
292-
final IScope rootIsolationScope = new Scope(options);
293-
rootScopes = new Scopes(rootScope, rootIsolationScope, globalScope, "Sentry.init");
293+
final IScopes scopes = getCurrentScopes();
294+
final IScope rootScope = new Scope(options);
295+
final IScope rootIsolationScope = new Scope(options);
296+
rootScopes = new Scopes(rootScope, rootIsolationScope, globalScope, "Sentry.init");
294297

295-
getScopesStorage().set(rootScopes);
298+
getScopesStorage().set(rootScopes);
296299

297-
scopes.close(true);
298-
globalScope.bindClient(new SentryClient(rootScopes.getOptions()));
300+
scopes.close(true);
299301

300-
// If the executorService passed in the init is the same that was previously closed, we have to
301-
// set a new one
302-
if (options.getExecutorService().isClosed()) {
303-
options.setExecutorService(new SentryExecutorService());
304-
}
302+
initConfigurations(options);
305303

306-
// when integrations are registered on Scopes ctor and async integrations are fired,
307-
// it might and actually happened that integrations called captureSomething
308-
// and Scopes was still NoOp.
309-
// Registering integrations here make sure that Scopes is already created.
310-
for (final Integration integration : options.getIntegrations()) {
311-
integration.register(ScopesAdapter.getInstance(), options);
312-
}
304+
globalScope.bindClient(new SentryClient(options));
305+
306+
// If the executorService passed in the init is the same that was previously closed, we have
307+
// to
308+
// set a new one
309+
if (options.getExecutorService().isClosed()) {
310+
options.setExecutorService(new SentryExecutorService());
311+
}
312+
// when integrations are registered on Scopes ctor and async integrations are fired,
313+
// it might and actually happened that integrations called captureSomething
314+
// and Scopes was still NoOp.
315+
// Registering integrations here make sure that Scopes is already created.
316+
for (final Integration integration : options.getIntegrations()) {
317+
integration.register(ScopesAdapter.getInstance(), options);
318+
}
313319

314-
notifyOptionsObservers(options);
320+
notifyOptionsObservers(options);
315321

316-
finalizePreviousSession(options, ScopesAdapter.getInstance());
322+
finalizePreviousSession(options, ScopesAdapter.getInstance());
317323

318-
handleAppStartProfilingConfig(options, options.getExecutorService());
324+
handleAppStartProfilingConfig(options, options.getExecutorService());
325+
} else {
326+
options
327+
.getLogger()
328+
.log(
329+
SentryLevel.WARNING,
330+
"This init call has been ignored due to priority being too low.");
331+
}
319332
}
320333

321334
@SuppressWarnings("FutureReturnValueIgnored")
@@ -419,8 +432,7 @@ private static void notifyOptionsObservers(final @NotNull SentryOptions options)
419432
}
420433
}
421434

422-
@SuppressWarnings("FutureReturnValueIgnored")
423-
private static boolean initConfigurations(final @NotNull SentryOptions options) {
435+
private static boolean preInitConfigurations(final @NotNull SentryOptions options) {
424436
if (options.isEnableExternalConfiguration()) {
425437
options.merge(ExternalOptions.from(PropertiesProviderFactory.create(), options.getLogger()));
426438
}
@@ -438,6 +450,11 @@ private static boolean initConfigurations(final @NotNull SentryOptions options)
438450
@SuppressWarnings("unused")
439451
final Dsn parsedDsn = new Dsn(dsn);
440452

453+
return true;
454+
}
455+
456+
@SuppressWarnings("FutureReturnValueIgnored")
457+
private static void initConfigurations(final @NotNull SentryOptions options) {
441458
ILogger logger = options.getLogger();
442459

443460
if (options.isDebug() && logger instanceof NoOpLogger) {
@@ -534,8 +551,6 @@ private static boolean initConfigurations(final @NotNull SentryOptions options)
534551
options.setBackpressureMonitor(new BackpressureMonitor(options, ScopesAdapter.getInstance()));
535552
options.getBackpressureMonitor().start();
536553
}
537-
538-
return true;
539554
}
540555

541556
/** Close the SDK */

sentry/src/main/java/io/sentry/SentryOptions.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,9 @@ public class SentryOptions {
489489

490490
private @NotNull ScopeType defaultScopeType = ScopeType.ISOLATION;
491491

492+
private @NotNull InitPriority initPriority = InitPriority.MEDIUM;
493+
private boolean forceInit = false;
494+
492495
/**
493496
* Adds an event processor
494497
*
@@ -2440,6 +2443,33 @@ public void setDefaultScopeType(final @NotNull ScopeType scopeType) {
24402443
return defaultScopeType;
24412444
}
24422445

2446+
@ApiStatus.Internal
2447+
public void setInitPriority(final @NotNull InitPriority initPriority) {
2448+
this.initPriority = initPriority;
2449+
}
2450+
2451+
@ApiStatus.Internal
2452+
public @NotNull InitPriority getInitPriority() {
2453+
return initPriority;
2454+
}
2455+
2456+
/**
2457+
* If set to true a call to Sentry.init (or SentryAndroid.init) will go through and replace
2458+
* previous options if there are any.
2459+
*
2460+
* <p>By default the SDK will check whether a previous call to Sentry.init has higher priority
2461+
* than the current one and decide whether to actually perform the init and replace options.
2462+
*
2463+
* @param forceInit true = replace previous init and options
2464+
*/
2465+
public void setForceInit(final boolean forceInit) {
2466+
this.forceInit = forceInit;
2467+
}
2468+
2469+
public boolean isForceInit() {
2470+
return forceInit;
2471+
}
2472+
24432473
/** The BeforeSend callback */
24442474
public interface BeforeSendCallback {
24452475

@@ -2562,6 +2592,7 @@ public SentryOptions() {
25622592
*/
25632593
private SentryOptions(final boolean empty) {
25642594
if (!empty) {
2595+
setInitPriority(InitPriority.LOWEST);
25652596
setSpanFactory(new DefaultSpanFactory());
25662597
// SentryExecutorService should be initialized before any
25672598
// SendCachedEventFireAndForgetIntegration
@@ -2636,6 +2667,9 @@ public void merge(final @NotNull ExternalOptions options) {
26362667
if (options.getSendClientReports() != null) {
26372668
setSendClientReports(options.getSendClientReports());
26382669
}
2670+
if (options.isForceInit() != null) {
2671+
setForceInit(options.isForceInit());
2672+
}
26392673
final Map<String, String> tags = new HashMap<>(options.getTags());
26402674
for (final Map.Entry<String, String> tag : tags.entrySet()) {
26412675
this.tags.put(tag.getKey(), tag.getValue());
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package io.sentry.util;
2+
3+
import io.sentry.SentryOptions;
4+
import org.jetbrains.annotations.ApiStatus;
5+
import org.jetbrains.annotations.NotNull;
6+
import org.jetbrains.annotations.Nullable;
7+
8+
@ApiStatus.Internal
9+
public final class InitUtil {
10+
public static boolean shouldInit(
11+
final @Nullable SentryOptions previousOptions,
12+
final @NotNull SentryOptions newOptions,
13+
final boolean isEnabled) {
14+
if (!isEnabled) {
15+
return true;
16+
}
17+
18+
if (previousOptions == null) {
19+
return true;
20+
}
21+
22+
if (newOptions.isForceInit()) {
23+
return true;
24+
}
25+
26+
return previousOptions.getInitPriority().ordinal() <= newOptions.getInitPriority().ordinal();
27+
}
28+
}

0 commit comments

Comments
 (0)