result = new AtomicReference<>(null);
- final CountDownLatch latch = new CountDownLatch(1);
-
- try {
- activity.runOnUiThread(
- () -> {
- try {
- result.set(buildViewHierarchy(activity));
- } finally {
- latch.countDown();
- }
- });
-
- if (!latch.await(MASKING_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
- options
- .getLogger()
- .log(
- SentryLevel.WARNING, "Timed out waiting for view hierarchy capture on main thread");
- return null;
- }
- } catch (Throwable e) {
- options.getLogger().log(SentryLevel.ERROR, "Failed to capture view hierarchy", e);
- return null;
- }
-
- return result.get();
- }
-
- private @Nullable ViewHierarchyNode buildViewHierarchy(final @NotNull Activity activity) {
- try {
- final @Nullable View rootView =
- activity.getWindow() != null
- && activity.getWindow().peekDecorView() != null
- && activity.getWindow().peekDecorView().getRootView() != null
- ? activity.getWindow().peekDecorView().getRootView()
- : null;
- if (rootView == null) {
- return null;
- }
-
- final ViewHierarchyNode rootNode =
- ViewHierarchyNode.Companion.fromView(rootView, null, 0, options.getScreenshot());
- ViewsKt.traverse(rootView, rootNode, options.getScreenshot(), options.getLogger(), null);
- return rootNode;
- } catch (Throwable e) {
- options.getLogger().log(SentryLevel.ERROR, "Failed to build view hierarchy", e);
- return null;
- }
- }
-
- private @Nullable Bitmap applyMasking(
- final @NotNull Bitmap screenshot, final @NotNull ViewHierarchyNode rootNode) {
- Bitmap mutableBitmap = screenshot;
- boolean createdCopy = false;
- try (final MaskRenderer maskRenderer = new MaskRenderer()) {
- // Make bitmap mutable if needed
- if (!screenshot.isMutable()) {
- mutableBitmap = screenshot.copy(Bitmap.Config.RGB_565, true);
- if (mutableBitmap == null) {
- screenshot.recycle();
- return null;
- }
- createdCopy = true;
- }
-
- maskRenderer.renderMasks(mutableBitmap, rootNode, null);
-
- // Recycle original if we created a copy
- if (createdCopy && !screenshot.isRecycled()) {
- screenshot.recycle();
- }
-
- return mutableBitmap;
- } catch (Throwable e) {
- options.getLogger().log(SentryLevel.ERROR, "Failed to mask screenshot", e);
- if (createdCopy) {
- if (!mutableBitmap.isRecycled()) {
- mutableBitmap.recycle();
- }
- }
- if (!screenshot.isRecycled()) {
- screenshot.recycle();
- }
- return null;
- }
- }
-
@Override
public @Nullable Long getOrder() {
return 10000L;
diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/SentryScreenshotOptions.java b/sentry-android-core/src/main/java/io/sentry/android/core/SentryScreenshotOptions.java
index 8680ed907d1..6e1cceb760b 100644
--- a/sentry-android-core/src/main/java/io/sentry/android/core/SentryScreenshotOptions.java
+++ b/sentry-android-core/src/main/java/io/sentry/android/core/SentryScreenshotOptions.java
@@ -10,7 +10,8 @@
* #setMaskAllText(boolean)} and/or {@link #setMaskAllImages(boolean)}.
*
* Note: Screenshot masking requires the {@code sentry-android-replay} module to be present at
- * runtime. If the replay module is not available, screenshots will be captured without masking.
+ * runtime. If masking is enabled but the replay module is not available, no screenshot is captured
+ * to avoid leaking sensitive data.
*/
public final class SentryScreenshotOptions extends SentryMaskingOptions {
diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/SentryUserFeedbackButton.java b/sentry-android-core/src/main/java/io/sentry/android/core/SentryUserFeedbackButton.java
index f842f18674b..589a9fa2ce6 100644
--- a/sentry-android-core/src/main/java/io/sentry/android/core/SentryUserFeedbackButton.java
+++ b/sentry-android-core/src/main/java/io/sentry/android/core/SentryUserFeedbackButton.java
@@ -13,6 +13,9 @@
/**
* @deprecated `SentryUserFeedbackButton` will be removed in the next major version
*/
+// temp fix for JDK 21: Constructors call overridable methods; making them final would break the
+// public API.
+@SuppressWarnings("this-escape")
@Deprecated
public class SentryUserFeedbackButton extends Button {
diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/internal/util/ScreenshotMasking.java b/sentry-android-core/src/main/java/io/sentry/android/core/internal/util/ScreenshotMasking.java
new file mode 100644
index 00000000000..4d3e2d15955
--- /dev/null
+++ b/sentry-android-core/src/main/java/io/sentry/android/core/internal/util/ScreenshotMasking.java
@@ -0,0 +1,170 @@
+package io.sentry.android.core.internal.util;
+
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.view.View;
+import io.sentry.ILogger;
+import io.sentry.SentryLevel;
+import io.sentry.android.core.SentryScreenshotOptions;
+import io.sentry.android.replay.util.MaskRenderer;
+import io.sentry.android.replay.util.ViewsKt;
+import io.sentry.android.replay.viewhierarchy.ViewHierarchyNode;
+import io.sentry.util.ExceptionUtils;
+import io.sentry.util.LoadClass;
+import io.sentry.util.thread.IThreadChecker;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+import org.jetbrains.annotations.ApiStatus;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Applies screenshot masking using the Session Replay view hierarchy approach. Requires the
+ * `sentry-android-replay` module at runtime, callers must check {@link #isAvailable} first.
+ */
+@ApiStatus.Internal
+public final class ScreenshotMasking {
+
+ private static final long MASKING_TIMEOUT_MS = 2000;
+
+ // Checked instead of the masking classes, since it's the only replay class whose name is kept
+ // by the consumer proguard rules
+ private static final String REPLAY_INTEGRATION_CLASS_NAME =
+ "io.sentry.android.replay.ReplayIntegration";
+
+ private ScreenshotMasking() {}
+
+ /** Whether the `sentry-android-replay` module, required for masking, is available at runtime. */
+ public static boolean isAvailable(final @NotNull ILogger logger) {
+ return new LoadClass().isClassAvailable(REPLAY_INTEGRATION_CLASS_NAME, logger);
+ }
+
+ /**
+ * Masks the given screenshot according to the screenshot options.
+ *
+ * @return the masked bitmap, or null if masking failed. The passed screenshot is recycled on
+ * failure, so a raw screenshot is never returned in place of a masked one.
+ */
+ public static @Nullable Bitmap mask(
+ final @NotNull Activity activity,
+ final @NotNull Bitmap screenshot,
+ final @NotNull SentryScreenshotOptions screenshotOptions,
+ final @NotNull IThreadChecker threadChecker,
+ final @NotNull ILogger logger) {
+ final @Nullable ViewHierarchyNode rootNode =
+ captureViewHierarchy(activity, screenshotOptions, threadChecker, logger);
+ if (rootNode == null) {
+ screenshot.recycle();
+ return null;
+ }
+ // applyMasking already recycles its bitmaps on failure
+ return applyMasking(screenshot, rootNode, logger);
+ }
+
+ /**
+ * Captures the view hierarchy on the main thread, since view traversal requires it. If already on
+ * the main thread, captures directly; otherwise posts to the main thread and waits.
+ */
+ private static @Nullable ViewHierarchyNode captureViewHierarchy(
+ final @NotNull Activity activity,
+ final @NotNull SentryScreenshotOptions screenshotOptions,
+ final @NotNull IThreadChecker threadChecker,
+ final @NotNull ILogger logger) {
+ if (threadChecker.isMainThread()) {
+ return buildViewHierarchy(activity, screenshotOptions, logger);
+ }
+
+ final AtomicReference result = new AtomicReference<>(null);
+ final CountDownLatch latch = new CountDownLatch(1);
+
+ try {
+ activity.runOnUiThread(
+ () -> {
+ try {
+ result.set(buildViewHierarchy(activity, screenshotOptions, logger));
+ } finally {
+ latch.countDown();
+ }
+ });
+
+ if (!latch.await(MASKING_TIMEOUT_MS, TimeUnit.MILLISECONDS)) {
+ logger.log(
+ SentryLevel.WARNING, "Timed out waiting for view hierarchy capture on main thread");
+ return null;
+ }
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ logger.log(SentryLevel.ERROR, "Interrupted while capturing view hierarchy", e);
+ return null;
+ }
+
+ return result.get();
+ }
+
+ private static @Nullable ViewHierarchyNode buildViewHierarchy(
+ final @NotNull Activity activity,
+ final @NotNull SentryScreenshotOptions screenshotOptions,
+ final @NotNull ILogger logger) {
+ try {
+ final @Nullable View rootView =
+ activity.getWindow() != null
+ && activity.getWindow().peekDecorView() != null
+ && activity.getWindow().peekDecorView().getRootView() != null
+ ? activity.getWindow().peekDecorView().getRootView()
+ : null;
+ if (rootView == null) {
+ return null;
+ }
+
+ final ViewHierarchyNode rootNode =
+ ViewHierarchyNode.Companion.fromView(rootView, null, 0, screenshotOptions);
+ ViewsKt.traverse(rootView, rootNode, screenshotOptions, logger, null);
+ return rootNode;
+ } catch (Throwable e) {
+ // Traversal calls into arbitrary (custom) View code, which can throw anything
+ ExceptionUtils.rethrowIfFatal(e);
+ logger.log(SentryLevel.ERROR, "Failed to build view hierarchy", e);
+ return null;
+ }
+ }
+
+ private static @Nullable Bitmap applyMasking(
+ final @NotNull Bitmap screenshot,
+ final @NotNull ViewHierarchyNode rootNode,
+ final @NotNull ILogger logger) {
+ Bitmap mutableBitmap = screenshot;
+ boolean createdCopy = false;
+ try (final MaskRenderer maskRenderer = new MaskRenderer()) {
+ // Make bitmap mutable if needed
+ if (!screenshot.isMutable()) {
+ mutableBitmap = screenshot.copy(Bitmap.Config.RGB_565, true);
+ if (mutableBitmap == null) {
+ screenshot.recycle();
+ return null;
+ }
+ createdCopy = true;
+ }
+
+ maskRenderer.renderMasks(mutableBitmap, rootNode, null);
+
+ // Recycle original if we created a copy
+ if (createdCopy && !screenshot.isRecycled()) {
+ screenshot.recycle();
+ }
+
+ return mutableBitmap;
+ } catch (RuntimeException e) {
+ logger.log(SentryLevel.ERROR, "Failed to mask screenshot", e);
+ if (createdCopy) {
+ if (!mutableBitmap.isRecycled()) {
+ mutableBitmap.recycle();
+ }
+ }
+ if (!screenshot.isRecycled()) {
+ screenshot.recycle();
+ }
+ return null;
+ }
+ }
+}
diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/internal/util/ScreenshotUtils.java b/sentry-android-core/src/main/java/io/sentry/android/core/internal/util/ScreenshotUtils.java
index 092caa040db..657ba54cbd2 100644
--- a/sentry-android-core/src/main/java/io/sentry/android/core/internal/util/ScreenshotUtils.java
+++ b/sentry-android-core/src/main/java/io/sentry/android/core/internal/util/ScreenshotUtils.java
@@ -14,6 +14,7 @@
import io.sentry.ILogger;
import io.sentry.SentryLevel;
import io.sentry.android.core.BuildInfoProvider;
+import io.sentry.android.core.SentryAndroidOptions;
import io.sentry.util.thread.IThreadChecker;
import java.io.ByteArrayOutputStream;
import java.util.concurrent.CountDownLatch;
@@ -51,6 +52,62 @@ public class ScreenshotUtils {
return compressBitmapToPng(screenshot, logger);
}
+ // Used by Hybrid SDKs
+ /**
+ * Takes a screenshot and masks it according to {@link SentryAndroidOptions#getScreenshot()}, the
+ * same way {@link io.sentry.android.core.ScreenshotEventProcessor} does for native errors.
+ *
+ * @see #captureMaskedScreenshot(Activity, SentryAndroidOptions, BuildInfoProvider, boolean)
+ * @noinspection unused
+ */
+ public static @Nullable byte[] takeMaskedScreenshot(
+ final @NotNull Activity activity,
+ final @NotNull SentryAndroidOptions options,
+ final @NotNull BuildInfoProvider buildInfoProvider) {
+ final boolean isReplayAvailable = ScreenshotMasking.isAvailable(options.getLogger());
+ return compressBitmapToPng(
+ captureMaskedScreenshot(activity, options, buildInfoProvider, isReplayAvailable),
+ options.getLogger());
+ }
+
+ /**
+ * Captures a screenshot and masks it according to {@link SentryAndroidOptions#getScreenshot()}.
+ * Shared by {@link io.sentry.android.core.ScreenshotEventProcessor} and Hybrid SDKs, so native
+ * and hybrid screenshots follow the same masking rules.
+ *
+ * If no masking is configured, the screenshot is returned unmasked. If masking is configured
+ * but the `sentry-android-replay` module is not available, or masking fails, null is returned to
+ * avoid leaking sensitive data.
+ */
+ public static @Nullable Bitmap captureMaskedScreenshot(
+ final @NotNull Activity activity,
+ final @NotNull SentryAndroidOptions options,
+ final @NotNull BuildInfoProvider buildInfoProvider,
+ final boolean isReplayAvailable) {
+ final boolean isMaskingConfigured = !options.getScreenshot().getMaskViewClasses().isEmpty();
+ if (isMaskingConfigured && !isReplayAvailable) {
+ options
+ .getLogger()
+ .log(SentryLevel.WARNING, "Screenshot masking requires sentry-android-replay module");
+ return null;
+ }
+
+ final @Nullable Bitmap screenshot =
+ captureScreenshot(
+ activity, options.getThreadChecker(), options.getLogger(), buildInfoProvider);
+ if (screenshot == null || !isMaskingConfigured) {
+ return screenshot;
+ }
+
+ // mask() recycles the screenshot on failure, so a raw screenshot is never returned
+ return ScreenshotMasking.mask(
+ activity,
+ screenshot,
+ options.getScreenshot(),
+ options.getThreadChecker(),
+ options.getLogger());
+ }
+
public static @Nullable Bitmap captureScreenshot(
final @NotNull Activity activity,
final @NotNull ILogger logger,
diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/performance/AppStartMetrics.java b/sentry-android-core/src/main/java/io/sentry/android/core/performance/AppStartMetrics.java
index 82376a75d8b..dacab11e4f4 100644
--- a/sentry-android-core/src/main/java/io/sentry/android/core/performance/AppStartMetrics.java
+++ b/sentry-android-core/src/main/java/io/sentry/android/core/performance/AppStartMetrics.java
@@ -50,6 +50,9 @@
*
This class is also responsible for - determining the app start type (cold, warm) - determining
* if the app was launched in foreground
*/
+// temp fix for JDK 21: Constructors call overridable methods; making them final would break the
+// public API.
+@SuppressWarnings("this-escape")
@ApiStatus.Internal
public class AppStartMetrics extends ActivityLifecycleCallbacksAdapter {
public interface HeadlessAppStartListener {
diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/AnrV2IntegrationTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/AnrV2IntegrationTest.kt
index cd21f92fd28..e41d5778a7f 100644
--- a/sentry-android-core/src/test/java/io/sentry/android/core/AnrV2IntegrationTest.kt
+++ b/sentry-android-core/src/test/java/io/sentry/android/core/AnrV2IntegrationTest.kt
@@ -121,7 +121,7 @@ class AnrV2IntegrationTest : ApplicationExitIntegrationTestBase() {
}
shadowActivityManager.addApplicationExitInfo(exitInfo)
},
- flushLogPrefix = "Timed out waiting to flush ANR event to disk.",
+ flushLogPrefix = "Timed out waiting to flush %s event to disk.",
)
override fun assertEnrichedEvent(event: SentryEvent) {
diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/ApplicationExitIntegrationTestBase.kt b/sentry-android-core/src/test/java/io/sentry/android/core/ApplicationExitIntegrationTestBase.kt
index 82cf1c25c9c..7db354ea64c 100644
--- a/sentry-android-core/src/test/java/io/sentry/android/core/ApplicationExitIntegrationTestBase.kt
+++ b/sentry-android-core/src/test/java/io/sentry/android/core/ApplicationExitIntegrationTestBase.kt
@@ -27,6 +27,7 @@ import org.junit.Rule
import org.junit.rules.TemporaryFolder
import org.mockito.kotlin.any
import org.mockito.kotlin.anyOrNull
+import org.mockito.kotlin.anyVararg
import org.mockito.kotlin.argThat
import org.mockito.kotlin.atMost
import org.mockito.kotlin.check
@@ -171,7 +172,7 @@ abstract class ApplicationExitIntegrationTestBase {
verify(fixture.scopes).captureEvent(any(), anyOrNull())
verify(fixture.logger, never())
- .log(any(), argThat { startsWith(config.flushLogPrefix) }, any())
+ .log(any(), argThat { startsWith(config.flushLogPrefix) }, anyVararg())
}
@Test
@@ -184,7 +185,7 @@ abstract class ApplicationExitIntegrationTestBase {
verify(fixture.scopes).captureEvent(any(), anyOrNull())
verify(fixture.logger, never())
- .log(any(), argThat { startsWith(config.flushLogPrefix) }, any())
+ .log(any(), argThat { startsWith(config.flushLogPrefix) }, anyVararg())
}
@Test
@@ -316,7 +317,7 @@ abstract class ApplicationExitIntegrationTestBase {
.log(
any(),
argThat { startsWith("Timed out waiting to flush previous session to its own file.") },
- any(),
+ anyVararg(),
)
}
@@ -337,7 +338,7 @@ abstract class ApplicationExitIntegrationTestBase {
.log(
any(),
argThat { startsWith("Timed out waiting to flush previous session to its own file.") },
- any(),
+ anyVararg(),
)
verify(fixture.scopes).captureEvent(any(), any())
}
@@ -354,7 +355,7 @@ abstract class ApplicationExitIntegrationTestBase {
.log(
any(),
argThat { startsWith("Timed out waiting to flush previous session to its own file.") },
- any(),
+ anyVararg(),
)
assertTrue((fixture.options.envelopeDiskCache as EnvelopeCache).waitPreviousSessionFlush())
}
diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/TombstoneIntegrationTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/TombstoneIntegrationTest.kt
index bc05f3b23fd..39a63148a17 100644
--- a/sentry-android-core/src/test/java/io/sentry/android/core/TombstoneIntegrationTest.kt
+++ b/sentry-android-core/src/test/java/io/sentry/android/core/TombstoneIntegrationTest.kt
@@ -65,7 +65,7 @@ class TombstoneIntegrationTest : ApplicationExitIntegrationTestBase()
+ val options =
+ SentryAndroidOptions().apply {
+ dsn = "https://key@sentry.io/proj"
+ threadChecker = this@Fixture.threadChecker
+ }
+ val buildInfoProvider = BuildInfoProvider(options.logger)
+
+ init {
+ whenever(threadChecker.isMainThread).thenReturn(true)
+ }
+ }
+
+ private lateinit var fixture: Fixture
+
+ private fun takeMaskedScreenshot(isReplayAvailable: Boolean): ByteArray? =
+ ScreenshotUtils.compressBitmapToPng(
+ ScreenshotUtils.captureMaskedScreenshot(
+ fixture.activity,
+ fixture.options,
+ fixture.buildInfoProvider,
+ isReplayAvailable,
+ ),
+ fixture.options.logger,
+ )
+
+ @BeforeTest
+ fun `set up`() {
+ System.setProperty("robolectric.areWindowsMarkedVisible", "true")
+ System.setProperty("robolectric.pixelCopyRenderMode", "hardware")
+
+ fixture = Fixture()
+ fixture.activity = buildActivity(TextActivity::class.java, null).setup().get()
+ }
+
+ @Test
+ fun `when masking is not configured, returns an unmasked screenshot`() {
+ val bytes = takeMaskedScreenshot(isReplayAvailable = false)
+
+ assertNotNull(bytes)
+ }
+
+ @Test
+ fun `when masking is configured, returns a masked screenshot`() {
+ val unmasked = takeMaskedScreenshot(isReplayAvailable = true)
+ fixture.options.screenshot.setMaskAllText(true)
+ val masked = takeMaskedScreenshot(isReplayAvailable = true)
+
+ assertNotNull(unmasked)
+ assertNotNull(masked)
+ assertFalse(unmasked.contentEquals(masked))
+ }
+
+ @Test
+ fun `when masking is configured but replay is not available, returns no screenshot`() {
+ fixture.options.screenshot.setMaskAllText(true)
+
+ val bytes = takeMaskedScreenshot(isReplayAvailable = false)
+
+ assertNull(bytes)
+ }
+
+ @Test
+ fun `when masking is configured but fails, returns no screenshot`() {
+ fixture.options.screenshot.setMaskAllText(true)
+ fixture.activity.findViewById(android.R.id.text1).throwOnTraversal = true
+
+ val bytes = takeMaskedScreenshot(isReplayAvailable = true)
+
+ assertNull(bytes)
+ }
+
+ @Test
+ fun `public overload detects replay availability`() {
+ fixture.options.screenshot.setMaskAllText(true)
+
+ // sentry-android-replay is on the test classpath
+ val bytes =
+ ScreenshotUtils.takeMaskedScreenshot(
+ fixture.activity,
+ fixture.options,
+ fixture.buildInfoProvider,
+ )
+
+ assertNotNull(bytes)
+ }
+}
+
+private class TextActivity : Activity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ val linearLayout =
+ LinearLayout(this).apply {
+ setBackgroundColor(Color.WHITE)
+ orientation = LinearLayout.VERTICAL
+ layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
+ }
+ linearLayout.addView(
+ ThrowingTextView(this).apply {
+ id = android.R.id.text1
+ text = "Sensitive text"
+ setTextColor(Color.BLACK)
+ textSize = 32f
+ layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)
+ }
+ )
+ setContentView(linearLayout)
+ }
+}
+
+/** Fails view hierarchy traversal on demand, to exercise the masking failure path. */
+private class ThrowingTextView(context: Context) : TextView(context) {
+ var throwOnTraversal = false
+
+ override fun getTotalPaddingLeft(): Int {
+ if (throwOnTraversal) {
+ throw IllegalStateException("Traversal failure")
+ }
+ return super.getTotalPaddingLeft()
+ }
+}
diff --git a/sentry-android-fragment/build.gradle.kts b/sentry-android-fragment/build.gradle.kts
index e613f1fd5bb..3c7a0404970 100644
--- a/sentry-android-fragment/build.gradle.kts
+++ b/sentry-android-fragment/build.gradle.kts
@@ -70,7 +70,7 @@ dependencies {
testImplementation(libs.androidx.fragment.ktx)
testImplementation(libs.kotlin.test.junit)
testImplementation(libs.mockito.kotlin)
- testImplementation(libs.mockito.inline)
+ testImplementation(libs.mockito.core)
}
tasks.withType().configureEach {
diff --git a/sentry-android-integration-tests/sentry-uitest-android-critical/build.gradle.kts b/sentry-android-integration-tests/sentry-uitest-android-critical/build.gradle.kts
index 9ca0c1f6d9d..e606ab52553 100644
--- a/sentry-android-integration-tests/sentry-uitest-android-critical/build.gradle.kts
+++ b/sentry-android-integration-tests/sentry-uitest-android-critical/build.gradle.kts
@@ -1,5 +1,4 @@
import io.gitlab.arturbosch.detekt.Detekt
-import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
id("com.android.application")
@@ -33,7 +32,6 @@ android {
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro")
}
}
- kotlin { compilerOptions.jvmTarget = JvmTarget.JVM_11 }
buildFeatures { compose = true }
composeOptions { kotlinCompilerExtensionVersion = libs.versions.composeCompiler.get() }
androidComponents.beforeVariants {
diff --git a/sentry-android-integration-tests/sentry-uitest-android-macrobenchmark/build.gradle.kts b/sentry-android-integration-tests/sentry-uitest-android-macrobenchmark/build.gradle.kts
index 18a5b6cb7f5..cab7c28f934 100644
--- a/sentry-android-integration-tests/sentry-uitest-android-macrobenchmark/build.gradle.kts
+++ b/sentry-android-integration-tests/sentry-uitest-android-macrobenchmark/build.gradle.kts
@@ -1,5 +1,3 @@
-import org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11
-
plugins {
id("com.android.test")
alias(libs.plugins.kotlin.android)
@@ -28,13 +26,6 @@ android {
}
}
- compileOptions {
- sourceCompatibility = JavaVersion.VERSION_11
- targetCompatibility = JavaVersion.VERSION_11
- }
-
- kotlin { compilerOptions.jvmTarget = JVM_11 }
-
targetProjectPath = ":sentry-samples:sentry-samples-android"
// Run the test in its own process so it measures the target app cold, not itself.
experimentalProperties["android.experimental.self-instrumenting"] = true
diff --git a/sentry-android-integration-tests/sentry-uitest-android/build.gradle.kts b/sentry-android-integration-tests/sentry-uitest-android/build.gradle.kts
index 85ff2b1a3c7..8f479470cac 100644
--- a/sentry-android-integration-tests/sentry-uitest-android/build.gradle.kts
+++ b/sentry-android-integration-tests/sentry-uitest-android/build.gradle.kts
@@ -1,6 +1,5 @@
import io.gitlab.arturbosch.detekt.Detekt
import net.ltgt.gradle.errorprone.errorprone
-import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
id("com.android.application")
@@ -65,8 +64,6 @@ android {
}
}
- kotlin { compilerOptions.jvmTarget = JvmTarget.JVM_11 }
-
lint {
warningsAsErrors = true
checkDependencies = true
diff --git a/sentry-android-integration-tests/sentry-uitest-android/proguard-rules.pro b/sentry-android-integration-tests/sentry-uitest-android/proguard-rules.pro
index 5de2dac4bdb..174e6e38774 100644
--- a/sentry-android-integration-tests/sentry-uitest-android/proguard-rules.pro
+++ b/sentry-android-integration-tests/sentry-uitest-android/proguard-rules.pro
@@ -24,6 +24,7 @@
-dontwarn com.google.errorprone.**
-dontwarn com.sun.jna.**
+-dontwarn com.sun.net.httpserver.**
-dontwarn edu.umd.cs.findbugs.**
-dontwarn java.lang.instrument.**
-dontwarn java.lang.management.**
diff --git a/sentry-android-navigation/build.gradle.kts b/sentry-android-navigation/build.gradle.kts
index 19b9b3c753f..ddc6d6f4161 100644
--- a/sentry-android-navigation/build.gradle.kts
+++ b/sentry-android-navigation/build.gradle.kts
@@ -71,7 +71,7 @@ dependencies {
testImplementation(libs.kotlin.test.junit)
testImplementation(libs.mockito.kotlin)
- testImplementation(libs.mockito.inline)
+ testImplementation(libs.mockito.core)
testImplementation(libs.roboelectric)
testImplementation(libs.androidx.core)
diff --git a/sentry-android-navigation3/build.gradle.kts b/sentry-android-navigation3/build.gradle.kts
index da7ad9f36f4..b9d02bb49d4 100644
--- a/sentry-android-navigation3/build.gradle.kts
+++ b/sentry-android-navigation3/build.gradle.kts
@@ -67,7 +67,7 @@ dependencies {
testImplementation(libs.androidx.test.core)
testImplementation(libs.androidx.test.ext.junit)
testImplementation(libs.google.truth)
- testImplementation(libs.mockito.inline)
+ testImplementation(libs.mockito.core)
testImplementation(libs.mockito.kotlin)
testImplementation(libs.roboelectric)
}
diff --git a/sentry-android-replay/build.gradle.kts b/sentry-android-replay/build.gradle.kts
index 1318f7767c9..1a92f9a0b36 100644
--- a/sentry-android-replay/build.gradle.kts
+++ b/sentry-android-replay/build.gradle.kts
@@ -85,7 +85,7 @@ dependencies {
testImplementation(libs.awaitility.kotlin)
testImplementation(libs.google.truth)
testImplementation(libs.mockito.kotlin)
- testImplementation(libs.mockito.inline)
+ testImplementation(libs.mockito.core)
testImplementation(libs.androidx.compose.ui)
testImplementation(libs.androidx.compose.foundation)
testImplementation(libs.androidx.compose.foundation.layout)
diff --git a/sentry-android-sqlite/build.gradle.kts b/sentry-android-sqlite/build.gradle.kts
index fd15526fcbe..38ea832082f 100644
--- a/sentry-android-sqlite/build.gradle.kts
+++ b/sentry-android-sqlite/build.gradle.kts
@@ -79,7 +79,7 @@ dependencies {
testImplementation(libs.androidx.sqlite)
testImplementation(libs.kotlin.test.junit)
testImplementation(libs.mockito.kotlin)
- testImplementation(libs.mockito.inline)
+ testImplementation(libs.mockito.core)
}
tasks.withType().configureEach {
diff --git a/sentry-android-timber/build.gradle.kts b/sentry-android-timber/build.gradle.kts
index f66c1a8a96b..92f14b37c8c 100644
--- a/sentry-android-timber/build.gradle.kts
+++ b/sentry-android-timber/build.gradle.kts
@@ -80,7 +80,7 @@ dependencies {
testImplementation(libs.kotlin.test.junit)
testImplementation(libs.androidx.test.ext.junit)
testImplementation(libs.mockito.kotlin)
- testImplementation(libs.mockito.inline)
+ testImplementation(libs.mockito.core)
}
tasks.withType().configureEach {
diff --git a/sentry-android-timber/src/test/java/io/sentry/android/timber/SentryTimberTreeTest.kt b/sentry-android-timber/src/test/java/io/sentry/android/timber/SentryTimberTreeTest.kt
index 08fd7972d86..ff90a420701 100644
--- a/sentry-android-timber/src/test/java/io/sentry/android/timber/SentryTimberTreeTest.kt
+++ b/sentry-android-timber/src/test/java/io/sentry/android/timber/SentryTimberTreeTest.kt
@@ -13,6 +13,7 @@ import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertNull
import org.mockito.kotlin.any
+import org.mockito.kotlin.anyVararg
import org.mockito.kotlin.check
import org.mockito.kotlin.eq
import org.mockito.kotlin.mock
@@ -338,7 +339,7 @@ class SentryTimberTreeTest {
fun `Tree adds a log if min level is higher`() {
val sut = fixture.getSut()
sut.e(Throwable("test"))
- verify(fixture.logs).log(any(), any(), any(), any())
+ verify(fixture.logs).log(any(), any(), any(), anyVararg())
}
@Test
diff --git a/sentry-apollo-3/build.gradle.kts b/sentry-apollo-3/build.gradle.kts
index 6711b165dd9..ae8721b22b2 100644
--- a/sentry-apollo-3/build.gradle.kts
+++ b/sentry-apollo-3/build.gradle.kts
@@ -12,7 +12,7 @@ plugins {
id("io.sentry.animalsniffer.android")
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
@@ -37,7 +37,7 @@ dependencies {
testImplementation(libs.google.truth)
testImplementation(libs.kotlinx.coroutines)
testImplementation(libs.mockito.kotlin)
- testImplementation(libs.mockito.inline)
+ testImplementation(libs.mockito.core)
testImplementation(libs.okhttp.mockwebserver)
}
diff --git a/sentry-apollo-4/build.gradle.kts b/sentry-apollo-4/build.gradle.kts
index 9fb024a01db..63c8b5431c6 100644
--- a/sentry-apollo-4/build.gradle.kts
+++ b/sentry-apollo-4/build.gradle.kts
@@ -12,7 +12,7 @@ plugins {
id("io.sentry.animalsniffer.android")
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
@@ -38,7 +38,7 @@ dependencies {
testImplementation(libs.kotlinx.coroutines)
testImplementation(libs.kotlinx.coroutines.test)
testImplementation(libs.mockito.kotlin)
- testImplementation(libs.mockito.inline)
+ testImplementation(libs.mockito.core)
testImplementation(libs.okhttp.mockwebserver)
testImplementation("org.jetbrains.kotlin:kotlin-reflect:2.0.0")
}
diff --git a/sentry-apollo-5/build.gradle.kts b/sentry-apollo-5/build.gradle.kts
index e4cd7dd0345..2d78dff8fa1 100644
--- a/sentry-apollo-5/build.gradle.kts
+++ b/sentry-apollo-5/build.gradle.kts
@@ -11,7 +11,7 @@ plugins {
id("io.sentry.animalsniffer.android")
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
@@ -37,7 +37,7 @@ dependencies {
testImplementation(libs.kotlinx.coroutines)
testImplementation(libs.kotlinx.coroutines.test)
testImplementation(libs.mockito.kotlin)
- testImplementation(libs.mockito.inline)
+ testImplementation(libs.mockito.core)
testImplementation(libs.okhttp.mockwebserver5)
}
diff --git a/sentry-apollo/build.gradle.kts b/sentry-apollo/build.gradle.kts
index b3cb3cff953..72a183bb7b3 100644
--- a/sentry-apollo/build.gradle.kts
+++ b/sentry-apollo/build.gradle.kts
@@ -12,7 +12,7 @@ plugins {
id("io.sentry.animalsniffer.android")
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
@@ -38,7 +38,7 @@ dependencies {
testImplementation(libs.google.truth)
testImplementation(libs.kotlinx.coroutines)
testImplementation(libs.mockito.kotlin)
- testImplementation(libs.mockito.inline)
+ testImplementation(libs.mockito.core)
testImplementation(libs.okhttp.mockwebserver)
}
@@ -46,6 +46,8 @@ tasks.withType().configureEach {
options.errorprone {
check("NullAway", net.ltgt.gradle.errorprone.CheckSeverity.ERROR)
option("NullAway:AnnotatedPackages", "io.sentry")
+ // Generated by the Apollo plugin and marked "DO NOT MODIFY".
+ excludedPaths.set(".*/LaunchDetailsQuery.java")
}
}
diff --git a/sentry-async-profiler/build.gradle.kts b/sentry-async-profiler/build.gradle.kts
index 17454baa662..3bcdefd1d82 100644
--- a/sentry-async-profiler/build.gradle.kts
+++ b/sentry-async-profiler/build.gradle.kts
@@ -11,7 +11,7 @@ plugins {
id("io.sentry.animalsniffer")
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
}
@@ -34,7 +34,7 @@ dependencies {
testImplementation(projects.sentryTestSupport)
testImplementation(libs.kotlin.test.junit)
testImplementation(libs.mockito.kotlin)
- testImplementation(libs.mockito.inline)
+ testImplementation(libs.mockito.core)
}
tasks.withType().configureEach {
diff --git a/sentry-async-profiler/src/main/java/io/sentry/asyncprofiler/convert/JfrAsyncProfilerToSentryProfileConverter.java b/sentry-async-profiler/src/main/java/io/sentry/asyncprofiler/convert/JfrAsyncProfilerToSentryProfileConverter.java
index 718fae422f7..a0ce94c08ec 100644
--- a/sentry-async-profiler/src/main/java/io/sentry/asyncprofiler/convert/JfrAsyncProfilerToSentryProfileConverter.java
+++ b/sentry-async-profiler/src/main/java/io/sentry/asyncprofiler/convert/JfrAsyncProfilerToSentryProfileConverter.java
@@ -83,7 +83,7 @@ private class ProfileEventVisitor implements EventCollector.Visitor {
private final @NotNull JfrReader jfr;
private final @NotNull Arguments args;
- public ProfileEventVisitor(
+ ProfileEventVisitor(
@NotNull SentryProfile sentryProfile,
@NotNull SentryStackTraceFactory stackTraceFactory,
@NotNull JfrReader jfr,
diff --git a/sentry-compose/build.gradle.kts b/sentry-compose/build.gradle.kts
index 394885df1b8..19fce9f95b5 100644
--- a/sentry-compose/build.gradle.kts
+++ b/sentry-compose/build.gradle.kts
@@ -69,7 +69,7 @@ kotlin {
implementation(libs.androidx.test.runner)
implementation(libs.google.truth)
implementation(libs.kotlin.test.junit)
- implementation(libs.mockito.inline)
+ implementation(libs.mockito.core)
implementation(libs.mockito.kotlin)
implementation(libs.roboelectric)
}
diff --git a/sentry-graphql-22/build.gradle.kts b/sentry-graphql-22/build.gradle.kts
index def6708f672..9da6bcc1e36 100644
--- a/sentry-graphql-22/build.gradle.kts
+++ b/sentry-graphql-22/build.gradle.kts
@@ -11,7 +11,7 @@ plugins {
id("io.sentry.animalsniffer")
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
@@ -36,7 +36,7 @@ dependencies {
testImplementation(libs.kotlin.test.junit)
testImplementation(libs.google.truth)
testImplementation(libs.mockito.kotlin)
- testImplementation(libs.mockito.inline)
+ testImplementation(libs.mockito.core)
testImplementation(libs.okhttp)
testImplementation(libs.okhttp.mockwebserver)
testImplementation(libs.springboot.starter.graphql)
diff --git a/sentry-graphql-core/build.gradle.kts b/sentry-graphql-core/build.gradle.kts
index 34f71ab9cfb..df0496f070e 100644
--- a/sentry-graphql-core/build.gradle.kts
+++ b/sentry-graphql-core/build.gradle.kts
@@ -11,7 +11,7 @@ plugins {
id("io.sentry.animalsniffer")
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
@@ -34,7 +34,7 @@ dependencies {
testImplementation(libs.graphql.java17)
testImplementation(libs.kotlin.test.junit)
testImplementation(libs.mockito.kotlin)
- testImplementation(libs.mockito.inline)
+ testImplementation(libs.mockito.core)
testImplementation(libs.okhttp)
testImplementation(libs.okhttp.mockwebserver)
testImplementation(libs.springboot.starter.graphql)
diff --git a/sentry-graphql/build.gradle.kts b/sentry-graphql/build.gradle.kts
index f996e0310a1..25613e1fdd6 100644
--- a/sentry-graphql/build.gradle.kts
+++ b/sentry-graphql/build.gradle.kts
@@ -11,7 +11,7 @@ plugins {
id("io.sentry.animalsniffer")
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
@@ -36,7 +36,7 @@ dependencies {
testImplementation(libs.kotlin.test.junit)
testImplementation(libs.google.truth)
testImplementation(libs.mockito.kotlin)
- testImplementation(libs.mockito.inline)
+ testImplementation(libs.mockito.core)
testImplementation(libs.okhttp)
testImplementation(libs.okhttp.mockwebserver)
testImplementation(libs.springboot.starter.graphql)
diff --git a/sentry-jcache/build.gradle.kts b/sentry-jcache/build.gradle.kts
index b388f35881f..b773c42c340 100644
--- a/sentry-jcache/build.gradle.kts
+++ b/sentry-jcache/build.gradle.kts
@@ -11,7 +11,7 @@ plugins {
id("io.sentry.animalsniffer")
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
@@ -34,7 +34,7 @@ dependencies {
testImplementation(kotlin(Config.kotlinStdLib))
testImplementation(libs.kotlin.test.junit)
testImplementation(libs.mockito.kotlin)
- testImplementation(libs.mockito.inline)
+ testImplementation(libs.mockito.core)
}
tasks.withType().configureEach {
diff --git a/sentry-jdbc/build.gradle.kts b/sentry-jdbc/build.gradle.kts
index e2a7f573138..9d0aa1596fe 100644
--- a/sentry-jdbc/build.gradle.kts
+++ b/sentry-jdbc/build.gradle.kts
@@ -11,7 +11,7 @@ plugins {
id("io.sentry.animalsniffer")
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
}
@@ -32,7 +32,7 @@ dependencies {
testImplementation(libs.hsqldb)
testImplementation(libs.kotlin.test.junit)
testImplementation(libs.mockito.kotlin)
- testImplementation(libs.mockito.inline)
+ testImplementation(libs.mockito.core)
}
tasks.withType().configureEach {
diff --git a/sentry-jul/build.gradle.kts b/sentry-jul/build.gradle.kts
index 2eec61eb171..130b46ad5ed 100644
--- a/sentry-jul/build.gradle.kts
+++ b/sentry-jul/build.gradle.kts
@@ -11,7 +11,7 @@ plugins {
id("io.sentry.animalsniffer")
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
}
diff --git a/sentry-jul/src/main/java/io/sentry/jul/SentryHandler.java b/sentry-jul/src/main/java/io/sentry/jul/SentryHandler.java
index 5b1a417f9ae..37173a70aa6 100644
--- a/sentry-jul/src/main/java/io/sentry/jul/SentryHandler.java
+++ b/sentry-jul/src/main/java/io/sentry/jul/SentryHandler.java
@@ -41,6 +41,9 @@
import org.slf4j.MDC;
/** Logging handler in charge of sending the java.util.logging records to a Sentry server. */
+// temp fix for JDK 21: Constructors call overridable methods; making them final would break the
+// public API.
+@SuppressWarnings("this-escape")
@Open
public class SentryHandler extends Handler {
public static final String MECHANISM_TYPE = "JulSentryHandler";
diff --git a/sentry-kafka/build.gradle.kts b/sentry-kafka/build.gradle.kts
index 0d543bad270..37240c8305e 100644
--- a/sentry-kafka/build.gradle.kts
+++ b/sentry-kafka/build.gradle.kts
@@ -11,7 +11,7 @@ plugins {
id("io.sentry.animalsniffer")
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
}
@@ -30,7 +30,7 @@ dependencies {
testImplementation(kotlin(Config.kotlinStdLib))
testImplementation(libs.kotlin.test.junit)
testImplementation(libs.mockito.kotlin)
- testImplementation(libs.mockito.inline)
+ testImplementation(libs.mockito.core)
testImplementation(libs.kafka.clients)
}
diff --git a/sentry-kafka/src/main/java/io/sentry/kafka/SentryKafkaConsumerTracing.java b/sentry-kafka/src/main/java/io/sentry/kafka/SentryKafkaConsumerTracing.java
index dbce760de99..a45505f1019 100644
--- a/sentry-kafka/src/main/java/io/sentry/kafka/SentryKafkaConsumerTracing.java
+++ b/sentry-kafka/src/main/java/io/sentry/kafka/SentryKafkaConsumerTracing.java
@@ -247,7 +247,7 @@ private void finishTransaction(
try {
final double enqueuedTimeSeconds = Double.parseDouble(enqueuedTimeStr);
- final double nowSeconds = DateUtils.millisToSeconds(System.currentTimeMillis());
+ final double nowSeconds = DateUtils.millisToSeconds((double) System.currentTimeMillis());
final long latencyMs = (long) ((nowSeconds - enqueuedTimeSeconds) * 1000);
return latencyMs >= 0 ? latencyMs : null;
} catch (NumberFormatException ignored) {
diff --git a/sentry-kafka/src/main/java/io/sentry/kafka/SentryKafkaProducer.java b/sentry-kafka/src/main/java/io/sentry/kafka/SentryKafkaProducer.java
index bcc538e339c..312faabbb42 100644
--- a/sentry-kafka/src/main/java/io/sentry/kafka/SentryKafkaProducer.java
+++ b/sentry-kafka/src/main/java/io/sentry/kafka/SentryKafkaProducer.java
@@ -114,7 +114,8 @@ static final class SentryProducerHandler implements InvocationHandler {
}
@Override
- @SuppressWarnings("unchecked")
+ // temp fix for JDK 21: Proxy equals() is identity-based.
+ @SuppressWarnings({"unchecked", "ReferenceEquality"})
public @Nullable Object invoke(
final @NotNull Object proxy, final @NotNull Method method, final @Nullable Object[] args)
throws Throwable {
@@ -236,7 +237,8 @@ private void maybeInjectHeaders(final @NotNull Headers headers, final @Nullable
headers.remove(SENTRY_ENQUEUED_TIME_HEADER);
headers.add(
SENTRY_ENQUEUED_TIME_HEADER,
- DateUtils.doubleToBigDecimal(DateUtils.millisToSeconds(System.currentTimeMillis()))
+ DateUtils.doubleToBigDecimal(
+ DateUtils.millisToSeconds((double) System.currentTimeMillis()))
.toString()
.getBytes(StandardCharsets.UTF_8));
} catch (Throwable t) {
diff --git a/sentry-kotlin-extensions/build.gradle.kts b/sentry-kotlin-extensions/build.gradle.kts
index 101761b2a82..ded17d445e7 100644
--- a/sentry-kotlin-extensions/build.gradle.kts
+++ b/sentry-kotlin-extensions/build.gradle.kts
@@ -11,7 +11,7 @@ plugins {
id("io.sentry.animalsniffer.android")
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
diff --git a/sentry-ktor-client/build.gradle.kts b/sentry-ktor-client/build.gradle.kts
index cbee84179fb..28edd1689e0 100644
--- a/sentry-ktor-client/build.gradle.kts
+++ b/sentry-ktor-client/build.gradle.kts
@@ -12,7 +12,7 @@ plugins {
id("io.sentry.animalsniffer.android")
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
@@ -37,7 +37,7 @@ dependencies {
testImplementation(libs.kotlin.test.junit)
testImplementation(libs.google.truth)
testImplementation(libs.mockito.kotlin)
- testImplementation(libs.mockito.inline)
+ testImplementation(libs.mockito.core)
testImplementation(libs.ktor.client.core)
testImplementation(libs.ktor.client.java)
testImplementation(libs.okhttp.mockwebserver)
diff --git a/sentry-launchdarkly-android/build.gradle.kts b/sentry-launchdarkly-android/build.gradle.kts
index ddc982e9d6a..df081b21213 100644
--- a/sentry-launchdarkly-android/build.gradle.kts
+++ b/sentry-launchdarkly-android/build.gradle.kts
@@ -70,6 +70,6 @@ dependencies {
testImplementation(libs.androidx.test.ext.junit)
testImplementation(libs.kotlin.test.junit)
testImplementation(libs.mockito.kotlin)
- testImplementation(libs.mockito.inline)
+ testImplementation(libs.mockito.core)
testImplementation(libs.launchdarkly.android)
}
diff --git a/sentry-launchdarkly-server/build.gradle.kts b/sentry-launchdarkly-server/build.gradle.kts
index 95aba9faaf5..f2ed3d15742 100644
--- a/sentry-launchdarkly-server/build.gradle.kts
+++ b/sentry-launchdarkly-server/build.gradle.kts
@@ -11,7 +11,7 @@ plugins {
id("io.sentry.animalsniffer")
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
@@ -34,7 +34,7 @@ dependencies {
testImplementation(kotlin(Config.kotlinStdLib))
testImplementation(libs.kotlin.test.junit)
testImplementation(libs.mockito.kotlin)
- testImplementation(libs.mockito.inline)
+ testImplementation(libs.mockito.core)
testImplementation(libs.launchdarkly.server)
}
diff --git a/sentry-log4j2/build.gradle.kts b/sentry-log4j2/build.gradle.kts
index 6e5250ece50..2d2444a2395 100644
--- a/sentry-log4j2/build.gradle.kts
+++ b/sentry-log4j2/build.gradle.kts
@@ -11,7 +11,7 @@ plugins {
id("io.sentry.animalsniffer")
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
}
diff --git a/sentry-logback/build.gradle.kts b/sentry-logback/build.gradle.kts
index de2c9dbb807..48f84725a78 100644
--- a/sentry-logback/build.gradle.kts
+++ b/sentry-logback/build.gradle.kts
@@ -11,7 +11,7 @@ plugins {
id("io.sentry.animalsniffer")
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
}
diff --git a/sentry-logback/src/main/java/io/sentry/logback/SentryAppender.java b/sentry-logback/src/main/java/io/sentry/logback/SentryAppender.java
index bf99b8573bb..127ca7aa707 100644
--- a/sentry-logback/src/main/java/io/sentry/logback/SentryAppender.java
+++ b/sentry-logback/src/main/java/io/sentry/logback/SentryAppender.java
@@ -197,7 +197,8 @@ protected void captureLog(@NotNull ILoggingEvent loggingEvent) {
final @NotNull SentryLogParameters params = SentryLogParameters.create(attributes);
params.setOrigin("auto.log.logback");
- Sentry.logger().log(sentryLevel, params, formattedMessage, arguments);
+ Sentry.logger()
+ .log(sentryLevel, params, formattedMessage, arguments != null ? arguments : new Object[0]);
}
@SuppressWarnings("deprecation")
diff --git a/sentry-okhttp/build.gradle.kts b/sentry-okhttp/build.gradle.kts
index 5abd1cf26b9..0b3e2388415 100644
--- a/sentry-okhttp/build.gradle.kts
+++ b/sentry-okhttp/build.gradle.kts
@@ -12,7 +12,7 @@ plugins {
id("io.sentry.animalsniffer.android")
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
@@ -36,7 +36,7 @@ dependencies {
testImplementation(projects.sentryTestSupport)
testImplementation(libs.kotlin.test.junit)
testImplementation(libs.mockito.kotlin)
- testImplementation(libs.mockito.inline)
+ testImplementation(libs.mockito.core)
testImplementation(libs.okhttp)
testImplementation(libs.okhttp.mockwebserver)
testImplementation(libs.google.truth)
diff --git a/sentry-openfeature/build.gradle.kts b/sentry-openfeature/build.gradle.kts
index b079ead1fc5..6750e22e61c 100644
--- a/sentry-openfeature/build.gradle.kts
+++ b/sentry-openfeature/build.gradle.kts
@@ -11,7 +11,7 @@ plugins {
id("io.sentry.animalsniffer")
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
@@ -34,7 +34,7 @@ dependencies {
testImplementation(kotlin(Config.kotlinStdLib))
testImplementation(libs.kotlin.test.junit)
testImplementation(libs.mockito.kotlin)
- testImplementation(libs.mockito.inline)
+ testImplementation(libs.mockito.core)
testImplementation(libs.openfeature)
}
diff --git a/sentry-openfeign/build.gradle.kts b/sentry-openfeign/build.gradle.kts
index 8b7adc97544..209e5c34e54 100644
--- a/sentry-openfeign/build.gradle.kts
+++ b/sentry-openfeign/build.gradle.kts
@@ -11,7 +11,7 @@ plugins {
id("io.sentry.animalsniffer")
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
}
diff --git a/sentry-opentelemetry/sentry-opentelemetry-agentcustomization/build.gradle.kts b/sentry-opentelemetry/sentry-opentelemetry-agentcustomization/build.gradle.kts
index 087568d03ee..3390f2695c8 100644
--- a/sentry-opentelemetry/sentry-opentelemetry-agentcustomization/build.gradle.kts
+++ b/sentry-opentelemetry/sentry-opentelemetry-agentcustomization/build.gradle.kts
@@ -10,7 +10,7 @@ plugins {
alias(libs.plugins.gradle.versions)
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
}
diff --git a/sentry-opentelemetry/sentry-opentelemetry-bootstrap/build.gradle.kts b/sentry-opentelemetry/sentry-opentelemetry-bootstrap/build.gradle.kts
index 3585aa40d4a..28a1b030e15 100644
--- a/sentry-opentelemetry/sentry-opentelemetry-bootstrap/build.gradle.kts
+++ b/sentry-opentelemetry/sentry-opentelemetry-bootstrap/build.gradle.kts
@@ -10,7 +10,7 @@ plugins {
alias(libs.plugins.gradle.versions)
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
}
diff --git a/sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/OtelContextScopesStorage.java b/sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/OtelContextScopesStorage.java
index 143ebb6c16d..ad70d2346a8 100644
--- a/sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/OtelContextScopesStorage.java
+++ b/sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/OtelContextScopesStorage.java
@@ -17,7 +17,7 @@ public final class OtelContextScopesStorage implements IScopesStorage {
@Override
public void init() {
- /**
+ /*
* We're currently overriding the storage mechanism to allow for cleanup of non closed OTel
* scopes. These happen when using e.g. Sentry static API due to getCurrentScopes() invoking
* Context.makeCurrent and then ignoring the returned lifecycle token (OTel Scope). After fixing
diff --git a/sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/SentryOtelThreadLocalStorage.java b/sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/SentryOtelThreadLocalStorage.java
index e44afc5a2dc..7ac6bee4a82 100644
--- a/sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/SentryOtelThreadLocalStorage.java
+++ b/sentry-opentelemetry/sentry-opentelemetry-bootstrap/src/main/java/io/sentry/opentelemetry/SentryOtelThreadLocalStorage.java
@@ -29,6 +29,8 @@ public final class SentryOtelThreadLocalStorage implements ContextStorage {
private static final ThreadLocal THREAD_LOCAL_STORAGE = new ThreadLocal<>();
+ // temp fix for JDK 21: Same identity check as OpenTelemetry's ThreadLocalContextStorage.
+ @SuppressWarnings("ReferenceEquality")
@Override
public Scope attach(Context toAttach) {
if (toAttach == null) {
diff --git a/sentry-opentelemetry/sentry-opentelemetry-core/build.gradle.kts b/sentry-opentelemetry/sentry-opentelemetry-core/build.gradle.kts
index a252628c1a2..1c1e7f984ba 100644
--- a/sentry-opentelemetry/sentry-opentelemetry-core/build.gradle.kts
+++ b/sentry-opentelemetry/sentry-opentelemetry-core/build.gradle.kts
@@ -10,7 +10,7 @@ plugins {
alias(libs.plugins.gradle.versions)
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
}
diff --git a/sentry-opentelemetry/sentry-opentelemetry-otlp/build.gradle.kts b/sentry-opentelemetry/sentry-opentelemetry-otlp/build.gradle.kts
index ec240c681ae..afab9ef180f 100644
--- a/sentry-opentelemetry/sentry-opentelemetry-otlp/build.gradle.kts
+++ b/sentry-opentelemetry/sentry-opentelemetry-otlp/build.gradle.kts
@@ -10,7 +10,7 @@ plugins {
alias(libs.plugins.gradle.versions)
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
}
diff --git a/sentry-quartz/build.gradle.kts b/sentry-quartz/build.gradle.kts
index f4f0d9d07d2..b5387daf207 100644
--- a/sentry-quartz/build.gradle.kts
+++ b/sentry-quartz/build.gradle.kts
@@ -11,7 +11,7 @@ plugins {
id("io.sentry.animalsniffer")
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
@@ -33,7 +33,7 @@ dependencies {
testImplementation(kotlin(Config.kotlinStdLib))
testImplementation(libs.kotlin.test.junit)
testImplementation(libs.mockito.kotlin)
- testImplementation(libs.mockito.inline)
+ testImplementation(libs.mockito.core)
}
tasks.withType().configureEach {
diff --git a/sentry-reactor/build.gradle.kts b/sentry-reactor/build.gradle.kts
index fe9023586ef..b98eafd028f 100644
--- a/sentry-reactor/build.gradle.kts
+++ b/sentry-reactor/build.gradle.kts
@@ -10,12 +10,10 @@ plugins {
alias(libs.plugins.buildconfig)
}
-configure {
- sourceCompatibility = JavaVersion.VERSION_17
- targetCompatibility = JavaVersion.VERSION_17
-}
+// Published code targets Java 17. Test code is not published and follows the toolchain.
+tasks.named("compileJava") { options.release.set(17) }
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
diff --git a/sentry-reactor/src/main/java/io/sentry/reactor/SentryReactorUtils.java b/sentry-reactor/src/main/java/io/sentry/reactor/SentryReactorUtils.java
index 16fed92bd01..04d87a8b45b 100644
--- a/sentry-reactor/src/main/java/io/sentry/reactor/SentryReactorUtils.java
+++ b/sentry-reactor/src/main/java/io/sentry/reactor/SentryReactorUtils.java
@@ -48,7 +48,7 @@ public static Mono withSentryForkedRoots(final @NotNull Mono mono) {
*/
public static Mono withSentryScopes(
final @NotNull Mono mono, final @NotNull IScopes scopes) {
- /**
+ /*
* WARNING: Cannot set the scopes as current. It would be used by others to clone again causing
* shared scopes and thus leading to issues like unrelated breadcrumbs showing up in events.
*/
@@ -96,7 +96,7 @@ public static Flux withSentryForkedRoots(final @NotNull Flux flux) {
*/
public static Flux withSentryScopes(
final @NotNull Flux flux, final @NotNull IScopes scopes) {
- /**
+ /*
* WARNING: Cannot set the scopes as current. It would be used by others to fork again causing
* shared scopes and thus leading to issues like unrelated breadcrumbs showing up in events.
*/
diff --git a/sentry-samples/sentry-samples-android/build.gradle.kts b/sentry-samples/sentry-samples-android/build.gradle.kts
index 4fee4a1b92a..cf4b054e354 100644
--- a/sentry-samples/sentry-samples-android/build.gradle.kts
+++ b/sentry-samples/sentry-samples-android/build.gradle.kts
@@ -129,14 +129,6 @@ android {
}
}
- // Java 11 b/c androidx.room3 requires it.
- compileOptions {
- sourceCompatibility = JavaVersion.VERSION_11
- targetCompatibility = JavaVersion.VERSION_11
- }
-
- kotlin { compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11 }
-
androidComponents.onVariants { variant ->
variant.buildConfigFields?.put(
"USE_SAGP",
diff --git a/sentry-samples/sentry-samples-console-opentelemetry-noagent/build.gradle.kts b/sentry-samples/sentry-samples-console-opentelemetry-noagent/build.gradle.kts
index a71f0bb9040..57d1dea0e8d 100644
--- a/sentry-samples/sentry-samples-console-opentelemetry-noagent/build.gradle.kts
+++ b/sentry-samples/sentry-samples-console-opentelemetry-noagent/build.gradle.kts
@@ -11,23 +11,9 @@ plugins {
application { mainClass.set("io.sentry.samples.console.Main") }
-java.sourceCompatibility = JavaVersion.VERSION_17
-
-java.targetCompatibility = JavaVersion.VERSION_17
-
-configure {
- sourceCompatibility = JavaVersion.VERSION_17
- targetCompatibility = JavaVersion.VERSION_17
-}
-
-tasks.withType().configureEach {
- compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
-}
-
tasks.withType().configureEach {
kotlin {
compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict")
- compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
}
}
diff --git a/sentry-samples/sentry-samples-console-otlp/build.gradle.kts b/sentry-samples/sentry-samples-console-otlp/build.gradle.kts
index 491583175ae..58a8578c7d1 100644
--- a/sentry-samples/sentry-samples-console-otlp/build.gradle.kts
+++ b/sentry-samples/sentry-samples-console-otlp/build.gradle.kts
@@ -11,23 +11,9 @@ plugins {
application { mainClass.set("io.sentry.samples.console.Main") }
-java.sourceCompatibility = JavaVersion.VERSION_17
-
-java.targetCompatibility = JavaVersion.VERSION_17
-
-configure {
- sourceCompatibility = JavaVersion.VERSION_17
- targetCompatibility = JavaVersion.VERSION_17
-}
-
-tasks.withType().configureEach {
- compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
-}
-
tasks.withType().configureEach {
kotlin {
compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict")
- compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
}
}
diff --git a/sentry-samples/sentry-samples-console/build.gradle.kts b/sentry-samples/sentry-samples-console/build.gradle.kts
index d714a0ed541..f0b0d862896 100644
--- a/sentry-samples/sentry-samples-console/build.gradle.kts
+++ b/sentry-samples/sentry-samples-console/build.gradle.kts
@@ -11,23 +11,9 @@ plugins {
application { mainClass.set("io.sentry.samples.console.Main") }
-java.sourceCompatibility = JavaVersion.VERSION_17
-
-java.targetCompatibility = JavaVersion.VERSION_17
-
-configure {
- sourceCompatibility = JavaVersion.VERSION_17
- targetCompatibility = JavaVersion.VERSION_17
-}
-
-tasks.withType().configureEach {
- compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
-}
-
tasks.withType().configureEach {
kotlin {
compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict")
- compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
}
}
diff --git a/sentry-samples/sentry-samples-jul/build.gradle.kts b/sentry-samples/sentry-samples-jul/build.gradle.kts
index 3edf8e427a7..6fa4bbb8c8b 100644
--- a/sentry-samples/sentry-samples-jul/build.gradle.kts
+++ b/sentry-samples/sentry-samples-jul/build.gradle.kts
@@ -11,19 +11,9 @@ plugins {
application { mainClass.set("io.sentry.samples.jul.Main") }
-java.sourceCompatibility = JavaVersion.VERSION_17
-
-java.targetCompatibility = JavaVersion.VERSION_17
-
-configure {
- sourceCompatibility = JavaVersion.VERSION_17
- targetCompatibility = JavaVersion.VERSION_17
-}
-
tasks.withType().configureEach {
kotlin {
compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict")
- compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
}
}
diff --git a/sentry-samples/sentry-samples-log4j2/build.gradle.kts b/sentry-samples/sentry-samples-log4j2/build.gradle.kts
index 809167d040c..901604d2cff 100644
--- a/sentry-samples/sentry-samples-log4j2/build.gradle.kts
+++ b/sentry-samples/sentry-samples-log4j2/build.gradle.kts
@@ -11,19 +11,9 @@ plugins {
application { mainClass.set("io.sentry.samples.log4j2.Main") }
-java.sourceCompatibility = JavaVersion.VERSION_17
-
-java.targetCompatibility = JavaVersion.VERSION_17
-
-configure {
- sourceCompatibility = JavaVersion.VERSION_17
- targetCompatibility = JavaVersion.VERSION_17
-}
-
tasks.withType().configureEach {
kotlin {
compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict")
- compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
}
}
diff --git a/sentry-samples/sentry-samples-logback/build.gradle.kts b/sentry-samples/sentry-samples-logback/build.gradle.kts
index 8bbc70a8fbb..6d6e7051030 100644
--- a/sentry-samples/sentry-samples-logback/build.gradle.kts
+++ b/sentry-samples/sentry-samples-logback/build.gradle.kts
@@ -11,19 +11,9 @@ plugins {
application { mainClass.set("io.sentry.samples.logback.Main") }
-java.sourceCompatibility = JavaVersion.VERSION_17
-
-java.targetCompatibility = JavaVersion.VERSION_17
-
-configure {
- sourceCompatibility = JavaVersion.VERSION_17
- targetCompatibility = JavaVersion.VERSION_17
-}
-
tasks.withType().configureEach {
kotlin {
compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict")
- compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
}
}
diff --git a/sentry-samples/sentry-samples-spring-7/build.gradle.kts b/sentry-samples/sentry-samples-spring-7/build.gradle.kts
index 8770dd8d380..82a18d86c73 100644
--- a/sentry-samples/sentry-samples-spring-7/build.gradle.kts
+++ b/sentry-samples/sentry-samples-spring-7/build.gradle.kts
@@ -22,10 +22,6 @@ group = "io.sentry.sample.spring-7"
version = "0.0.1-SNAPSHOT"
-java.sourceCompatibility = JavaVersion.VERSION_17
-
-java.targetCompatibility = JavaVersion.VERSION_17
-
dependencyManagement {
imports {
mavenBom(SpringBootPlugin.BOM_COORDINATES)
@@ -65,7 +61,6 @@ tasks.withType().configureEach {
// skip metadata version check, as Spring 7 / Spring Boot 4 is
// compiled against a newer version of Kotlin
compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict", "-Xskip-metadata-version-check")
- compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
}
diff --git a/sentry-samples/sentry-samples-spring-boot-4-log4j2/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-4-log4j2/build.gradle.kts
index 2ca03bfc284..06cbdbe9400 100644
--- a/sentry-samples/sentry-samples-spring-boot-4-log4j2/build.gradle.kts
+++ b/sentry-samples/sentry-samples-spring-boot-4-log4j2/build.gradle.kts
@@ -13,22 +13,12 @@ group = "io.sentry.sample.spring-boot-4-log4j2"
version = "0.0.1-SNAPSHOT"
-java.sourceCompatibility = JavaVersion.VERSION_17
-
-java.targetCompatibility = JavaVersion.VERSION_17
-
-configure {
- sourceCompatibility = JavaVersion.VERSION_17
- targetCompatibility = JavaVersion.VERSION_17
-}
-
tasks.withType().configureEach {
kotlin {
explicitApi()
// skip metadata version check, as Spring 7 / Spring Boot 4 is
// compiled against a newer version of Kotlin
compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict", "-Xskip-metadata-version-check")
- compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
}
diff --git a/sentry-samples/sentry-samples-spring-boot-4-opentelemetry-noagent/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-4-opentelemetry-noagent/build.gradle.kts
index a2fefae6bac..bfd59790ce2 100644
--- a/sentry-samples/sentry-samples-spring-boot-4-opentelemetry-noagent/build.gradle.kts
+++ b/sentry-samples/sentry-samples-spring-boot-4-opentelemetry-noagent/build.gradle.kts
@@ -13,22 +13,12 @@ group = "io.sentry.sample.spring-boot-4"
version = "0.0.1-SNAPSHOT"
-java.sourceCompatibility = JavaVersion.VERSION_17
-
-java.targetCompatibility = JavaVersion.VERSION_17
-
-configure {
- sourceCompatibility = JavaVersion.VERSION_17
- targetCompatibility = JavaVersion.VERSION_17
-}
-
tasks.withType().configureEach {
kotlin {
explicitApi()
// skip metadata version check, as Spring 7 / Spring Boot 4 is
// compiled against a newer version of Kotlin
compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict", "-Xskip-metadata-version-check")
- compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
}
diff --git a/sentry-samples/sentry-samples-spring-boot-4-opentelemetry/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-4-opentelemetry/build.gradle.kts
index 112465bb5fd..15bb3fca8a8 100644
--- a/sentry-samples/sentry-samples-spring-boot-4-opentelemetry/build.gradle.kts
+++ b/sentry-samples/sentry-samples-spring-boot-4-opentelemetry/build.gradle.kts
@@ -14,22 +14,12 @@ group = "io.sentry.sample.spring-boot-4"
version = "0.0.1-SNAPSHOT"
-java.sourceCompatibility = JavaVersion.VERSION_17
-
-java.targetCompatibility = JavaVersion.VERSION_17
-
-configure {
- sourceCompatibility = JavaVersion.VERSION_17
- targetCompatibility = JavaVersion.VERSION_17
-}
-
tasks.withType().configureEach {
kotlin {
explicitApi()
// skip metadata version check, as Spring 7 / Spring Boot 4 is
// compiled against a newer version of Kotlin
compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict", "-Xskip-metadata-version-check")
- compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
}
diff --git a/sentry-samples/sentry-samples-spring-boot-4-otlp/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-4-otlp/build.gradle.kts
index d995d39de2a..c5bc2b96fb3 100644
--- a/sentry-samples/sentry-samples-spring-boot-4-otlp/build.gradle.kts
+++ b/sentry-samples/sentry-samples-spring-boot-4-otlp/build.gradle.kts
@@ -13,22 +13,12 @@ group = "io.sentry.sample.spring-boot-4-otlp"
version = "0.0.1-SNAPSHOT"
-java.sourceCompatibility = JavaVersion.VERSION_17
-
-java.targetCompatibility = JavaVersion.VERSION_17
-
-configure {
- sourceCompatibility = JavaVersion.VERSION_17
- targetCompatibility = JavaVersion.VERSION_17
-}
-
tasks.withType().configureEach {
kotlin {
explicitApi()
// skip metadata version check, as Spring 7 / Spring Boot 4 is
// compiled against a newer version of Kotlin
compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict", "-Xskip-metadata-version-check")
- compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
}
diff --git a/sentry-samples/sentry-samples-spring-boot-4-webflux/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-4-webflux/build.gradle.kts
index e5b44c1793a..c0c021e8320 100644
--- a/sentry-samples/sentry-samples-spring-boot-4-webflux/build.gradle.kts
+++ b/sentry-samples/sentry-samples-spring-boot-4-webflux/build.gradle.kts
@@ -13,10 +13,6 @@ group = "io.sentry.sample.spring-boot-4-webflux"
version = "0.0.1-SNAPSHOT"
-java.sourceCompatibility = JavaVersion.VERSION_17
-
-java.targetCompatibility = JavaVersion.VERSION_17
-
dependencies {
implementation(Config.Libs.kotlinReflect)
implementation(kotlin(Config.kotlinStdLib, KotlinCompilerVersion.VERSION))
@@ -53,7 +49,6 @@ tasks.withType().configureEach {
// skip metadata version check, as Spring 7 / Spring Boot 4 is
// compiled against a newer version of Kotlin
compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict", "-Xskip-metadata-version-check")
- compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
}
diff --git a/sentry-samples/sentry-samples-spring-boot-4/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-4/build.gradle.kts
index 3ec1817ce66..00b85d45bd5 100644
--- a/sentry-samples/sentry-samples-spring-boot-4/build.gradle.kts
+++ b/sentry-samples/sentry-samples-spring-boot-4/build.gradle.kts
@@ -13,22 +13,12 @@ group = "io.sentry.sample.spring-boot-4"
version = "0.0.1-SNAPSHOT"
-java.sourceCompatibility = JavaVersion.VERSION_17
-
-java.targetCompatibility = JavaVersion.VERSION_17
-
-configure {
- sourceCompatibility = JavaVersion.VERSION_17
- targetCompatibility = JavaVersion.VERSION_17
-}
-
tasks.withType().configureEach {
kotlin {
explicitApi()
// skip metadata version check, as Spring 7 / Spring Boot 4 is
// compiled against a newer version of Kotlin
compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict", "-Xskip-metadata-version-check")
- compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
}
diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta-log4j2/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-jakarta-log4j2/build.gradle.kts
index 9ac03b5ebf8..3535e1232e2 100644
--- a/sentry-samples/sentry-samples-spring-boot-jakarta-log4j2/build.gradle.kts
+++ b/sentry-samples/sentry-samples-spring-boot-jakarta-log4j2/build.gradle.kts
@@ -1,5 +1,4 @@
import org.jetbrains.kotlin.config.KotlinCompilerVersion
-import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
@@ -14,10 +13,6 @@ group = "io.sentry.sample.spring-boot-jakarta-log4j2"
version = "0.0.1-SNAPSHOT"
-java.sourceCompatibility = JavaVersion.VERSION_17
-
-java.targetCompatibility = JavaVersion.VERSION_17
-
dependencyManagement {
imports {
mavenBom("org.springframework.boot:spring-boot-dependencies:${libs.versions.springboot3.get()}")
@@ -27,17 +22,9 @@ dependencyManagement {
// Apollo 4.x requires coroutines 1.9.0+, override Spring Boot's managed version
extra["kotlin-coroutines.version"] = "1.9.0"
-configure {
- sourceCompatibility = JavaVersion.VERSION_17
- targetCompatibility = JavaVersion.VERSION_17
-}
-
-tasks.withType().configureEach { compilerOptions.jvmTarget = JvmTarget.JVM_17 }
-
tasks.withType().configureEach {
kotlin {
compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict")
- compilerOptions.jvmTarget = JvmTarget.JVM_17
}
}
diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/build.gradle.kts
index 6d1549842ce..da761af1f62 100644
--- a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/build.gradle.kts
+++ b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry-noagent/build.gradle.kts
@@ -1,5 +1,4 @@
import org.jetbrains.kotlin.config.KotlinCompilerVersion
-import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
@@ -14,10 +13,6 @@ group = "io.sentry.sample.spring-boot-jakarta"
version = "0.0.1-SNAPSHOT"
-java.sourceCompatibility = JavaVersion.VERSION_17
-
-java.targetCompatibility = JavaVersion.VERSION_17
-
dependencyManagement {
imports {
mavenBom("org.springframework.boot:spring-boot-dependencies:${libs.versions.springboot3.get()}")
@@ -28,16 +23,9 @@ dependencyManagement {
// Apollo 4.x requires coroutines 1.9.0+, override Spring Boot's managed version
extra["kotlin-coroutines.version"] = "1.9.0"
-configure {
- sourceCompatibility = JavaVersion.VERSION_17
- targetCompatibility = JavaVersion.VERSION_17
-}
-
tasks.withType().configureEach {
- compilerOptions.jvmTarget = JvmTarget.JVM_17
kotlin {
compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict")
- compilerOptions.jvmTarget = JvmTarget.JVM_17
}
}
diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/build.gradle.kts
index bfe39c0dfab..9b59911bd34 100644
--- a/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/build.gradle.kts
+++ b/sentry-samples/sentry-samples-spring-boot-jakarta-opentelemetry/build.gradle.kts
@@ -1,5 +1,4 @@
import org.jetbrains.kotlin.config.KotlinCompilerVersion
-import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.springframework.boot.gradle.tasks.run.BootRun
@@ -15,10 +14,6 @@ group = "io.sentry.sample.spring-boot-jakarta"
version = "0.0.1-SNAPSHOT"
-java.sourceCompatibility = JavaVersion.VERSION_17
-
-java.targetCompatibility = JavaVersion.VERSION_17
-
dependencyManagement {
imports {
mavenBom("org.springframework.boot:spring-boot-dependencies:${libs.versions.springboot3.get()}")
@@ -28,17 +23,9 @@ dependencyManagement {
// Apollo 4.x requires coroutines 1.9.0+, override Spring Boot's managed version
extra["kotlin-coroutines.version"] = "1.9.0"
-configure {
- sourceCompatibility = JavaVersion.VERSION_17
- targetCompatibility = JavaVersion.VERSION_17
-}
-
-tasks.withType().configureEach { compilerOptions.jvmTarget = JvmTarget.JVM_17 }
-
tasks.withType().configureEach {
kotlin {
compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict")
- compilerOptions.jvmTarget = JvmTarget.JVM_17
}
}
diff --git a/sentry-samples/sentry-samples-spring-boot-jakarta/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-jakarta/build.gradle.kts
index 722ccc69d3e..cdc5753a9c5 100644
--- a/sentry-samples/sentry-samples-spring-boot-jakarta/build.gradle.kts
+++ b/sentry-samples/sentry-samples-spring-boot-jakarta/build.gradle.kts
@@ -1,5 +1,4 @@
import org.jetbrains.kotlin.config.KotlinCompilerVersion
-import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
@@ -14,10 +13,6 @@ group = "io.sentry.sample.spring-boot-jakarta"
version = "0.0.1-SNAPSHOT"
-java.sourceCompatibility = JavaVersion.VERSION_17
-
-java.targetCompatibility = JavaVersion.VERSION_17
-
dependencyManagement {
imports {
mavenBom("org.springframework.boot:spring-boot-dependencies:${libs.versions.springboot3.get()}")
@@ -27,17 +22,9 @@ dependencyManagement {
// Apollo 4.x requires coroutines 1.9.0+, override Spring Boot's managed version
extra["kotlin-coroutines.version"] = "1.9.0"
-configure {
- sourceCompatibility = JavaVersion.VERSION_17
- targetCompatibility = JavaVersion.VERSION_17
-}
-
-tasks.withType().configureEach { compilerOptions.jvmTarget = JvmTarget.JVM_17 }
-
tasks.withType().configureEach {
kotlin {
compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict")
- compilerOptions.jvmTarget = JvmTarget.JVM_17
}
}
diff --git a/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/build.gradle.kts
index 466c4fa7b58..5ffc83b7f65 100644
--- a/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/build.gradle.kts
+++ b/sentry-samples/sentry-samples-spring-boot-opentelemetry-noagent/build.gradle.kts
@@ -1,5 +1,4 @@
import org.jetbrains.kotlin.config.KotlinCompilerVersion
-import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
@@ -11,16 +10,22 @@ plugins {
id("io.sentry.systemtest")
}
+// Spring scans this app's own bytecode with its repackaged ASM at startup, and the oldest version
+// the Spring Boot 2.x matrix covers (2.4.13, Spring 5.3.13) fails on class files as new as the
+// toolchain's: "Unsupported class file major version 65". Only the app is scanned, so its test
+// code keeps following the toolchain.
+tasks.named("compileJava") { options.release.set(11) }
+
+tasks.named("compileKotlin") {
+ compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11
+}
+
application { mainClass.set("io.sentry.samples.spring.boot.SentryDemoApplication") }
group = "io.sentry.sample.spring-boot"
version = "0.0.1-SNAPSHOT"
-java.sourceCompatibility = JavaVersion.VERSION_11
-
-java.targetCompatibility = JavaVersion.VERSION_11
-
fun springBoot2SupportsOptionalIntegrations(): Boolean {
val version = libs.versions.springboot2.get().removeSuffix(".RELEASE")
val parts = version.split(".").map { it.toIntOrNull() ?: 0 }
@@ -33,17 +38,9 @@ val includeGraphql =
!project.hasProperty("excludeGraphql") && springBoot2SupportsOptionalIntegrations()
val includeKafka = !project.hasProperty("excludeKafka") && springBoot2SupportsOptionalIntegrations()
-configure {
- sourceCompatibility = JavaVersion.VERSION_11
- targetCompatibility = JavaVersion.VERSION_11
-}
-
-tasks.withType().configureEach { compilerOptions.jvmTarget = JvmTarget.JVM_11 }
-
tasks.withType().configureEach {
kotlin {
compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict")
- compilerOptions.jvmTarget = JvmTarget.JVM_11
}
}
diff --git a/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts
index f27ee6b2346..3b7f56523df 100644
--- a/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts
+++ b/sentry-samples/sentry-samples-spring-boot-opentelemetry/build.gradle.kts
@@ -1,5 +1,4 @@
import org.jetbrains.kotlin.config.KotlinCompilerVersion
-import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
@@ -11,16 +10,22 @@ plugins {
id("io.sentry.systemtest")
}
+// Spring scans this app's own bytecode with its repackaged ASM at startup, and the oldest version
+// the Spring Boot 2.x matrix covers (2.4.13, Spring 5.3.13) fails on class files as new as the
+// toolchain's: "Unsupported class file major version 65". Only the app is scanned, so its test
+// code keeps following the toolchain.
+tasks.named("compileJava") { options.release.set(11) }
+
+tasks.named("compileKotlin") {
+ compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11
+}
+
application { mainClass.set("io.sentry.samples.spring.boot.SentryDemoApplication") }
group = "io.sentry.sample.spring-boot"
version = "0.0.1-SNAPSHOT"
-java.sourceCompatibility = JavaVersion.VERSION_11
-
-java.targetCompatibility = JavaVersion.VERSION_11
-
fun springBoot2SupportsOptionalIntegrations(): Boolean {
val version = libs.versions.springboot2.get().removeSuffix(".RELEASE")
val parts = version.split(".").map { it.toIntOrNull() ?: 0 }
@@ -33,16 +38,9 @@ val includeGraphql =
!project.hasProperty("excludeGraphql") && springBoot2SupportsOptionalIntegrations()
val includeKafka = !project.hasProperty("excludeKafka") && springBoot2SupportsOptionalIntegrations()
-configure {
- sourceCompatibility = JavaVersion.VERSION_11
- targetCompatibility = JavaVersion.VERSION_11
-}
-
tasks.withType().configureEach {
- compilerOptions.jvmTarget = JvmTarget.JVM_11
kotlin {
compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict")
- compilerOptions.jvmTarget = JvmTarget.JVM_11
}
}
diff --git a/sentry-samples/sentry-samples-spring-boot-webflux-jakarta/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-webflux-jakarta/build.gradle.kts
index 08f74e90baa..342aaa0d70c 100644
--- a/sentry-samples/sentry-samples-spring-boot-webflux-jakarta/build.gradle.kts
+++ b/sentry-samples/sentry-samples-spring-boot-webflux-jakarta/build.gradle.kts
@@ -1,5 +1,4 @@
import org.jetbrains.kotlin.config.KotlinCompilerVersion
-import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
@@ -14,10 +13,6 @@ group = "io.sentry.sample.spring-boot-webflux-jakarta"
version = "0.0.1-SNAPSHOT"
-java.sourceCompatibility = JavaVersion.VERSION_17
-
-java.targetCompatibility = JavaVersion.VERSION_17
-
dependencyManagement {
imports {
mavenBom("org.springframework.boot:spring-boot-dependencies:${libs.versions.springboot3.get()}")
@@ -59,7 +54,6 @@ dependencies {
tasks.withType().configureEach {
kotlin {
compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict")
- compilerOptions.jvmTarget = JvmTarget.JVM_17
}
}
diff --git a/sentry-samples/sentry-samples-spring-boot-webflux/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot-webflux/build.gradle.kts
index 1ef3a196e9c..fe1859c0df7 100644
--- a/sentry-samples/sentry-samples-spring-boot-webflux/build.gradle.kts
+++ b/sentry-samples/sentry-samples-spring-boot-webflux/build.gradle.kts
@@ -1,5 +1,4 @@
import org.jetbrains.kotlin.config.KotlinCompilerVersion
-import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
@@ -11,16 +10,22 @@ plugins {
id("io.sentry.systemtest")
}
+// Spring scans this app's own bytecode with its repackaged ASM at startup, and the oldest version
+// the Spring Boot 2.x matrix covers (2.4.13, Spring 5.3.13) fails on class files as new as the
+// toolchain's: "Unsupported class file major version 65". Only the app is scanned, so its test
+// code keeps following the toolchain.
+tasks.named("compileJava") { options.release.set(11) }
+
+tasks.named("compileKotlin") {
+ compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11
+}
+
application { mainClass.set("io.sentry.samples.spring.boot.SentryDemoApplication") }
group = "io.sentry.sample.spring-boot"
version = "0.0.1-SNAPSHOT"
-java.sourceCompatibility = JavaVersion.VERSION_11
-
-java.targetCompatibility = JavaVersion.VERSION_11
-
fun springBoot2SupportsGraphql(): Boolean {
val version = libs.versions.springboot2.get().removeSuffix(".RELEASE")
val parts = version.split(".").map { it.toIntOrNull() ?: 0 }
@@ -94,7 +99,6 @@ configure {
tasks.withType().configureEach {
kotlin {
compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict")
- compilerOptions.jvmTarget = JvmTarget.JVM_11
}
}
diff --git a/sentry-samples/sentry-samples-spring-boot/build.gradle.kts b/sentry-samples/sentry-samples-spring-boot/build.gradle.kts
index 86ed855e2d3..316e98ebdb6 100644
--- a/sentry-samples/sentry-samples-spring-boot/build.gradle.kts
+++ b/sentry-samples/sentry-samples-spring-boot/build.gradle.kts
@@ -1,5 +1,4 @@
import org.jetbrains.kotlin.config.KotlinCompilerVersion
-import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
@@ -11,16 +10,22 @@ plugins {
id("io.sentry.systemtest")
}
+// Spring scans this app's own bytecode with its repackaged ASM at startup, and the oldest version
+// the Spring Boot 2.x matrix covers (2.4.13, Spring 5.3.13) fails on class files as new as the
+// toolchain's: "Unsupported class file major version 65". Only the app is scanned, so its test
+// code keeps following the toolchain.
+tasks.named("compileJava") { options.release.set(11) }
+
+tasks.named("compileKotlin") {
+ compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11
+}
+
application { mainClass.set("io.sentry.samples.spring.boot.SentryDemoApplication") }
group = "io.sentry.sample.spring-boot"
version = "0.0.1-SNAPSHOT"
-java.sourceCompatibility = JavaVersion.VERSION_11
-
-java.targetCompatibility = JavaVersion.VERSION_11
-
fun springBoot2SupportsOptionalIntegrations(): Boolean {
val version = libs.versions.springboot2.get().removeSuffix(".RELEASE")
val parts = version.split(".").map { it.toIntOrNull() ?: 0 }
@@ -33,15 +38,9 @@ val includeGraphql =
!project.hasProperty("excludeGraphql") && springBoot2SupportsOptionalIntegrations()
val includeKafka = !project.hasProperty("excludeKafka") && springBoot2SupportsOptionalIntegrations()
-configure {
- sourceCompatibility = JavaVersion.VERSION_11
- targetCompatibility = JavaVersion.VERSION_11
-}
-
tasks.withType().configureEach {
kotlin {
compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict")
- compilerOptions.jvmTarget = JvmTarget.JVM_11
}
}
diff --git a/sentry-samples/sentry-samples-spring-jakarta/build.gradle.kts b/sentry-samples/sentry-samples-spring-jakarta/build.gradle.kts
index 2d28ed2531f..022b9fbb0c6 100644
--- a/sentry-samples/sentry-samples-spring-jakarta/build.gradle.kts
+++ b/sentry-samples/sentry-samples-spring-jakarta/build.gradle.kts
@@ -1,4 +1,3 @@
-import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
@@ -20,10 +19,6 @@ group = "io.sentry.sample.spring-jakarta"
version = "0.0.1-SNAPSHOT"
-java.sourceCompatibility = JavaVersion.VERSION_17
-
-java.targetCompatibility = JavaVersion.VERSION_17
-
// Apollo 4.x requires coroutines 1.9.0+, override Spring Boot's managed version
extra["kotlin-coroutines.version"] = "1.9.0"
@@ -64,7 +59,6 @@ dependencies {
tasks.withType().configureEach {
kotlin {
compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict")
- compilerOptions.jvmTarget = JvmTarget.JVM_17
}
}
diff --git a/sentry-samples/sentry-samples-spring/build.gradle.kts b/sentry-samples/sentry-samples-spring/build.gradle.kts
index 7c6b6a915fc..8ae94a2e367 100644
--- a/sentry-samples/sentry-samples-spring/build.gradle.kts
+++ b/sentry-samples/sentry-samples-spring/build.gradle.kts
@@ -1,4 +1,3 @@
-import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
@@ -11,6 +10,16 @@ plugins {
id("io.sentry.systemtest")
}
+// Spring scans this app's own bytecode with its repackaged ASM at startup, and the oldest version
+// the Spring Boot 2.x matrix covers (2.4.13, Spring 5.3.13) fails on class files as new as the
+// toolchain's: "Unsupported class file major version 65". Only the app is scanned, so its test
+// code keeps following the toolchain.
+tasks.named("compileJava") { options.release.set(8) }
+
+tasks.named("compileKotlin") {
+ compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
+}
+
application { mainClass.set("io.sentry.samples.spring.Main") }
// Ensure WAR is up to date before run task
@@ -20,11 +29,6 @@ group = "io.sentry.sample.spring"
version = "0.0.1-SNAPSHOT"
-java {
- sourceCompatibility = JavaVersion.VERSION_1_8
- targetCompatibility = JavaVersion.VERSION_1_8
-}
-
// Apollo 4.x requires coroutines 1.9.0+, override Spring Boot's managed version
extra["kotlin-coroutines.version"] = "1.9.0"
@@ -65,7 +69,6 @@ dependencies {
tasks.withType().configureEach {
kotlin {
compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict")
- compilerOptions.jvmTarget = JvmTarget.JVM_1_8
}
}
diff --git a/sentry-servlet-jakarta/build.gradle.kts b/sentry-servlet-jakarta/build.gradle.kts
index 5762a4ae52b..b9d6ffc2ec4 100644
--- a/sentry-servlet-jakarta/build.gradle.kts
+++ b/sentry-servlet-jakarta/build.gradle.kts
@@ -11,7 +11,7 @@ plugins {
id("io.sentry.animalsniffer")
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
diff --git a/sentry-servlet/build.gradle.kts b/sentry-servlet/build.gradle.kts
index c2e3fe8e52e..08ac7d45284 100644
--- a/sentry-servlet/build.gradle.kts
+++ b/sentry-servlet/build.gradle.kts
@@ -11,7 +11,7 @@ plugins {
id("io.sentry.animalsniffer")
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
diff --git a/sentry-spotlight/build.gradle.kts b/sentry-spotlight/build.gradle.kts
index a8d538c2e2e..072cb360e61 100644
--- a/sentry-spotlight/build.gradle.kts
+++ b/sentry-spotlight/build.gradle.kts
@@ -11,7 +11,7 @@ plugins {
alias(libs.plugins.buildconfig)
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
}
@@ -28,7 +28,7 @@ dependencies {
testImplementation(kotlin(Config.kotlinStdLib))
testImplementation(libs.kotlin.test.junit)
testImplementation(libs.mockito.kotlin)
- testImplementation(libs.mockito.inline)
+ testImplementation(libs.mockito.core)
testImplementation(projects.sentryTestSupport)
}
diff --git a/sentry-spring-7/build.gradle.kts b/sentry-spring-7/build.gradle.kts
index 4e5ea54d294..c848c9416a0 100644
--- a/sentry-spring-7/build.gradle.kts
+++ b/sentry-spring-7/build.gradle.kts
@@ -12,12 +12,10 @@ plugins {
alias(libs.plugins.springboot4) apply false
}
-configure {
- sourceCompatibility = JavaVersion.VERSION_17
- targetCompatibility = JavaVersion.VERSION_17
-}
+// Published code targets Java 17. Test code is not published and follows the toolchain.
+tasks.named("compileJava") { options.release.set(17) }
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions {
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17)
languageVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_1)
@@ -67,8 +65,8 @@ dependencies {
testImplementation(libs.context.propagation)
testImplementation(libs.graphql.java24)
testImplementation(libs.kotlin.test.junit)
- testImplementation(libs.mockito.kotlin.spring7)
- testImplementation(libs.mockito.inline)
+ testImplementation(libs.mockito.kotlin)
+ testImplementation(libs.mockito.core)
testImplementation(libs.springboot4.starter.aspectj)
testImplementation(libs.springboot4.starter.graphql)
testImplementation(libs.spring.kafka4)
diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/HttpServletRequestSentryUserProvider.java b/sentry-spring-7/src/main/java/io/sentry/spring7/HttpServletRequestSentryUserProvider.java
index 44ae584ec17..27720570a2e 100644
--- a/sentry-spring-7/src/main/java/io/sentry/spring7/HttpServletRequestSentryUserProvider.java
+++ b/sentry-spring-7/src/main/java/io/sentry/spring7/HttpServletRequestSentryUserProvider.java
@@ -25,9 +25,8 @@ public HttpServletRequestSentryUserProvider(final @NotNull SentryOptions options
public @Nullable User provideUser() {
if (options.getDataCollectionResolver().isUserInfo()) {
final RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
- if (requestAttributes instanceof ServletRequestAttributes) {
- final ServletRequestAttributes servletRequestAttributes =
- (ServletRequestAttributes) requestAttributes;
+ if (requestAttributes instanceof ServletRequestAttributes servletRequestAttributes) {
+
final HttpServletRequest request = servletRequestAttributes.getRequest();
final User user = new User();
diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/SentryInitBeanPostProcessor.java b/sentry-spring-7/src/main/java/io/sentry/spring7/SentryInitBeanPostProcessor.java
index 4b778d68649..b36df8be77b 100644
--- a/sentry-spring-7/src/main/java/io/sentry/spring7/SentryInitBeanPostProcessor.java
+++ b/sentry-spring-7/src/main/java/io/sentry/spring7/SentryInitBeanPostProcessor.java
@@ -42,8 +42,7 @@ public SentryInitBeanPostProcessor() {
@SuppressWarnings({"unchecked", "deprecation"})
public @NotNull Object postProcessAfterInitialization(
final @NotNull Object bean, @NotNull final String beanName) throws BeansException {
- if (bean instanceof SentryOptions) {
- final SentryOptions options = (SentryOptions) bean;
+ if (bean instanceof SentryOptions options) {
if (applicationContext != null) {
applicationContext
diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/cache/SentryCacheBeanPostProcessor.java b/sentry-spring-7/src/main/java/io/sentry/spring7/cache/SentryCacheBeanPostProcessor.java
index b6569a9953b..8c755be2dea 100644
--- a/sentry-spring-7/src/main/java/io/sentry/spring7/cache/SentryCacheBeanPostProcessor.java
+++ b/sentry-spring-7/src/main/java/io/sentry/spring7/cache/SentryCacheBeanPostProcessor.java
@@ -16,8 +16,8 @@ public final class SentryCacheBeanPostProcessor implements BeanPostProcessor, Pr
@Override
public @NotNull Object postProcessAfterInitialization(
final @NotNull Object bean, final @NotNull String beanName) throws BeansException {
- if (bean instanceof CacheManager && !(bean instanceof SentryCacheManagerWrapper)) {
- return new SentryCacheManagerWrapper((CacheManager) bean, ScopesAdapter.getInstance());
+ if (bean instanceof CacheManager cacheManager && !(bean instanceof SentryCacheManagerWrapper)) {
+ return new SentryCacheManagerWrapper(cacheManager, ScopesAdapter.getInstance());
}
return bean;
}
diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/checkin/SentryCheckInAdvice.java b/sentry-spring-7/src/main/java/io/sentry/spring7/checkin/SentryCheckInAdvice.java
index e58e0e9dd97..a14f0d4c96a 100644
--- a/sentry-spring-7/src/main/java/io/sentry/spring7/checkin/SentryCheckInAdvice.java
+++ b/sentry-spring-7/src/main/java/io/sentry/spring7/checkin/SentryCheckInAdvice.java
@@ -44,9 +44,11 @@ public SentryCheckInAdvice(final @NotNull IScopes scopes) {
}
@Override
- public Object invoke(final @NotNull MethodInvocation invocation) throws Throwable {
+ public @Nullable Object invoke(final @NotNull MethodInvocation invocation) throws Throwable {
+ final @Nullable Object target = invocation.getThis();
final Method mostSpecificMethod =
- AopUtils.getMostSpecificMethod(invocation.getMethod(), invocation.getThis().getClass());
+ AopUtils.getMostSpecificMethod(
+ invocation.getMethod(), target != null ? target.getClass() : null);
@Nullable
SentryCheckIn checkInAnnotation =
diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/exception/SentryCaptureExceptionParameterAdvice.java b/sentry-spring-7/src/main/java/io/sentry/spring7/exception/SentryCaptureExceptionParameterAdvice.java
index cb5cba62a4d..f4c630033a8 100644
--- a/sentry-spring-7/src/main/java/io/sentry/spring7/exception/SentryCaptureExceptionParameterAdvice.java
+++ b/sentry-spring-7/src/main/java/io/sentry/spring7/exception/SentryCaptureExceptionParameterAdvice.java
@@ -11,6 +11,7 @@
import org.aopalliance.intercept.MethodInvocation;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.springframework.aop.support.AopUtils;
import org.springframework.core.annotation.AnnotationUtils;
@@ -33,17 +34,19 @@ public SentryCaptureExceptionParameterAdvice(final @NotNull IScopes scopes) {
}
@Override
- public Object invoke(final @NotNull MethodInvocation invocation) throws Throwable {
+ public @Nullable Object invoke(final @NotNull MethodInvocation invocation) throws Throwable {
+ final @Nullable Object target = invocation.getThis();
final Method mostSpecificMethod =
- AopUtils.getMostSpecificMethod(invocation.getMethod(), invocation.getThis().getClass());
+ AopUtils.getMostSpecificMethod(
+ invocation.getMethod(), target != null ? target.getClass() : null);
SentryCaptureExceptionParameter sentryCaptureExceptionParameter =
AnnotationUtils.findAnnotation(mostSpecificMethod, SentryCaptureExceptionParameter.class);
if (sentryCaptureExceptionParameter != null) {
Object[] args = invocation.getArguments();
for (Object arg : args) {
- if (arg instanceof Exception) {
- captureException((Exception) arg);
+ if (arg instanceof Exception exception) {
+ captureException(exception);
break;
}
}
diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/graphql/SentryBatchLoaderRegistry.java b/sentry-spring-7/src/main/java/io/sentry/spring7/graphql/SentryBatchLoaderRegistry.java
index 591863d906b..647da383818 100644
--- a/sentry-spring-7/src/main/java/io/sentry/spring7/graphql/SentryBatchLoaderRegistry.java
+++ b/sentry-spring-7/src/main/java/io/sentry/spring7/graphql/SentryBatchLoaderRegistry.java
@@ -108,8 +108,8 @@ public void registerMappedBatchLoader(
private @NotNull IScopes scopesFromContext(final @NotNull BatchLoaderEnvironment environment) {
Object context = environment.getContext();
- if (context instanceof GraphQLContext) {
- GraphQLContext graphqlContext = (GraphQLContext) context;
+ if (context instanceof GraphQLContext graphqlContext) {
+
return graphqlContext.getOrDefault(SENTRY_SCOPES_CONTEXT_KEY, NoOpScopes.getInstance());
}
diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/graphql/SentryGraphqlBeanPostProcessor.java b/sentry-spring-7/src/main/java/io/sentry/spring7/graphql/SentryGraphqlBeanPostProcessor.java
index 2ea390fd2dd..1a973c62031 100644
--- a/sentry-spring-7/src/main/java/io/sentry/spring7/graphql/SentryGraphqlBeanPostProcessor.java
+++ b/sentry-spring-7/src/main/java/io/sentry/spring7/graphql/SentryGraphqlBeanPostProcessor.java
@@ -12,8 +12,8 @@ public final class SentryGraphqlBeanPostProcessor implements BeanPostProcessor,
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
- if (bean instanceof BatchLoaderRegistry) {
- return new SentryBatchLoaderRegistry((BatchLoaderRegistry) bean);
+ if (bean instanceof BatchLoaderRegistry batchLoaderRegistry) {
+ return new SentryBatchLoaderRegistry(batchLoaderRegistry);
}
return bean;
}
diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/kafka/SentryKafkaProducerBeanPostProcessor.java b/sentry-spring-7/src/main/java/io/sentry/spring7/kafka/SentryKafkaProducerBeanPostProcessor.java
index eff0b4154bb..c8b41d4d0f7 100644
--- a/sentry-spring-7/src/main/java/io/sentry/spring7/kafka/SentryKafkaProducerBeanPostProcessor.java
+++ b/sentry-spring-7/src/main/java/io/sentry/spring7/kafka/SentryKafkaProducerBeanPostProcessor.java
@@ -36,8 +36,8 @@ public final class SentryKafkaProducerBeanPostProcessor
@SuppressWarnings({"unchecked", "rawtypes"})
public @NotNull Object postProcessAfterInitialization(
final @NotNull Object bean, final @NotNull String beanName) throws BeansException {
- if (bean instanceof ProducerFactory) {
- final @NotNull ProducerFactory factory = (ProducerFactory) bean;
+ if (bean instanceof ProducerFactory, ?> factory) {
+
final @NotNull SentryProducerPostProcessor pp = new SentryProducerPostProcessor<>();
factory.addPostProcessor(pp);
if (!factory.getPostProcessors().contains(pp)) {
diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/kafka/SentryKafkaRecordInterceptor.java b/sentry-spring-7/src/main/java/io/sentry/spring7/kafka/SentryKafkaRecordInterceptor.java
index b2b4d20b948..dca7c7d61dd 100644
--- a/sentry-spring-7/src/main/java/io/sentry/spring7/kafka/SentryKafkaRecordInterceptor.java
+++ b/sentry-spring-7/src/main/java/io/sentry/spring7/kafka/SentryKafkaRecordInterceptor.java
@@ -196,7 +196,9 @@ private boolean isIgnored() {
if (enqueuedTimeStr != null) {
try {
final double enqueuedTimeSeconds = Double.parseDouble(enqueuedTimeStr);
- final double nowSeconds = DateUtils.millisToSeconds(System.currentTimeMillis());
+ // millisToSeconds takes a double; the cast is explicit for Error Prone's
+ // LongDoubleConversion check.
+ final double nowSeconds = DateUtils.millisToSeconds((double) System.currentTimeMillis());
final long latencyMs = (long) ((nowSeconds - enqueuedTimeSeconds) * 1000);
if (latencyMs >= 0) {
transaction.setData(SpanDataConvention.MESSAGING_MESSAGE_RECEIVE_LATENCY, latencyMs);
diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentrySpanAdvice.java b/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentrySpanAdvice.java
index 6c9a3287edc..36eb08d524c 100644
--- a/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentrySpanAdvice.java
+++ b/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentrySpanAdvice.java
@@ -35,15 +35,17 @@ public SentrySpanAdvice(final @NotNull IScopes scopes) {
@SuppressWarnings("deprecation")
@Override
- public Object invoke(final @NotNull MethodInvocation invocation) throws Throwable {
+ public @Nullable Object invoke(final @NotNull MethodInvocation invocation) throws Throwable {
final ISpan activeSpan = scopes.getSpan();
if (activeSpan == null || activeSpan.isNoOp()) {
// there is no active transaction, we do not start new span
return invocation.proceed();
} else {
+ final @Nullable Object target = invocation.getThis();
final Method mostSpecificMethod =
- AopUtils.getMostSpecificMethod(invocation.getMethod(), invocation.getThis().getClass());
+ AopUtils.getMostSpecificMethod(
+ invocation.getMethod(), target != null ? target.getClass() : null);
final Class> targetClass = invocation.getMethod().getDeclaringClass();
SentrySpan sentrySpan = AnnotationUtils.findAnnotation(mostSpecificMethod, SentrySpan.class);
if (sentrySpan == null) {
diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentrySpanClientHttpRequestInterceptor.java b/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentrySpanClientHttpRequestInterceptor.java
index 46a31245ba1..d0d0923a42b 100644
--- a/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentrySpanClientHttpRequestInterceptor.java
+++ b/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentrySpanClientHttpRequestInterceptor.java
@@ -39,7 +39,7 @@ public SentrySpanClientHttpRequestInterceptor(final @NotNull IScopes scopes) {
}
public SentrySpanClientHttpRequestInterceptor(
- final @NotNull IScopes scopes, final @NotNull boolean isRestTemplate) {
+ final @NotNull IScopes scopes, final boolean isRestTemplate) {
this.scopes = Objects.requireNonNull(scopes, "Scopes are required");
this.traceOrigin = isRestTemplate ? TRACE_ORIGIN_REST_TEMPLATE : TRACE_ORIGIN_REST_CLIENT;
}
diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentryTransactionAdvice.java b/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentryTransactionAdvice.java
index b16a6ab00ef..913ee09b2d3 100644
--- a/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentryTransactionAdvice.java
+++ b/sentry-spring-7/src/main/java/io/sentry/spring7/tracing/SentryTransactionAdvice.java
@@ -41,9 +41,11 @@ public SentryTransactionAdvice(final @NotNull IScopes scopes) {
@SuppressWarnings("deprecation")
@Override
- public Object invoke(final @NotNull MethodInvocation invocation) throws Throwable {
+ public @Nullable Object invoke(final @NotNull MethodInvocation invocation) throws Throwable {
+ final @Nullable Object target = invocation.getThis();
final Method mostSpecificMethod =
- AopUtils.getMostSpecificMethod(invocation.getMethod(), invocation.getThis().getClass());
+ AopUtils.getMostSpecificMethod(
+ invocation.getMethod(), target != null ? target.getClass() : null);
@Nullable
SentryTransaction sentryTransaction =
@@ -116,7 +118,7 @@ private static class TransactionNameAndSource {
private final @NotNull String name;
private final @NotNull TransactionNameSource source;
- public TransactionNameAndSource(
+ TransactionNameAndSource(
final @NotNull String name, final @NotNull TransactionNameSource source) {
this.name = name;
this.source = source;
diff --git a/sentry-spring-7/src/main/java/io/sentry/spring7/webflux/SentryWebExceptionHandler.java b/sentry-spring-7/src/main/java/io/sentry/spring7/webflux/SentryWebExceptionHandler.java
index 19e6fa0fc4e..421cb7a2a90 100644
--- a/sentry-spring-7/src/main/java/io/sentry/spring7/webflux/SentryWebExceptionHandler.java
+++ b/sentry-spring-7/src/main/java/io/sentry/spring7/webflux/SentryWebExceptionHandler.java
@@ -38,7 +38,7 @@ public SentryWebExceptionHandler(final @NotNull IScopes scopes) {
public @NotNull Mono handle(
final @NotNull ServerWebExchange serverWebExchange, final @NotNull Throwable ex) {
final @Nullable IScopes requestScopes =
- serverWebExchange.getAttributeOrDefault(SentryWebFilter.SENTRY_SCOPES_KEY, null);
+ serverWebExchange.getAttribute(SentryWebFilter.SENTRY_SCOPES_KEY);
final @NotNull IScopes scopesToUse = requestScopes != null ? requestScopes : scopes;
return SentryReactorUtils.withSentryScopes(
diff --git a/sentry-spring-boot-4-starter/build.gradle.kts b/sentry-spring-boot-4-starter/build.gradle.kts
index bffe53aab01..7ad300d4790 100644
--- a/sentry-spring-boot-4-starter/build.gradle.kts
+++ b/sentry-spring-boot-4-starter/build.gradle.kts
@@ -11,12 +11,10 @@ plugins {
alias(libs.plugins.springboot4) apply false
}
-configure {
- sourceCompatibility = JavaVersion.VERSION_17
- targetCompatibility = JavaVersion.VERSION_17
-}
+// Published code targets Java 17. Test code is not published and follows the toolchain.
+tasks.named("compileJava") { options.release.set(17) }
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
diff --git a/sentry-spring-boot-4/build.gradle.kts b/sentry-spring-boot-4/build.gradle.kts
index 127955c5bf0..1573e161df5 100644
--- a/sentry-spring-boot-4/build.gradle.kts
+++ b/sentry-spring-boot-4/build.gradle.kts
@@ -13,12 +13,10 @@ plugins {
alias(libs.plugins.springboot4) apply false
}
-configure {
- sourceCompatibility = JavaVersion.VERSION_17
- targetCompatibility = JavaVersion.VERSION_17
-}
+// Published code targets Java 17. Test code is not published and follows the toolchain.
+tasks.named("compileJava") { options.release.set(17) }
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions {
jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17)
languageVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9)
diff --git a/sentry-spring-boot-4/src/main/java/io/sentry/spring/boot4/SentryLog4j2Initializer.java b/sentry-spring-boot-4/src/main/java/io/sentry/spring/boot4/SentryLog4j2Initializer.java
index bb20d47a35a..d3b2d7da049 100644
--- a/sentry-spring-boot-4/src/main/java/io/sentry/spring/boot4/SentryLog4j2Initializer.java
+++ b/sentry-spring-boot-4/src/main/java/io/sentry/spring/boot4/SentryLog4j2Initializer.java
@@ -45,13 +45,12 @@ public boolean supportsEventType(final @NotNull ResolvableType eventType) {
@Override
public void onApplicationEvent(final @NotNull ApplicationEvent event) {
final Object context = LogManager.getContext(false);
- if (!(context instanceof LoggerContext)) {
+ if (!(context instanceof LoggerContext loggerContext)) {
logger.info(
"Sentry Log4j2 appender was not configured because Log4j2 Core is not the active logging backend. Log4j2 API calls may be routed through SLF4J.");
return;
}
- final LoggerContext loggerContext = (LoggerContext) context;
final Configuration configuration = loggerContext.getConfiguration();
boolean changed = false;
diff --git a/sentry-spring-boot-4/src/main/java/io/sentry/spring/boot4/SentryOkHttpClientBeanPostProcessor.java b/sentry-spring-boot-4/src/main/java/io/sentry/spring/boot4/SentryOkHttpClientBeanPostProcessor.java
index 5dd84ab413c..88099b6eea3 100644
--- a/sentry-spring-boot-4/src/main/java/io/sentry/spring/boot4/SentryOkHttpClientBeanPostProcessor.java
+++ b/sentry-spring-boot-4/src/main/java/io/sentry/spring/boot4/SentryOkHttpClientBeanPostProcessor.java
@@ -19,11 +19,10 @@ final class SentryOkHttpClientBeanPostProcessor implements BeanPostProcessor, Pr
@Override
public @NotNull Object postProcessAfterInitialization(
final @NotNull Object bean, final @NotNull String beanName) throws BeansException {
- if (!(bean instanceof OkHttpClient)) {
+ if (!(bean instanceof OkHttpClient client)) {
return bean;
}
- final @NotNull OkHttpClient client = (OkHttpClient) bean;
if (client.getClass() != OkHttpClient.class) {
ScopesAdapter.getInstance()
.getOptions()
diff --git a/sentry-spring-boot-jakarta/build.gradle.kts b/sentry-spring-boot-jakarta/build.gradle.kts
index 2b26280cd65..4d71d435def 100644
--- a/sentry-spring-boot-jakarta/build.gradle.kts
+++ b/sentry-spring-boot-jakarta/build.gradle.kts
@@ -12,12 +12,10 @@ plugins {
alias(libs.plugins.springboot3) apply false
}
-configure {
- sourceCompatibility = JavaVersion.VERSION_17
- targetCompatibility = JavaVersion.VERSION_17
-}
+// Published code targets Java 17. Test code is not published and follows the toolchain.
+tasks.named("compileJava") { options.release.set(17) }
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
diff --git a/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryLog4j2Initializer.java b/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryLog4j2Initializer.java
index 8db89bf9f20..06d946d090e 100644
--- a/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryLog4j2Initializer.java
+++ b/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryLog4j2Initializer.java
@@ -45,13 +45,12 @@ public boolean supportsEventType(final @NotNull ResolvableType eventType) {
@Override
public void onApplicationEvent(final @NotNull ApplicationEvent event) {
final Object context = LogManager.getContext(false);
- if (!(context instanceof LoggerContext)) {
+ if (!(context instanceof LoggerContext loggerContext)) {
logger.info(
"Sentry Log4j2 appender was not configured because Log4j2 Core is not the active logging backend. Log4j2 API calls may be routed through SLF4J.");
return;
}
- final LoggerContext loggerContext = (LoggerContext) context;
final Configuration configuration = loggerContext.getConfiguration();
boolean changed = false;
diff --git a/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryOkHttpClientBeanPostProcessor.java b/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryOkHttpClientBeanPostProcessor.java
index 8409240d7fe..4c0bbf6c920 100644
--- a/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryOkHttpClientBeanPostProcessor.java
+++ b/sentry-spring-boot-jakarta/src/main/java/io/sentry/spring/boot/jakarta/SentryOkHttpClientBeanPostProcessor.java
@@ -19,11 +19,10 @@ final class SentryOkHttpClientBeanPostProcessor implements BeanPostProcessor, Pr
@Override
public @NotNull Object postProcessAfterInitialization(
final @NotNull Object bean, final @NotNull String beanName) throws BeansException {
- if (!(bean instanceof OkHttpClient)) {
+ if (!(bean instanceof OkHttpClient client)) {
return bean;
}
- final @NotNull OkHttpClient client = (OkHttpClient) bean;
if (client.getClass() != OkHttpClient.class) {
ScopesAdapter.getInstance()
.getOptions()
diff --git a/sentry-spring-boot-starter-jakarta/build.gradle.kts b/sentry-spring-boot-starter-jakarta/build.gradle.kts
index c6fe511073e..63594df7a2e 100644
--- a/sentry-spring-boot-starter-jakarta/build.gradle.kts
+++ b/sentry-spring-boot-starter-jakarta/build.gradle.kts
@@ -11,12 +11,10 @@ plugins {
alias(libs.plugins.springboot3) apply false
}
-configure {
- sourceCompatibility = JavaVersion.VERSION_17
- targetCompatibility = JavaVersion.VERSION_17
-}
+// Published code targets Java 17. Test code is not published and follows the toolchain.
+tasks.named("compileJava") { options.release.set(17) }
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
diff --git a/sentry-spring-boot-starter/build.gradle.kts b/sentry-spring-boot-starter/build.gradle.kts
index cd05baecc4d..641b335becb 100644
--- a/sentry-spring-boot-starter/build.gradle.kts
+++ b/sentry-spring-boot-starter/build.gradle.kts
@@ -10,7 +10,7 @@ plugins {
alias(libs.plugins.gradle.versions)
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
diff --git a/sentry-spring-boot/build.gradle.kts b/sentry-spring-boot/build.gradle.kts
index e5aaa15eecc..121819b1e79 100644
--- a/sentry-spring-boot/build.gradle.kts
+++ b/sentry-spring-boot/build.gradle.kts
@@ -12,7 +12,7 @@ plugins {
id("io.sentry.animalsniffer")
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = JvmTarget.JVM_1_8
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
diff --git a/sentry-spring-jakarta/build.gradle.kts b/sentry-spring-jakarta/build.gradle.kts
index f103bfcbe0a..138ad1e5f16 100644
--- a/sentry-spring-jakarta/build.gradle.kts
+++ b/sentry-spring-jakarta/build.gradle.kts
@@ -12,18 +12,17 @@ plugins {
alias(libs.plugins.springboot3) apply false
}
-configure {
- sourceCompatibility = JavaVersion.VERSION_17
- targetCompatibility = JavaVersion.VERSION_17
+// Published code targets Java 17. Test code is not published and follows the toolchain.
+tasks.named("compileJava") { options.release.set(17) }
+
+kotlin {
+ compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
+ compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
+ compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict")
}
-tasks.withType().configureEach {
- kotlin {
- compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
- compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
- compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
- compilerOptions.freeCompilerArgs = listOf("-Xjsr305=strict")
- }
+tasks.named("compileKotlin") {
+ compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17
}
dependencies {
@@ -66,7 +65,7 @@ dependencies {
testImplementation(libs.graphql.java24)
testImplementation(libs.kotlin.test.junit)
testImplementation(libs.mockito.kotlin)
- testImplementation(libs.mockito.inline)
+ testImplementation(libs.mockito.core)
testImplementation(libs.springboot3.starter.aop)
testImplementation(libs.springboot3.starter.graphql)
testImplementation(libs.springboot3.starter.security)
diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/HttpServletRequestSentryUserProvider.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/HttpServletRequestSentryUserProvider.java
index b7f4646b4a8..a64eb826f04 100644
--- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/HttpServletRequestSentryUserProvider.java
+++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/HttpServletRequestSentryUserProvider.java
@@ -25,9 +25,8 @@ public HttpServletRequestSentryUserProvider(final @NotNull SentryOptions options
public @Nullable User provideUser() {
if (options.getDataCollectionResolver().isUserInfo()) {
final RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
- if (requestAttributes instanceof ServletRequestAttributes) {
- final ServletRequestAttributes servletRequestAttributes =
- (ServletRequestAttributes) requestAttributes;
+ if (requestAttributes instanceof ServletRequestAttributes servletRequestAttributes) {
+
final HttpServletRequest request = servletRequestAttributes.getRequest();
final User user = new User();
diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/SentryInitBeanPostProcessor.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/SentryInitBeanPostProcessor.java
index 4d9e63a151b..28157e0336b 100644
--- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/SentryInitBeanPostProcessor.java
+++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/SentryInitBeanPostProcessor.java
@@ -42,8 +42,7 @@ public SentryInitBeanPostProcessor() {
@SuppressWarnings({"unchecked", "deprecation"})
public @NotNull Object postProcessAfterInitialization(
final @NotNull Object bean, @NotNull final String beanName) throws BeansException {
- if (bean instanceof SentryOptions) {
- final SentryOptions options = (SentryOptions) bean;
+ if (bean instanceof SentryOptions options) {
if (applicationContext != null) {
applicationContext
diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/cache/SentryCacheBeanPostProcessor.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/cache/SentryCacheBeanPostProcessor.java
index ec9964f7abc..ad4425131ff 100644
--- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/cache/SentryCacheBeanPostProcessor.java
+++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/cache/SentryCacheBeanPostProcessor.java
@@ -16,8 +16,8 @@ public final class SentryCacheBeanPostProcessor implements BeanPostProcessor, Pr
@Override
public @NotNull Object postProcessAfterInitialization(
final @NotNull Object bean, final @NotNull String beanName) throws BeansException {
- if (bean instanceof CacheManager && !(bean instanceof SentryCacheManagerWrapper)) {
- return new SentryCacheManagerWrapper((CacheManager) bean, ScopesAdapter.getInstance());
+ if (bean instanceof CacheManager cacheManager && !(bean instanceof SentryCacheManagerWrapper)) {
+ return new SentryCacheManagerWrapper(cacheManager, ScopesAdapter.getInstance());
}
return bean;
}
diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameterAdvice.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameterAdvice.java
index c6537f853c2..5fe03f385df 100644
--- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameterAdvice.java
+++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/exception/SentryCaptureExceptionParameterAdvice.java
@@ -42,8 +42,8 @@ public Object invoke(final @NotNull MethodInvocation invocation) throws Throwabl
if (sentryCaptureExceptionParameter != null) {
Object[] args = invocation.getArguments();
for (Object arg : args) {
- if (arg instanceof Exception) {
- captureException((Exception) arg);
+ if (arg instanceof Exception exception) {
+ captureException(exception);
break;
}
}
diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/graphql/SentryBatchLoaderRegistry.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/graphql/SentryBatchLoaderRegistry.java
index 4e7c3665aae..6a9f33e65f1 100644
--- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/graphql/SentryBatchLoaderRegistry.java
+++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/graphql/SentryBatchLoaderRegistry.java
@@ -108,8 +108,8 @@ public void registerMappedBatchLoader(
private @NotNull IScopes scopesFromContext(final @NotNull BatchLoaderEnvironment environment) {
Object context = environment.getContext();
- if (context instanceof GraphQLContext) {
- GraphQLContext graphqlContext = (GraphQLContext) context;
+ if (context instanceof GraphQLContext graphqlContext) {
+
return graphqlContext.getOrDefault(SENTRY_SCOPES_CONTEXT_KEY, NoOpScopes.getInstance());
}
diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/graphql/SentryGraphqlBeanPostProcessor.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/graphql/SentryGraphqlBeanPostProcessor.java
index 5eb4374bb1f..79bc5e11ccd 100644
--- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/graphql/SentryGraphqlBeanPostProcessor.java
+++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/graphql/SentryGraphqlBeanPostProcessor.java
@@ -12,8 +12,8 @@ public final class SentryGraphqlBeanPostProcessor implements BeanPostProcessor,
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
- if (bean instanceof BatchLoaderRegistry) {
- return new SentryBatchLoaderRegistry((BatchLoaderRegistry) bean);
+ if (bean instanceof BatchLoaderRegistry batchLoaderRegistry) {
+ return new SentryBatchLoaderRegistry(batchLoaderRegistry);
}
return bean;
}
diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/kafka/SentryKafkaProducerBeanPostProcessor.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/kafka/SentryKafkaProducerBeanPostProcessor.java
index 8a06e4e338e..dc3636a2b24 100644
--- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/kafka/SentryKafkaProducerBeanPostProcessor.java
+++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/kafka/SentryKafkaProducerBeanPostProcessor.java
@@ -36,8 +36,8 @@ public final class SentryKafkaProducerBeanPostProcessor
@SuppressWarnings({"unchecked", "rawtypes"})
public @NotNull Object postProcessAfterInitialization(
final @NotNull Object bean, final @NotNull String beanName) throws BeansException {
- if (bean instanceof ProducerFactory) {
- final @NotNull ProducerFactory factory = (ProducerFactory) bean;
+ if (bean instanceof ProducerFactory, ?> factory) {
+
final @NotNull SentryProducerPostProcessor pp = new SentryProducerPostProcessor<>();
factory.addPostProcessor(pp);
if (!factory.getPostProcessors().contains(pp)) {
diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/kafka/SentryKafkaRecordInterceptor.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/kafka/SentryKafkaRecordInterceptor.java
index 72535712695..4d5abda711f 100644
--- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/kafka/SentryKafkaRecordInterceptor.java
+++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/kafka/SentryKafkaRecordInterceptor.java
@@ -196,7 +196,7 @@ private boolean isIgnored() {
if (enqueuedTimeStr != null) {
try {
final double enqueuedTimeSeconds = Double.parseDouble(enqueuedTimeStr);
- final double nowSeconds = DateUtils.millisToSeconds(System.currentTimeMillis());
+ final double nowSeconds = DateUtils.millisToSeconds((double) System.currentTimeMillis());
final long latencyMs = (long) ((nowSeconds - enqueuedTimeSeconds) * 1000);
if (latencyMs >= 0) {
transaction.setData(SpanDataConvention.MESSAGING_MESSAGE_RECEIVE_LATENCY, latencyMs);
diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentrySpanClientHttpRequestInterceptor.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentrySpanClientHttpRequestInterceptor.java
index 0628bc1d30e..8a5d1db3e05 100644
--- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentrySpanClientHttpRequestInterceptor.java
+++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentrySpanClientHttpRequestInterceptor.java
@@ -39,7 +39,7 @@ public SentrySpanClientHttpRequestInterceptor(final @NotNull IScopes scopes) {
}
public SentrySpanClientHttpRequestInterceptor(
- final @NotNull IScopes scopes, final @NotNull boolean isRestTemplate) {
+ final @NotNull IScopes scopes, final boolean isRestTemplate) {
this.scopes = Objects.requireNonNull(scopes, "Scopes are required");
this.traceOrigin = isRestTemplate ? TRACE_ORIGIN_REST_TEMPLATE : TRACE_ORIGIN_REST_CLIENT;
}
diff --git a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryTransactionAdvice.java b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryTransactionAdvice.java
index 95618f76fd7..833e59670e2 100644
--- a/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryTransactionAdvice.java
+++ b/sentry-spring-jakarta/src/main/java/io/sentry/spring/jakarta/tracing/SentryTransactionAdvice.java
@@ -116,7 +116,7 @@ private static class TransactionNameAndSource {
private final @NotNull String name;
private final @NotNull TransactionNameSource source;
- public TransactionNameAndSource(
+ TransactionNameAndSource(
final @NotNull String name, final @NotNull TransactionNameSource source) {
this.name = name;
this.source = source;
diff --git a/sentry-spring/build.gradle.kts b/sentry-spring/build.gradle.kts
index 03176d7b867..71eb6d1f15e 100644
--- a/sentry-spring/build.gradle.kts
+++ b/sentry-spring/build.gradle.kts
@@ -12,7 +12,7 @@ plugins {
id("io.sentry.animalsniffer")
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = JvmTarget.JVM_1_8
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
@@ -54,7 +54,7 @@ dependencies {
testImplementation(libs.graphql.java17)
testImplementation(libs.kotlin.test.junit)
testImplementation(libs.mockito.kotlin)
- testImplementation(libs.mockito.inline)
+ testImplementation(libs.mockito.core)
testImplementation(libs.springboot.starter.aop)
testImplementation(libs.springboot.starter.graphql)
testImplementation(libs.springboot.starter.security)
diff --git a/sentry-spring/src/main/java/io/sentry/spring/kafka/SentryKafkaRecordInterceptor.java b/sentry-spring/src/main/java/io/sentry/spring/kafka/SentryKafkaRecordInterceptor.java
index d1ad3086098..ed26e2ee795 100644
--- a/sentry-spring/src/main/java/io/sentry/spring/kafka/SentryKafkaRecordInterceptor.java
+++ b/sentry-spring/src/main/java/io/sentry/spring/kafka/SentryKafkaRecordInterceptor.java
@@ -202,7 +202,7 @@ private boolean isIgnored() {
if (enqueuedTimeStr != null) {
try {
final double enqueuedTimeSeconds = Double.parseDouble(enqueuedTimeStr);
- final double nowSeconds = DateUtils.millisToSeconds(System.currentTimeMillis());
+ final double nowSeconds = DateUtils.millisToSeconds((double) System.currentTimeMillis());
final long latencyMs = (long) ((nowSeconds - enqueuedTimeSeconds) * 1000);
if (latencyMs >= 0) {
transaction.setData(SpanDataConvention.MESSAGING_MESSAGE_RECEIVE_LATENCY, latencyMs);
diff --git a/sentry-spring/src/main/java/io/sentry/spring/tracing/SentryTransactionAdvice.java b/sentry-spring/src/main/java/io/sentry/spring/tracing/SentryTransactionAdvice.java
index 180d5df00a7..eab13d1a7d6 100644
--- a/sentry-spring/src/main/java/io/sentry/spring/tracing/SentryTransactionAdvice.java
+++ b/sentry-spring/src/main/java/io/sentry/spring/tracing/SentryTransactionAdvice.java
@@ -115,7 +115,7 @@ private static class TransactionNameAndSource {
private final @NotNull String name;
private final @NotNull TransactionNameSource source;
- public TransactionNameAndSource(
+ TransactionNameAndSource(
final @NotNull String name, final @NotNull TransactionNameSource source) {
this.name = name;
this.source = source;
diff --git a/sentry-system-test-support/build.gradle.kts b/sentry-system-test-support/build.gradle.kts
index 7f08bf6d01b..ecfdc6011f8 100644
--- a/sentry-system-test-support/build.gradle.kts
+++ b/sentry-system-test-support/build.gradle.kts
@@ -7,13 +7,7 @@ plugins {
id("com.apollographql.apollo") version "4.1.1"
}
-configure {
- sourceCompatibility = JavaVersion.VERSION_1_8
- targetCompatibility = JavaVersion.VERSION_1_8
-}
-
tasks.withType().configureEach {
- compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
}
diff --git a/sentry-test-support/build.gradle.kts b/sentry-test-support/build.gradle.kts
index a0b508c9715..2539beccb5f 100644
--- a/sentry-test-support/build.gradle.kts
+++ b/sentry-test-support/build.gradle.kts
@@ -6,13 +6,7 @@ plugins {
alias(libs.plugins.gradle.versions)
}
-configure {
- sourceCompatibility = JavaVersion.VERSION_1_8
- targetCompatibility = JavaVersion.VERSION_1_8
-}
-
tasks.withType().configureEach {
- compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
compilerOptions.languageVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
compilerOptions.apiVersion = org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_1_9
}
@@ -30,4 +24,6 @@ dependencies {
implementation(kotlin(Config.kotlinStdLib))
implementation(libs.kotlin.test.junit)
implementation(libs.mockito.kotlin)
+
+ testImplementation(libs.google.truth)
}
diff --git a/sentry-test-support/src/main/kotlin/io/sentry/test/MockSentryServer.kt b/sentry-test-support/src/main/kotlin/io/sentry/test/MockSentryServer.kt
new file mode 100644
index 00000000000..439b61f2c2a
--- /dev/null
+++ b/sentry-test-support/src/main/kotlin/io/sentry/test/MockSentryServer.kt
@@ -0,0 +1,87 @@
+package io.sentry.test
+
+import com.sun.net.httpserver.HttpExchange
+import com.sun.net.httpserver.HttpServer
+import io.sentry.JsonSerializer
+import io.sentry.SentryEnvelope
+import io.sentry.SentryOptions
+import io.sentry.time.Deadline
+import io.sentry.time.JavaMonotonicTicker
+import java.io.Closeable
+import java.net.InetAddress
+import java.net.InetSocketAddress
+import java.util.concurrent.CopyOnWriteArrayList
+import java.util.concurrent.TimeUnit
+import java.util.zip.GZIPInputStream
+
+/**
+ * A stand-in for Sentry's ingestion endpoint that integration tests point the SDK at through [dsn].
+ *
+ * Envelopes travel through the real HTTP transport, so serialization, compression and the DSN are
+ * covered too. It binds a free port so that test tasks running in parallel don't clash, and it
+ * works for an app in a child process as well as in the test's own JVM.
+ */
+class MockSentryServer : Closeable {
+ private val serializer = JsonSerializer(SentryOptions.empty())
+ private val received = CopyOnWriteArrayList()
+ private val server =
+ HttpServer.create(InetSocketAddress(InetAddress.getByName(HOST), 0), 0).apply {
+ createContext("/api/") { exchange -> receive(exchange) }
+ start()
+ }
+
+ val dsn: String = "http://key@$HOST:${server.address.port}/0"
+
+ val envelopes: List
+ get() = received.toList()
+
+ /** Returns the first received envelope matching [predicate], waiting up to [timeoutMillis]. */
+ fun awaitEnvelope(
+ timeoutMillis: Long = DEFAULT_TIMEOUT_MILLIS,
+ predicate: (SentryEnvelope) -> Boolean,
+ ): SentryEnvelope {
+ val deadline =
+ Deadline.after(JavaMonotonicTicker.getInstance(), timeoutMillis, TimeUnit.MILLISECONDS)
+ while (true) {
+ received.firstOrNull(predicate)?.let {
+ return it
+ }
+ if (deadline.hasPassed()) {
+ throw AssertionError(
+ "No matching envelope within ${timeoutMillis}ms, received ${received.size} envelopes"
+ )
+ }
+ Thread.sleep(POLL_INTERVAL_MILLIS)
+ }
+ }
+
+ fun reset() {
+ received.clear()
+ }
+
+ override fun close() {
+ server.stop(0)
+ }
+
+ private fun receive(exchange: HttpExchange) {
+ try {
+ val body =
+ if (exchange.requestHeaders.getFirst("Content-Encoding") == "gzip") {
+ GZIPInputStream(exchange.requestBody)
+ } else {
+ exchange.requestBody
+ }
+ serializer.deserializeEnvelope(body)?.let { received.add(it) }
+ exchange.sendResponseHeaders(200, -1)
+ } finally {
+ exchange.close()
+ }
+ }
+
+ private companion object {
+ // An IP rather than "localhost", which can resolve to IPv4 for the server and IPv6 for the SDK.
+ const val HOST = "127.0.0.1"
+ const val DEFAULT_TIMEOUT_MILLIS = 10_000L
+ const val POLL_INTERVAL_MILLIS = 50L
+ }
+}
diff --git a/sentry-test-support/src/test/kotlin/io/sentry/test/MockSentryServerTest.kt b/sentry-test-support/src/test/kotlin/io/sentry/test/MockSentryServerTest.kt
new file mode 100644
index 00000000000..6a1e3f03225
--- /dev/null
+++ b/sentry-test-support/src/test/kotlin/io/sentry/test/MockSentryServerTest.kt
@@ -0,0 +1,34 @@
+package io.sentry.test
+
+import com.google.common.truth.Truth.assertThat
+import io.sentry.Sentry
+import io.sentry.SentryItemType
+import kotlin.test.AfterTest
+import kotlin.test.Test
+import kotlin.test.assertFailsWith
+
+class MockSentryServerTest {
+ private val server = MockSentryServer()
+
+ @AfterTest
+ fun teardown() {
+ Sentry.close()
+ server.close()
+ }
+
+ @Test
+ fun `receives an event sent through the HTTP transport`() {
+ initForTest { it.dsn = server.dsn }
+
+ val eventId = Sentry.captureMessage("hello")
+ Sentry.flush(5000)
+
+ val envelope = server.awaitEnvelope { it.header.eventId == eventId }
+ assertThat(envelope.items.single().header.type).isEqualTo(SentryItemType.Event)
+ }
+
+ @Test
+ fun `awaitEnvelope fails once the timeout passes without a match`() {
+ assertFailsWith { server.awaitEnvelope(timeoutMillis = 100) { true } }
+ }
+}
diff --git a/sentry/build.gradle.kts b/sentry/build.gradle.kts
index 6b98ff790c6..9cbcf5bf2c0 100644
--- a/sentry/build.gradle.kts
+++ b/sentry/build.gradle.kts
@@ -11,7 +11,7 @@ plugins {
id("io.sentry.animalsniffer.android")
}
-tasks.withType().configureEach {
+tasks.named("compileKotlin") {
compilerOptions.jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8
}
@@ -28,7 +28,7 @@ dependencies {
testImplementation(libs.javafaker)
testImplementation(libs.kotlin.test.junit)
testImplementation(libs.mockito.kotlin)
- testImplementation(libs.mockito.inline)
+ testImplementation(libs.mockito.core)
testImplementation(libs.msgpack)
testImplementation(libs.okio)
testImplementation(projects.sentryTestSupport)
@@ -51,6 +51,9 @@ tasks {
"--add-opens",
"java.base/java.lang=ALL-UNNAMED",
)
+ // SentryEnvelopeItemTest."fromAttachment with file SecurityManager denies read access" installs
+ // a SecurityManager to simulate unreadable attachments; JDK 18+ refuses that without opt-in.
+ systemProperty("java.security.manager", "allow")
environment["SENTRY_TEST_PROPERTY"] = "\"some-value\""
environment["SENTRY_TEST_MAP_KEY1"] = "\"value1\""
environment["SENTRY_TEST_MAP_KEY2"] = "value2"
diff --git a/sentry/src/main/java/io/sentry/Baggage.java b/sentry/src/main/java/io/sentry/Baggage.java
index 9f0753f8671..a4ef2c9e859 100644
--- a/sentry/src/main/java/io/sentry/Baggage.java
+++ b/sentry/src/main/java/io/sentry/Baggage.java
@@ -257,6 +257,10 @@ public String getThirdPartyHeader() {
return thirdPartyHeader;
}
+ // temp fix for JDK 21: ConcurrentHashMap.keySet() compiled against JDK 8+ returns KeySetView,
+ // which crashes on Android
+ // < 24.
+ @SuppressWarnings("JdkObsolete")
public @NotNull String toHeaderString(@Nullable String thirdPartyBaggageHeaderString) {
final StringBuilder sb = new StringBuilder();
String separator = "";
@@ -325,10 +329,14 @@ public String getThirdPartyHeader() {
return sb.toString();
}
+ // temp fix for JDK 21: The Charset overload requires Java 10.
+ @SuppressWarnings("JdkObsolete")
private String encode(final @NotNull String value) throws UnsupportedEncodingException {
return URLEncoder.encode(value, CHARSET).replaceAll("\\+", "%20");
}
+ // temp fix for JDK 21: The Charset overload requires Java 10.
+ @SuppressWarnings("JdkObsolete")
private static String decode(final @NotNull String value) throws UnsupportedEncodingException {
return URLDecoder.decode(value, CHARSET);
}
diff --git a/sentry/src/main/java/io/sentry/Breadcrumb.java b/sentry/src/main/java/io/sentry/Breadcrumb.java
index 4db0dcf46c5..24ac5561d10 100644
--- a/sentry/src/main/java/io/sentry/Breadcrumb.java
+++ b/sentry/src/main/java/io/sentry/Breadcrumb.java
@@ -630,6 +630,8 @@ public void setType(@Nullable String type) {
this.type = type;
}
+ // temp fix for JDK 21: EMPTY_DATA is a sentinel, so identity comparison is intended.
+ @SuppressWarnings("ReferenceEquality")
private @NotNull Map getOrCreateData() {
Map currentData = data;
if (currentData == EMPTY_DATA) {
@@ -691,6 +693,8 @@ public void setData(@Nullable String key, @Nullable Object value) {
*
* @param key the key
*/
+ // temp fix for JDK 21: EMPTY_DATA is a sentinel, so identity comparison is intended.
+ @SuppressWarnings("ReferenceEquality")
public void removeData(@Nullable String key) {
if (key == null) {
return;
diff --git a/sentry/src/main/java/io/sentry/CombinedContextsView.java b/sentry/src/main/java/io/sentry/CombinedContextsView.java
index d9a8b14c628..0fff6b681bd 100644
--- a/sentry/src/main/java/io/sentry/CombinedContextsView.java
+++ b/sentry/src/main/java/io/sentry/CombinedContextsView.java
@@ -243,7 +243,7 @@ public void setSpring(@NotNull Spring spring) {
@ApiStatus.Internal
@Override
- /** Not intended to be set on a scopes Context directly */
+ /* Not intended to be set on a scopes Context directly */
public void setFeatureFlags(@NotNull FeatureFlags spring) {
getDefaultContexts().setFeatureFlags(spring);
}
diff --git a/sentry/src/main/java/io/sentry/DateUtils.java b/sentry/src/main/java/io/sentry/DateUtils.java
index fcba83fbe05..4be99b6322f 100644
--- a/sentry/src/main/java/io/sentry/DateUtils.java
+++ b/sentry/src/main/java/io/sentry/DateUtils.java
@@ -151,10 +151,10 @@ public static double nanosToSeconds(final long nanos) {
*/
@SuppressWarnings("JavaUtilDate")
public static double dateToSeconds(final @NotNull Date date) {
- return millisToSeconds(date.getTime());
+ return millisToSeconds((double) date.getTime());
}
- public static long secondsToNanos(final @NotNull long seconds) {
+ public static long secondsToNanos(final long seconds) {
return seconds * (1000L * 1000L * 1000L);
}
diff --git a/sentry/src/main/java/io/sentry/DefaultSpanFactory.java b/sentry/src/main/java/io/sentry/DefaultSpanFactory.java
index f664360f49b..71dd40843a4 100644
--- a/sentry/src/main/java/io/sentry/DefaultSpanFactory.java
+++ b/sentry/src/main/java/io/sentry/DefaultSpanFactory.java
@@ -21,7 +21,7 @@ public final class DefaultSpanFactory implements ISpanFactory {
final @NotNull SpanOptions spanOptions,
final @NotNull SpanContext spanContext,
@Nullable ISpan parentSpan) {
- /**
+ /*
* Be careful here when executing something like parentSpan.startChild() as that might cause a
* loop and a stack overflow. This can happen, e.g. when OpenTelemetry is creating spans that
* use OtelSpanWrapper which calls this createSpan method that then in turn calls startChild
diff --git a/sentry/src/main/java/io/sentry/DiagnosticLogger.java b/sentry/src/main/java/io/sentry/DiagnosticLogger.java
index c96e061f2c1..1f067cd6f1b 100644
--- a/sentry/src/main/java/io/sentry/DiagnosticLogger.java
+++ b/sentry/src/main/java/io/sentry/DiagnosticLogger.java
@@ -29,6 +29,8 @@ public DiagnosticLogger(final @NotNull SentryOptions options, final @Nullable IL
* @param level The SentryLevel to test against.
* @return True if a log message would be recorded for the level. Otherwise false.
*/
+ // temp fix for JDK 21: SentryLevel is declared in ascending severity order.
+ @SuppressWarnings("EnumOrdinal")
@Override
public boolean isEnabled(final @Nullable SentryLevel level) {
final SentryLevel diagLevel = options.getDiagnosticLevel();
diff --git a/sentry/src/main/java/io/sentry/DirectoryProcessor.java b/sentry/src/main/java/io/sentry/DirectoryProcessor.java
index 17f65bb8c76..d9f0f32c40c 100644
--- a/sentry/src/main/java/io/sentry/DirectoryProcessor.java
+++ b/sentry/src/main/java/io/sentry/DirectoryProcessor.java
@@ -120,7 +120,7 @@ private static final class SendCachedEnvelopeHint
private final @NotNull String filePath;
private final @NotNull Queue processedEnvelopes;
- public SendCachedEnvelopeHint(
+ SendCachedEnvelopeHint(
final long flushTimeoutMillis,
final @NotNull ILogger logger,
final @NotNull String filePath,
diff --git a/sentry/src/main/java/io/sentry/ExternalOptions.java b/sentry/src/main/java/io/sentry/ExternalOptions.java
index 83497c2fb06..bc9fc6f010d 100644
--- a/sentry/src/main/java/io/sentry/ExternalOptions.java
+++ b/sentry/src/main/java/io/sentry/ExternalOptions.java
@@ -236,7 +236,8 @@ public final class ExternalOptions {
String profileLifecycleString = propertiesProvider.getProperty("profile-lifecycle");
if (profileLifecycleString != null && !profileLifecycleString.isEmpty()) {
- options.setProfileLifecycle(ProfileLifecycle.valueOf(profileLifecycleString.toUpperCase()));
+ options.setProfileLifecycle(
+ ProfileLifecycle.valueOf(profileLifecycleString.toUpperCase(Locale.ROOT)));
}
return options;
diff --git a/sentry/src/main/java/io/sentry/Hint.java b/sentry/src/main/java/io/sentry/Hint.java
index 1e09dca5541..9281d41fa91 100644
--- a/sentry/src/main/java/io/sentry/Hint.java
+++ b/sentry/src/main/java/io/sentry/Hint.java
@@ -60,7 +60,7 @@ public void set(@NotNull String name, @Nullable Object hint) {
}
@SuppressWarnings("unchecked")
- public @Nullable T getAs(@NotNull String name, @NotNull Class clazz) {
+ public @Nullable T getAs(@NotNull String name, @NotNull Class clazz) {
try (final @NotNull ISentryLifecycleToken ignored = lock.acquire()) {
Object hintValue = internalStorage.get(name);
diff --git a/sentry/src/main/java/io/sentry/MonitorContexts.java b/sentry/src/main/java/io/sentry/MonitorContexts.java
index a52ecc6b97f..73db50ea4ca 100644
--- a/sentry/src/main/java/io/sentry/MonitorContexts.java
+++ b/sentry/src/main/java/io/sentry/MonitorContexts.java
@@ -43,6 +43,10 @@ public void setTrace(final @NotNull SpanContext traceContext) {
// region json
+ // temp fix for JDK 21: ConcurrentHashMap.keySet() compiled against JDK 8+ returns KeySetView,
+ // which crashes on Android
+ // < 24.
+ @SuppressWarnings("JdkObsolete")
@Override
public void serialize(final @NotNull ObjectWriter writer, final @NotNull ILogger logger)
throws IOException {
diff --git a/sentry/src/main/java/io/sentry/ReplayRecording.java b/sentry/src/main/java/io/sentry/ReplayRecording.java
index a83eddd380f..0688ce38f0a 100644
--- a/sentry/src/main/java/io/sentry/ReplayRecording.java
+++ b/sentry/src/main/java/io/sentry/ReplayRecording.java
@@ -102,7 +102,8 @@ public void setUnknown(@Nullable Map unknown) {
public static final class Deserializer implements JsonDeserializer {
- @SuppressWarnings("unchecked")
+ // temp fix for JDK 21: The rrweb protocol encodes these enums by ordinal.
+ @SuppressWarnings({"unchecked", "EnumOrdinal"})
@Override
public @NotNull ReplayRecording deserialize(
@NotNull ObjectReader reader, @NotNull ILogger logger) throws Exception {
diff --git a/sentry/src/main/java/io/sentry/SamplingContext.java b/sentry/src/main/java/io/sentry/SamplingContext.java
index 17ce111d0c2..7a9c69b0739 100644
--- a/sentry/src/main/java/io/sentry/SamplingContext.java
+++ b/sentry/src/main/java/io/sentry/SamplingContext.java
@@ -20,7 +20,7 @@ public final class SamplingContext {
@Deprecated
@SuppressWarnings("InlineMeSuggester")
- /**
+ /*
* @deprecated creating a SamplingContext is something only the SDK should do
*/
public SamplingContext(
diff --git a/sentry/src/main/java/io/sentry/Scope.java b/sentry/src/main/java/io/sentry/Scope.java
index 42aef2821ac..ec98cc5fcaf 100644
--- a/sentry/src/main/java/io/sentry/Scope.java
+++ b/sentry/src/main/java/io/sentry/Scope.java
@@ -463,10 +463,10 @@ public Queue getBreadcrumbs() {
*/
private @Nullable Breadcrumb executeBeforeBreadcrumb(
final @NotNull SentryOptions.BeforeBreadcrumbCallback callback,
- @NotNull Breadcrumb breadcrumb,
+ final @NotNull Breadcrumb breadcrumb,
final @NotNull Hint hint) {
try (final @NotNull ISentryLifecycleToken ignored = SentryCallbackReentrancyGuard.enter()) {
- breadcrumb = callback.execute(breadcrumb, hint);
+ return callback.execute(breadcrumb, hint);
} catch (Throwable e) {
options
.getLogger()
@@ -476,7 +476,6 @@ public Queue getBreadcrumbs() {
e);
return null;
}
- return breadcrumb;
}
/**
diff --git a/sentry/src/main/java/io/sentry/SentryEnvelopeItem.java b/sentry/src/main/java/io/sentry/SentryEnvelopeItem.java
index 2a7f06968dc..d1858c02767 100644
--- a/sentry/src/main/java/io/sentry/SentryEnvelopeItem.java
+++ b/sentry/src/main/java/io/sentry/SentryEnvelopeItem.java
@@ -691,11 +691,12 @@ private static class CachedItem {
private @Nullable byte[] bytes;
private final @Nullable Callable dataFactory;
- public CachedItem(final @Nullable Callable dataFactory) {
+ CachedItem(final @Nullable Callable dataFactory) {
this.dataFactory = dataFactory;
}
- public @NotNull byte[] getBytes() throws Exception {
+ @NotNull
+ byte[] getBytes() throws Exception {
if (bytes == null && dataFactory != null) {
bytes = dataFactory.call();
}
diff --git a/sentry/src/main/java/io/sentry/SentryExceptionFactory.java b/sentry/src/main/java/io/sentry/SentryExceptionFactory.java
index cd4ab1cc0e9..3c07ec38b91 100644
--- a/sentry/src/main/java/io/sentry/SentryExceptionFactory.java
+++ b/sentry/src/main/java/io/sentry/SentryExceptionFactory.java
@@ -11,6 +11,7 @@
import java.util.Deque;
import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
@@ -141,7 +142,7 @@ Deque extractExceptionQueue(final @NotNull Throwable throwable)
Deque extractExceptionQueueInternal(
final @NotNull Throwable throwable,
final @NotNull AtomicInteger exceptionId,
- final @NotNull HashSet circularityDetector,
+ final @NotNull Set circularityDetector,
final @NotNull Deque exceptions,
@Nullable String mechanismTypeOverride) {
Mechanism exceptionMechanism;
diff --git a/sentry/src/main/java/io/sentry/SentryOptions.java b/sentry/src/main/java/io/sentry/SentryOptions.java
index 64265e3f9cd..08e2f408824 100644
--- a/sentry/src/main/java/io/sentry/SentryOptions.java
+++ b/sentry/src/main/java/io/sentry/SentryOptions.java
@@ -58,6 +58,9 @@
import org.jetbrains.annotations.TestOnly;
/** Sentry SDK options */
+// temp fix for JDK 21: Constructors call overridable methods; making them final would break the
+// public API.
+@SuppressWarnings("this-escape")
@Open
public class SentryOptions implements RateLimiterConfig {
diff --git a/sentry/src/main/java/io/sentry/SentryThreadFactory.java b/sentry/src/main/java/io/sentry/SentryThreadFactory.java
index 8bd14483269..552ab1ed5c7 100644
--- a/sentry/src/main/java/io/sentry/SentryThreadFactory.java
+++ b/sentry/src/main/java/io/sentry/SentryThreadFactory.java
@@ -78,6 +78,8 @@ List getCurrentThreads(
* crashed. This is the case for e.g. watchdog threads which are not the one erroring.
* @return a list of SentryThread or null if none
*/
+ // temp fix for JDK 21: Identifies the current thread by identity.
+ @SuppressWarnings("ReferenceEquality")
@TestOnly
@Nullable
List getCurrentThreads(
diff --git a/sentry/src/main/java/io/sentry/SentryTracer.java b/sentry/src/main/java/io/sentry/SentryTracer.java
index d60187cb4d5..781cf51417e 100644
--- a/sentry/src/main/java/io/sentry/SentryTracer.java
+++ b/sentry/src/main/java/io/sentry/SentryTracer.java
@@ -154,7 +154,7 @@ private void onDeadlineTimeoutReached() {
}
@Override
- public @NotNull void forceFinish(
+ public void forceFinish(
final @NotNull SpanStatus status, final boolean dropIfNoChildren, final @Nullable Hint hint) {
if (isFinished()) {
return;
diff --git a/sentry/src/main/java/io/sentry/SpanContext.java b/sentry/src/main/java/io/sentry/SpanContext.java
index 19ab2c3ad87..ebbeb56cd6e 100644
--- a/sentry/src/main/java/io/sentry/SpanContext.java
+++ b/sentry/src/main/java/io/sentry/SpanContext.java
@@ -16,6 +16,9 @@
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
+// temp fix for JDK 21: Constructors call overridable methods; making them final would break the
+// public API.
+@SuppressWarnings("this-escape")
@Open
public class SpanContext implements JsonUnknown, JsonSerializable {
public static final String TYPE = "trace";
diff --git a/sentry/src/main/java/io/sentry/SynchronizedCollection.java b/sentry/src/main/java/io/sentry/SynchronizedCollection.java
index 8a58401020b..6e8e6b76c6c 100644
--- a/sentry/src/main/java/io/sentry/SynchronizedCollection.java
+++ b/sentry/src/main/java/io/sentry/SynchronizedCollection.java
@@ -50,9 +50,14 @@ class SynchronizedCollection implements Collection, Serializable {
private static final long serialVersionUID = 2412805092710877986L;
/** The collection to decorate */
+ // temp fix for JDK 21: Serializable only if the decorated collection is, as in Apache Commons
+ // Collections.
+ @SuppressWarnings("serial")
private final Collection collection;
/** The object to lock on, needed for List/SortedSet views */
+ // temp fix for JDK 21: Not Serializable either; the SDK never serializes these collections.
+ @SuppressWarnings("serial")
final AutoClosableReentrantLock lock;
/**
diff --git a/sentry/src/main/java/io/sentry/TraceContext.java b/sentry/src/main/java/io/sentry/TraceContext.java
index 1bb5508f85b..957bda79f49 100644
--- a/sentry/src/main/java/io/sentry/TraceContext.java
+++ b/sentry/src/main/java/io/sentry/TraceContext.java
@@ -30,7 +30,7 @@ public final class TraceContext implements JsonUnknown, JsonSerializable {
}
@SuppressWarnings("InlineMeSuggester")
- /**
+ /*
* @deprecated please use the constructor than also takes sampleRand
*/
@Deprecated
diff --git a/sentry/src/main/java/io/sentry/UncaughtExceptionHandlerIntegration.java b/sentry/src/main/java/io/sentry/UncaughtExceptionHandlerIntegration.java
index 6ea61895799..07e9b6357d7 100644
--- a/sentry/src/main/java/io/sentry/UncaughtExceptionHandlerIntegration.java
+++ b/sentry/src/main/java/io/sentry/UncaughtExceptionHandlerIntegration.java
@@ -47,6 +47,8 @@ public UncaughtExceptionHandlerIntegration() {
this.threadAdapter = threadAdapter;
}
+ // temp fix for JDK 21: Both integrations must share the same global scope instance.
+ @SuppressWarnings("ReferenceEquality")
@Override
public final void register(final @NotNull IScopes scopes, final @NotNull SentryOptions options) {
if (registered) {
diff --git a/sentry/src/main/java/io/sentry/cache/PersistingScopeObserver.java b/sentry/src/main/java/io/sentry/cache/PersistingScopeObserver.java
index 8a097486db1..8ebf494dc99 100644
--- a/sentry/src/main/java/io/sentry/cache/PersistingScopeObserver.java
+++ b/sentry/src/main/java/io/sentry/cache/PersistingScopeObserver.java
@@ -265,6 +265,9 @@ private void flush() {
}
}
+ // temp fix for JDK 21: DELETE_MARKER and CLEAR_MARKER are sentinels, so identity comparison is
+ // intended.
+ @SuppressWarnings("ReferenceEquality")
private void writePending() {
// ConcurrentHashMap's iterator is weakly consistent, so removing while iterating is safe. Keys
// added after iteration starts may be missed, but flush() re-checks and queues another write.
diff --git a/sentry/src/main/java/io/sentry/clientreport/ClientReportRecorder.java b/sentry/src/main/java/io/sentry/clientreport/ClientReportRecorder.java
index ccd7c5dc402..ba6d60e2563 100644
--- a/sentry/src/main/java/io/sentry/clientreport/ClientReportRecorder.java
+++ b/sentry/src/main/java/io/sentry/clientreport/ClientReportRecorder.java
@@ -113,6 +113,12 @@ public void recordLostEnvelopeItem(
recordLostEventInternal(
reason.getReason(), DataCategory.TraceMetricByte.getCategory(), metricBytes);
executeOnDiscard(reason, itemCategory, count);
+ } else if (itemCategory.equals(DataCategory.Span)) {
+ // Batched span items (span streaming) aren't created by this SDK yet, but hybrid SDKs
+ // like sentry-dart send them through it via InternalSentrySdk.captureEnvelope.
+ final long count = itemCountFromHeader(envelopeItem);
+ recordLostEventInternal(reason.getReason(), itemCategory.getCategory(), count);
+ executeOnDiscard(reason, itemCategory, count);
} else {
recordLostEventInternal(reason.getReason(), itemCategory.getCategory(), 1L);
executeOnDiscard(reason, itemCategory, 1L);
@@ -156,9 +162,9 @@ private void recordLostEventInternal(
storage.addCount(key, countToAdd);
}
- // The number of items batched into a log or metric envelope item is stored in its header, so we
- // read it from there instead of deserializing the payload. Deserializing on the discard path is
- // expensive and, under sustained rate limiting, caused a CPU busy-loop (JAVA-662).
+ // The number of items batched into a log, metric or span envelope item is stored in its header,
+ // so we read it from there instead of deserializing the payload. Deserializing on the discard
+ // path is expensive and, under sustained rate limiting, caused a CPU busy-loop (JAVA-662).
private long itemCountFromHeader(final @NotNull SentryEnvelopeItem envelopeItem) {
final @Nullable Integer itemCount = envelopeItem.getHeader().getItemCount();
return itemCount != null ? itemCount : 1L;
diff --git a/sentry/src/main/java/io/sentry/exception/ExceptionMechanismException.java b/sentry/src/main/java/io/sentry/exception/ExceptionMechanismException.java
index 5df6d473f78..f3e8cbd4744 100644
--- a/sentry/src/main/java/io/sentry/exception/ExceptionMechanismException.java
+++ b/sentry/src/main/java/io/sentry/exception/ExceptionMechanismException.java
@@ -14,9 +14,16 @@
public final class ExceptionMechanismException extends RuntimeException {
private static final long serialVersionUID = 142345454265713915L;
+ // temp fix for JDK 21: Never serialized.
+ @SuppressWarnings("serial")
private final @NotNull Mechanism exceptionMechanism;
+
private final @NotNull Throwable throwable;
+
+ // temp fix for JDK 21: Never serialized.
+ @SuppressWarnings("serial")
private final @Nullable Thread thread;
+
private final boolean snapshot;
/**
diff --git a/sentry/src/main/java/io/sentry/featureflags/FeatureFlagBuffer.java b/sentry/src/main/java/io/sentry/featureflags/FeatureFlagBuffer.java
index 5a02a911ace..84448878196 100644
--- a/sentry/src/main/java/io/sentry/featureflags/FeatureFlagBuffer.java
+++ b/sentry/src/main/java/io/sentry/featureflags/FeatureFlagBuffer.java
@@ -233,13 +233,14 @@ private static class FeatureFlagEntry {
private final boolean result;
private final long nanos;
- public FeatureFlagEntry(final @NotNull String flag, final boolean result, final long nanos) {
+ FeatureFlagEntry(final @NotNull String flag, final boolean result, final long nanos) {
this.flag = flag;
this.result = result;
this.nanos = nanos;
}
- public @NotNull FeatureFlag toFeatureFlag() {
+ @NotNull
+ FeatureFlag toFeatureFlag() {
return new FeatureFlag(flag, result);
}
}
diff --git a/sentry/src/main/java/io/sentry/internal/modules/ManifestModulesLoader.java b/sentry/src/main/java/io/sentry/internal/modules/ManifestModulesLoader.java
index 1f7ac93950e..fc1c313ec43 100644
--- a/sentry/src/main/java/io/sentry/internal/modules/ManifestModulesLoader.java
+++ b/sentry/src/main/java/io/sentry/internal/modules/ManifestModulesLoader.java
@@ -93,7 +93,7 @@ private static final class Module {
private final @NotNull String name;
private final @NotNull String version;
- public Module(final @NotNull String name, final @NotNull String version) {
+ Module(final @NotNull String name, final @NotNull String version) {
this.name = name;
this.version = version;
}
diff --git a/sentry/src/main/java/io/sentry/logger/LoggerApi.java b/sentry/src/main/java/io/sentry/logger/LoggerApi.java
index 139ac615394..77de6902614 100644
--- a/sentry/src/main/java/io/sentry/logger/LoggerApi.java
+++ b/sentry/src/main/java/io/sentry/logger/LoggerApi.java
@@ -151,7 +151,7 @@ private void captureLog(
}
}
- private @NotNull HashMap createAttributes(
+ private @NotNull Map createAttributes(
final @NotNull SentryLogParameters params,
final @NotNull String message,
final @Nullable Object... args) {
@@ -246,8 +246,7 @@ private void captureLog(
return attributes;
}
- private void setServerName(
- final @NotNull HashMap attributes) {
+ private void setServerName(final @NotNull Map attributes) {
final @NotNull SentryOptions options = scopes.getOptions();
final @Nullable String optionsServerName = options.getServerName();
if (optionsServerName != null) {
@@ -264,7 +263,7 @@ private void setServerName(
}
}
- private void setUser(final @NotNull HashMap attributes) {
+ private void setUser(final @NotNull Map attributes) {
final @Nullable User user = scopes.getCombinedScopeView().getUser();
if (user == null) {
// In case no user is set, we should fallback to the distinct id, known as installation id,
diff --git a/sentry/src/main/java/io/sentry/metrics/MetricsApi.java b/sentry/src/main/java/io/sentry/metrics/MetricsApi.java
index 93564e4ddac..fa78511d224 100644
--- a/sentry/src/main/java/io/sentry/metrics/MetricsApi.java
+++ b/sentry/src/main/java/io/sentry/metrics/MetricsApi.java
@@ -155,7 +155,7 @@ private void captureMetrics(
}
}
- private @NotNull HashMap createAttributes(
+ private @NotNull Map createAttributes(
final @NotNull SentryMetricsParameters params) {
final @NotNull HashMap attributes = new HashMap<>();
@@ -231,8 +231,7 @@ private void captureMetrics(
return attributes;
}
- private void setServerName(
- final @NotNull HashMap attributes) {
+ private void setServerName(final @NotNull Map attributes) {
final @NotNull SentryOptions options = scopes.getOptions();
final @Nullable String optionsServerName = options.getServerName();
if (optionsServerName != null) {
@@ -249,7 +248,7 @@ private void setServerName(
}
}
- private void setUser(final @NotNull HashMap attributes) {
+ private void setUser(final @NotNull Map attributes) {
final @Nullable User user = scopes.getCombinedScopeView().getUser();
if (user == null) {
// In case no user is set, we should fallback to the distinct id, known as installation id,
diff --git a/sentry/src/main/java/io/sentry/protocol/Contexts.java b/sentry/src/main/java/io/sentry/protocol/Contexts.java
index f6ba635383a..0ca6d77ec8d 100644
--- a/sentry/src/main/java/io/sentry/protocol/Contexts.java
+++ b/sentry/src/main/java/io/sentry/protocol/Contexts.java
@@ -36,6 +36,9 @@ public class Contexts implements JsonSerializable {
public Contexts() {}
+ // temp fix for JDK 21: Constructors call overridable methods; making them final would break the
+ // public API.
+ @SuppressWarnings("this-escape")
public Contexts(final @NotNull Contexts contexts) {
for (final Map.Entry entry : contexts.entrySet()) {
if (entry != null) {
@@ -252,6 +255,10 @@ public void clear() {
internalStorage.clear();
}
+ // temp fix for JDK 21: ConcurrentHashMap.keySet() compiled against JDK 8+ returns KeySetView,
+ // which crashes on Android
+ // < 24.
+ @SuppressWarnings("JdkObsolete")
public @NotNull Enumeration