diff --git a/sentry/api/sentry.api b/sentry/api/sentry.api index 376d004c5ac..252c5781fdf 100644 --- a/sentry/api/sentry.api +++ b/sentry/api/sentry.api @@ -2867,6 +2867,7 @@ public final class io/sentry/SentryInstantDateProvider : io/sentry/SentryDatePro public final class io/sentry/SentryIntegrationPackageStorage { public fun addIntegration (Ljava/lang/String;)V public fun addPackage (Ljava/lang/String;Ljava/lang/String;)V + public fun checkForMixedVersions (Lio/sentry/ILogger;)Z public fun clearStorage ()V public static fun getInstance ()Lio/sentry/SentryIntegrationPackageStorage; public fun getIntegrations ()Ljava/util/Set; diff --git a/sentry/src/main/java/io/sentry/SentryClient.java b/sentry/src/main/java/io/sentry/SentryClient.java index c98970306b7..bb8c2b4605f 100644 --- a/sentry/src/main/java/io/sentry/SentryClient.java +++ b/sentry/src/main/java/io/sentry/SentryClient.java @@ -767,6 +767,9 @@ public void captureSession(final @NotNull Session session, final @Nullable Hint .log(SentryLevel.ERROR, "The BeforeEnvelope callback threw an exception.", e); } } + + SentryIntegrationPackageStorage.getInstance().checkForMixedVersions(options.getLogger()); + if (hint == null) { transport.send(envelope); } else { diff --git a/sentry/src/main/java/io/sentry/SentryIntegrationPackageStorage.java b/sentry/src/main/java/io/sentry/SentryIntegrationPackageStorage.java index 16534291448..1ceba1dba3a 100644 --- a/sentry/src/main/java/io/sentry/SentryIntegrationPackageStorage.java +++ b/sentry/src/main/java/io/sentry/SentryIntegrationPackageStorage.java @@ -15,6 +15,9 @@ public final class SentryIntegrationPackageStorage { private static volatile @Nullable SentryIntegrationPackageStorage INSTANCE; private static final @NotNull AutoClosableReentrantLock staticLock = new AutoClosableReentrantLock(); + private static volatile @Nullable Boolean mixedVersionsDetected = null; + private static final @NotNull AutoClosableReentrantLock mixedVersionsLock = + new AutoClosableReentrantLock(); public static @NotNull SentryIntegrationPackageStorage getInstance() { if (INSTANCE == null) { @@ -64,12 +67,48 @@ public void addPackage(final @NotNull String name, final @NotNull String version SentryPackage newPackage = new SentryPackage(name, version); packages.add(newPackage); + try (final @NotNull ISentryLifecycleToken ignored = mixedVersionsLock.acquire()) { + mixedVersionsDetected = null; + } } public @NotNull Set getPackages() { return packages; } + public boolean checkForMixedVersions(final @NotNull ILogger logger) { + final @Nullable Boolean mixedVersionsDetectedBefore = mixedVersionsDetected; + if (mixedVersionsDetectedBefore != null) { + return mixedVersionsDetectedBefore; + } + try (final @NotNull ISentryLifecycleToken ignored = mixedVersionsLock.acquire()) { + final @NotNull String sdkVersion = BuildConfig.VERSION_NAME; + boolean mixedVersionsDetectedThisCheck = false; + + for (SentryPackage pkg : packages) { + if (pkg.getName().startsWith("maven:io.sentry:") + && !sdkVersion.equalsIgnoreCase(pkg.getVersion())) { + logger.log( + SentryLevel.ERROR, + "The Sentry SDK has been configured with mixed versions. Expected %s to match core SDK version %s but was %s", + pkg.getName(), + sdkVersion, + pkg.getVersion()); + mixedVersionsDetectedThisCheck = true; + } + } + + if (mixedVersionsDetectedThisCheck) { + logger.log(SentryLevel.ERROR, "^^^^^^^^^^^^^^^^^^^^^^^^^^^^"); + logger.log(SentryLevel.ERROR, "^^^^^^^^^^^^^^^^^^^^^^^^^^^^"); + logger.log(SentryLevel.ERROR, "^^^^^^^^^^^^^^^^^^^^^^^^^^^^"); + logger.log(SentryLevel.ERROR, "^^^^^^^^^^^^^^^^^^^^^^^^^^^^"); + } + mixedVersionsDetected = mixedVersionsDetectedThisCheck; + return mixedVersionsDetectedThisCheck; + } + } + @TestOnly public void clearStorage() { integrations.clear();