diff --git a/.github/workflows/agp-matrix.yml b/.github/workflows/agp-matrix.yml index a9c4293292..1f0a46ae97 100644 --- a/.github/workflows/agp-matrix.yml +++ b/.github/workflows/agp-matrix.yml @@ -38,7 +38,7 @@ jobs: java-version: '17' - name: Setup Gradle - uses: gradle/actions/setup-gradle@2cd2a6e951bd0b53f55a08e4e4c6f2586f3a36b9 # pin@v3 + uses: gradle/actions/setup-gradle@579fbbe7221704325eb4c4d4bf20c2b0859fba76 # pin@v3 with: gradle-home-cache-cleanup: true @@ -82,7 +82,7 @@ jobs: **/build/outputs/mapping/release/* - name: Test Report - uses: phoenix-actions/test-reporting@f957cd93fc2d848d556fa0d03c57bc79127b6b5e # pin@v15 + uses: phoenix-actions/test-reporting@41efe7ebebe7ef156ef46f6b0acf50ec0f10315b # pin@v12 if: always() with: name: JUnit AGP ${{ matrix.agp }} - Integrations ${{ matrix.integrations }} diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 969ad6135e..4220bca310 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,7 +27,7 @@ jobs: java-version: '17' - name: Setup Gradle - uses: gradle/actions/setup-gradle@2cd2a6e951bd0b53f55a08e4e4c6f2586f3a36b9 # pin@v3 + uses: gradle/actions/setup-gradle@579fbbe7221704325eb4c4d4bf20c2b0859fba76 # pin@v3 with: gradle-home-cache-cleanup: true @@ -50,7 +50,7 @@ jobs: **/build/reports/* - name: Test Report - uses: phoenix-actions/test-reporting@f957cd93fc2d848d556fa0d03c57bc79127b6b5e # pin@v15 + uses: phoenix-actions/test-reporting@41efe7ebebe7ef156ef46f6b0acf50ec0f10315b # pin@v12 if: always() with: name: JUnit Build diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 6636dc019d..5d09ac72cd 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -36,12 +36,12 @@ jobs: java-version: '17' - name: Setup Gradle - uses: gradle/actions/setup-gradle@2cd2a6e951bd0b53f55a08e4e4c6f2586f3a36b9 # pin@v3 + uses: gradle/actions/setup-gradle@579fbbe7221704325eb4c4d4bf20c2b0859fba76 # pin@v3 with: gradle-home-cache-cleanup: true - name: Initialize CodeQL - uses: github/codeql-action/init@23acc5c183826b7a8a97bce3cecc52db901f8251 # pin@v2 + uses: github/codeql-action/init@cdcdbb579706841c47f7063dda365e292e5cad7a # pin@v2 with: languages: ${{ matrix.language }} @@ -55,4 +55,4 @@ jobs: ./gradlew buildForCodeQL - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@23acc5c183826b7a8a97bce3cecc52db901f8251 # pin@v2 + uses: github/codeql-action/analyze@cdcdbb579706841c47f7063dda365e292e5cad7a # pin@v2 diff --git a/.github/workflows/enforce-license-compliance.yml b/.github/workflows/enforce-license-compliance.yml index 2c93ed9e4b..c31fec539e 100644 --- a/.github/workflows/enforce-license-compliance.yml +++ b/.github/workflows/enforce-license-compliance.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Setup Gradle - uses: gradle/actions/setup-gradle@2cd2a6e951bd0b53f55a08e4e4c6f2586f3a36b9 # pin@v3 + uses: gradle/actions/setup-gradle@579fbbe7221704325eb4c4d4bf20c2b0859fba76 # pin@v3 with: gradle-home-cache-cleanup: true diff --git a/.github/workflows/generate-javadocs.yml b/.github/workflows/generate-javadocs.yml index 635a87609b..858cc3f82d 100644 --- a/.github/workflows/generate-javadocs.yml +++ b/.github/workflows/generate-javadocs.yml @@ -20,7 +20,7 @@ jobs: java-version: '17' - name: Setup Gradle - uses: gradle/actions/setup-gradle@2cd2a6e951bd0b53f55a08e4e4c6f2586f3a36b9 # pin@v3 + uses: gradle/actions/setup-gradle@579fbbe7221704325eb4c4d4bf20c2b0859fba76 # pin@v3 with: gradle-home-cache-cleanup: true diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index d4981c5583..e99aa31f9a 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -13,4 +13,4 @@ jobs: - uses: actions/checkout@v4 with: submodules: 'recursive' - - uses: gradle/wrapper-validation-action@88425854a36845f9c881450d9660b5fd46bee142 # pin@v1 + - uses: gradle/wrapper-validation-action@699bb18358f12c5b78b37bb0111d3a0e2276e0e2 # pin@v1 diff --git a/.github/workflows/integration-tests-benchmarks.yml b/.github/workflows/integration-tests-benchmarks.yml index 2e885359ad..2b33b28528 100644 --- a/.github/workflows/integration-tests-benchmarks.yml +++ b/.github/workflows/integration-tests-benchmarks.yml @@ -37,7 +37,7 @@ jobs: java-version: '17' - name: Setup Gradle - uses: gradle/actions/setup-gradle@2cd2a6e951bd0b53f55a08e4e4c6f2586f3a36b9 # pin@v3 + uses: gradle/actions/setup-gradle@579fbbe7221704325eb4c4d4bf20c2b0859fba76 # pin@v3 with: gradle-home-cache-cleanup: true @@ -47,7 +47,7 @@ jobs: run: make assembleBenchmarks - name: Run All Tests in SauceLab - uses: saucelabs/saucectl-run-action@39e4f0666ca8ecb4b60847213c6e0fbd6a0c2bd8 # pin@v3 + uses: saucelabs/saucectl-run-action@7fe025ef1fdc6f211add3751a6c7d8bba27ba9b1 # pin@v3 if: github.event_name != 'pull_request' && env.SAUCE_USERNAME != null env: GITHUB_TOKEN: ${{ github.token }} @@ -57,7 +57,7 @@ jobs: config-file: .sauce/sentry-uitest-android-benchmark.yml - name: Run one test in SauceLab - uses: saucelabs/saucectl-run-action@39e4f0666ca8ecb4b60847213c6e0fbd6a0c2bd8 # pin@v3 + uses: saucelabs/saucectl-run-action@7fe025ef1fdc6f211add3751a6c7d8bba27ba9b1 # pin@v3 if: github.event_name == 'pull_request' && env.SAUCE_USERNAME != null env: GITHUB_TOKEN: ${{ github.token }} @@ -86,7 +86,7 @@ jobs: java-version: '17' - name: Setup Gradle - uses: gradle/actions/setup-gradle@2cd2a6e951bd0b53f55a08e4e4c6f2586f3a36b9 # pin@v3 + uses: gradle/actions/setup-gradle@579fbbe7221704325eb4c4d4bf20c2b0859fba76 # pin@v3 with: gradle-home-cache-cleanup: true diff --git a/.github/workflows/integration-tests-ui.yml b/.github/workflows/integration-tests-ui.yml index cd5134d38f..1d7038dd0a 100644 --- a/.github/workflows/integration-tests-ui.yml +++ b/.github/workflows/integration-tests-ui.yml @@ -32,7 +32,7 @@ jobs: java-version: '17' - name: Setup Gradle - uses: gradle/actions/setup-gradle@2cd2a6e951bd0b53f55a08e4e4c6f2586f3a36b9 # pin@v3 + uses: gradle/actions/setup-gradle@579fbbe7221704325eb4c4d4bf20c2b0859fba76 # pin@v3 with: gradle-home-cache-cleanup: true @@ -42,7 +42,7 @@ jobs: run: make assembleUiTests - name: Install SauceLabs CLI - uses: saucelabs/saucectl-run-action@39e4f0666ca8ecb4b60847213c6e0fbd6a0c2bd8 # pin@v3 + uses: saucelabs/saucectl-run-action@7fe025ef1fdc6f211add3751a6c7d8bba27ba9b1 # pin@v3 env: GITHUB_TOKEN: ${{ github.token }} with: diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index b021a6d8ec..a5449ed95b 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -26,7 +26,7 @@ jobs: java-version: '17' - name: Setup Gradle - uses: gradle/actions/setup-gradle@2cd2a6e951bd0b53f55a08e4e4c6f2586f3a36b9 # pin@v3 + uses: gradle/actions/setup-gradle@579fbbe7221704325eb4c4d4bf20c2b0859fba76 # pin@v3 with: gradle-home-cache-cleanup: true diff --git a/.github/workflows/system-tests-backend.yml b/.github/workflows/system-tests-backend.yml index d794ecb118..a916d8f9ac 100644 --- a/.github/workflows/system-tests-backend.yml +++ b/.github/workflows/system-tests-backend.yml @@ -40,7 +40,7 @@ jobs: java-version: '17' - name: Setup Gradle - uses: gradle/actions/setup-gradle@2cd2a6e951bd0b53f55a08e4e4c6f2586f3a36b9 # pin@v3 + uses: gradle/actions/setup-gradle@579fbbe7221704325eb4c4d4bf20c2b0859fba76 # pin@v3 with: gradle-home-cache-cleanup: true @@ -71,7 +71,7 @@ jobs: spring-server.txt - name: Test Report - uses: phoenix-actions/test-reporting@f957cd93fc2d848d556fa0d03c57bc79127b6b5e # pin@v15 + uses: phoenix-actions/test-reporting@41efe7ebebe7ef156ef46f6b0acf50ec0f10315b # pin@v12 if: always() with: name: JUnit System Tests ${{ matrix.sample }} diff --git a/CHANGELOG.md b/CHANGELOG.md index f67618933f..fd1866bf5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,30 +1,18 @@ # Changelog -## 7.11.0 - -### Features - -- Report dropped spans ([#3528](https://github.com/getsentry/sentry-java/pull/3528)) +## Unreleased ### Fixes -- Fix duplicate session start for React Native ([#3504](https://github.com/getsentry/sentry-java/pull/3504)) - Move onFinishCallback before span or transaction is finished ([#3459](https://github.com/getsentry/sentry-java/pull/3459)) - Add timestamp when a profile starts ([#3442](https://github.com/getsentry/sentry-java/pull/3442)) - Move fragment auto span finish to onFragmentStarted ([#3424](https://github.com/getsentry/sentry-java/pull/3424)) - Remove profiling timeout logic and disable profiling on API 21 ([#3478](https://github.com/getsentry/sentry-java/pull/3478)) - Properly reset metric flush flag on metric emission ([#3493](https://github.com/getsentry/sentry-java/pull/3493)) -- Use SecureRandom in favor of Random for Metrics ([#3495](https://github.com/getsentry/sentry-java/pull/3495)) -- Fix UncaughtExceptionHandlerIntegration Memory Leak ([#3398](https://github.com/getsentry/sentry-java/pull/3398)) -- Deprecated `User.segment`. Use a custom tag or context instead. ([#3511](https://github.com/getsentry/sentry-java/pull/3511)) -- Fix duplicated http spans ([#3526](https://github.com/getsentry/sentry-java/pull/3526)) -- When capturing unhandled hybrid exception session should be ended and new start if need ([#3480](https://github.com/getsentry/sentry-java/pull/3480)) ### Dependencies -- Bump Native SDK from v0.7.0 to v0.7.2 ([#3314](https://github.com/getsentry/sentry-java/pull/3314)) - - [changelog](https://github.com/getsentry/sentry-native/blob/master/CHANGELOG.md#072) - - [diff](https://github.com/getsentry/sentry-native/compare/0.7.0...0.7.2) +- Bump Spring Boot Jakarta from 3.2.0 to 3.3.0 ## 7.10.0 diff --git a/buildSrc/src/main/java/Config.kt b/buildSrc/src/main/java/Config.kt index 7a0081d5f4..697f509ebb 100644 --- a/buildSrc/src/main/java/Config.kt +++ b/buildSrc/src/main/java/Config.kt @@ -7,7 +7,7 @@ object Config { val kotlinStdLib = "stdlib-jdk8" val springBootVersion = "2.7.5" - val springBoot3Version = "3.2.0" + val springBoot3Version = "3.3.0" val kotlinCompatibleLanguageVersion = "1.4" val composeVersion = "1.5.3" diff --git a/gradle.properties b/gradle.properties index 35ce98ed2d..43afd204d7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,7 +10,7 @@ android.useAndroidX=true android.defaults.buildfeatures.buildconfig=true # Release information -versionName=7.11.0 +versionName=7.10.0 # Override the SDK name on native crashes on Android sentryAndroidSdkName=sentry.native.android diff --git a/sentry-android-core/api/sentry-android-core.api b/sentry-android-core/api/sentry-android-core.api index adcc6ea87d..97f7cddb7c 100644 --- a/sentry-android-core/api/sentry-android-core.api +++ b/sentry-android-core/api/sentry-android-core.api @@ -204,7 +204,7 @@ public abstract interface class io/sentry/android/core/IDebugImagesLoader { public final class io/sentry/android/core/InternalSentrySdk { public fun ()V - public static fun captureEnvelope ([BZ)Lio/sentry/protocol/SentryId; + public static fun captureEnvelope ([B)Lio/sentry/protocol/SentryId; public static fun getAppStartMeasurement ()Ljava/util/Map; public static fun getCurrentScope ()Lio/sentry/IScope; public static fun serializeScope (Landroid/content/Context;Lio/sentry/android/core/SentryAndroidOptions;Lio/sentry/IScope;)Ljava/util/Map; diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/InternalSentrySdk.java b/sentry-android-core/src/main/java/io/sentry/android/core/InternalSentrySdk.java index a3a15d7326..a4d1db09df 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/InternalSentrySdk.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/InternalSentrySdk.java @@ -1,9 +1,5 @@ package io.sentry.android.core; -import static io.sentry.SentryLevel.DEBUG; -import static io.sentry.SentryLevel.INFO; -import static io.sentry.SentryLevel.WARNING; - import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; @@ -23,14 +19,12 @@ import io.sentry.android.core.performance.ActivityLifecycleTimeSpan; import io.sentry.android.core.performance.AppStartMetrics; import io.sentry.android.core.performance.TimeSpan; -import io.sentry.cache.EnvelopeCache; import io.sentry.protocol.App; import io.sentry.protocol.Device; import io.sentry.protocol.SentryId; import io.sentry.protocol.User; import io.sentry.util.MapObjectWriter; import java.io.ByteArrayInputStream; -import java.io.File; import java.io.InputStream; import java.util.ArrayList; import java.util.HashMap; @@ -154,8 +148,7 @@ public static Map serializeScope( * captured */ @Nullable - public static SentryId captureEnvelope( - final @NotNull byte[] envelopeData, final boolean maybeStartNewSession) { + public static SentryId captureEnvelope(final @NotNull byte[] envelopeData) { final @NotNull IHub hub = HubAdapter.getInstance(); final @NotNull SentryOptions options = hub.getOptions(); @@ -191,13 +184,6 @@ public static SentryId captureEnvelope( if (session != null) { final SentryEnvelopeItem sessionItem = SentryEnvelopeItem.fromSession(serializer, session); envelopeItems.add(sessionItem); - deleteCurrentSessionFile( - options, - // should be sync if going to crash or already not a main thread - !maybeStartNewSession || !hub.getOptions().getMainThreadChecker().isMainThread()); - if (maybeStartNewSession) { - hub.startSession(); - } } final SentryEnvelope repackagedEnvelope = @@ -247,7 +233,7 @@ private static void addTimeSpanToSerializedSpans(TimeSpan span, List { - deleteCurrentSessionFile(options); - }); - } catch (Throwable e) { - options - .getLogger() - .log(WARNING, "Submission of deletion of the current session file rejected.", e); - } - } else { - deleteCurrentSessionFile(options); - } - } - - private static void deleteCurrentSessionFile(final @NotNull SentryOptions options) { - final String cacheDirPath = options.getCacheDirPath(); - if (cacheDirPath == null) { - options.getLogger().log(INFO, "Cache dir is not set, not deleting the current session."); - return; - } - - if (!options.isEnableAutoSessionTracking()) { - options - .getLogger() - .log(DEBUG, "Session tracking is disabled, bailing from deleting current session file."); - return; - } - - final File sessionFile = EnvelopeCache.getCurrentSessionFile(cacheDirPath); - if (!sessionFile.delete()) { - options.getLogger().log(WARNING, "Failed to delete the current session file."); - } - } - @Nullable private static Session updateSession( final @NotNull IHub hub, @@ -322,14 +268,11 @@ private static Session updateSession( if (updated) { if (session.getStatus() == Session.State.Crashed) { session.end(); - // Session needs to be removed from the scope, otherwise it will be send twice - // standalone and with the crash event - scope.clearSession(); } sessionRef.set(session); } } else { - options.getLogger().log(INFO, "Session is null on updateSession"); + options.getLogger().log(SentryLevel.INFO, "Session is null on updateSession"); } }); return sessionRef.get(); diff --git a/sentry-android-core/src/main/java/io/sentry/android/core/SentryAndroid.java b/sentry-android-core/src/main/java/io/sentry/android/core/SentryAndroid.java index 46590826ef..af68a026fb 100644 --- a/sentry-android-core/src/main/java/io/sentry/android/core/SentryAndroid.java +++ b/sentry-android-core/src/main/java/io/sentry/android/core/SentryAndroid.java @@ -11,7 +11,6 @@ import io.sentry.Sentry; import io.sentry.SentryLevel; import io.sentry.SentryOptions; -import io.sentry.Session; import io.sentry.android.core.internal.util.BreadcrumbFactory; import io.sentry.android.core.performance.AppStartMetrics; import io.sentry.android.core.performance.TimeSpan; @@ -20,9 +19,7 @@ import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; /** Sentry initialization class */ public final class SentryAndroid { @@ -149,21 +146,8 @@ public static synchronized void init( final @NotNull IHub hub = Sentry.getCurrentHub(); if (hub.getOptions().isEnableAutoSessionTracking() && ContextUtils.isForegroundImportance()) { - // The LifecycleWatcher of AppLifecycleIntegration may already started a session - // so only start a session if it's not already started - // This e.g. happens on React Native, or e.g. on deferred SDK init - final AtomicBoolean sessionStarted = new AtomicBoolean(false); - hub.configureScope( - scope -> { - final @Nullable Session currentSession = scope.getSession(); - if (currentSession != null && currentSession.getStarted() != null) { - sessionStarted.set(true); - } - }); - if (!sessionStarted.get()) { - hub.addBreadcrumb(BreadcrumbFactory.forSession("session.start")); - hub.startSession(); - } + hub.addBreadcrumb(BreadcrumbFactory.forSession("session.start")); + hub.startSession(); } } catch (IllegalAccessException e) { logger.log(SentryLevel.FATAL, "Fatal error during SentryAndroid.init(...)", e); diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/InternalSentrySdkTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/InternalSentrySdkTest.kt index 3aa8cb575e..65ecdb3b8c 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/InternalSentrySdkTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/InternalSentrySdkTest.kt @@ -39,7 +39,6 @@ import java.util.concurrent.atomic.AtomicReference import kotlin.test.BeforeTest import kotlin.test.Test import kotlin.test.assertEquals -import kotlin.test.assertNotEquals import kotlin.test.assertNotNull import kotlin.test.assertNull import kotlin.test.assertTrue @@ -85,7 +84,7 @@ class InternalSentrySdkTest { capturedEnvelopes.clear() } - fun captureEnvelopeWithEvent(event: SentryEvent = SentryEvent(), maybeStartNewSession: Boolean = false) { + fun captureEnvelopeWithEvent(event: SentryEvent = SentryEvent()) { // create an envelope with session data val options = Sentry.getCurrentHub().options val eventId = SentryId() @@ -104,24 +103,7 @@ class InternalSentrySdkTest { options.serializer.serialize(envelope, outputStream) val data = outputStream.toByteArray() - InternalSentrySdk.captureEnvelope(data, maybeStartNewSession) - } - - fun createSentryEventWithUnhandledException(): SentryEvent { - return SentryEvent(RuntimeException()).apply { - val mechanism = Mechanism() - mechanism.isHandled = false - - val factory = SentryExceptionFactory(mock()) - val sentryExceptions = factory.getSentryExceptions( - ExceptionMechanismException( - mechanism, - Throwable(), - Thread() - ) - ) - exceptions = sentryExceptions - } + InternalSentrySdk.captureEnvelope(data) } fun mockFinishedAppStart() { @@ -331,7 +313,7 @@ class InternalSentrySdkTest { @Test fun `captureEnvelope fails if payload is invalid`() { - assertNull(InternalSentrySdk.captureEnvelope(ByteArray(8), false)) + assertNull(InternalSentrySdk.captureEnvelope(ByteArray(8))) } @Test @@ -355,19 +337,27 @@ class InternalSentrySdkTest { } @Test - fun `captureEnvelope correctly enriches the envelope with session data and does not start new session`() { + fun `captureEnvelope correctly enriches the envelope with session data`() { val fixture = Fixture() fixture.init(context) - // keep reference for current session for later assertions - // we need to get the reference now as it will be removed from the scope - val sessionRef = AtomicReference() - Sentry.configureScope { scope -> - sessionRef.set(scope.session) - } - // when capture envelope is called with an crashed event - fixture.captureEnvelopeWithEvent(fixture.createSentryEventWithUnhandledException()) + fixture.captureEnvelopeWithEvent( + SentryEvent(RuntimeException()).apply { + val mechanism = Mechanism() + mechanism.isHandled = false + + val factory = SentryExceptionFactory(mock()) + val sentryExceptions = factory.getSentryExceptions( + ExceptionMechanismException( + mechanism, + Throwable(), + Thread() + ) + ) + exceptions = sentryExceptions + } + ) val capturedEnvelope = fixture.capturedEnvelopes.first() val capturedEnvelopeItems = capturedEnvelope.items.toList() @@ -384,52 +374,12 @@ class InternalSentrySdkTest { )!! assertEquals(Session.State.Crashed, capturedSession.status) - assertEquals(Session.State.Crashed, sessionRef.get().status) - assertEquals(capturedSession.sessionId, sessionRef.get().sessionId) - } - - @Test - fun `captureEnvelope starts new session when enabled`() { - val fixture = Fixture() - fixture.init(context) - - // when capture envelope is called with an crashed event - fixture.captureEnvelopeWithEvent(fixture.createSentryEventWithUnhandledException(), true) - + // and the local session should be marked as crashed too val scopeRef = AtomicReference() Sentry.configureScope { scope -> scopeRef.set(scope) } - - // first envelope is the new session start - val capturedStartSessionEnvelope = fixture.capturedEnvelopes.first() - val capturedNewSessionStart = fixture.options.serializer.deserialize( - InputStreamReader(ByteArrayInputStream(capturedStartSessionEnvelope.items.toList()[0].data)), - Session::class.java - )!! - assertEquals(capturedNewSessionStart.sessionId, scopeRef.get().session!!.sessionId) - assertEquals(Session.State.Ok, capturedNewSessionStart.status) - - val capturedEnvelope = fixture.capturedEnvelopes.last() - val capturedEnvelopeItems = capturedEnvelope.items.toList() - - // there should be two envelopes session start and captured crash - assertEquals(2, fixture.capturedEnvelopes.size) - - // then it should contain the original event + session - assertEquals(2, capturedEnvelopeItems.size) - assertEquals(SentryItemType.Event, capturedEnvelopeItems[0].header.type) - assertEquals(SentryItemType.Session, capturedEnvelopeItems[1].header.type) - - // and then the sent session should be marked as crashed - val capturedSession = fixture.options.serializer.deserialize( - InputStreamReader(ByteArrayInputStream(capturedEnvelopeItems[1].data)), - Session::class.java - )!! - assertEquals(Session.State.Crashed, capturedSession.status) - - // and the local session should be a new session - assertNotEquals(capturedSession.sessionId, scopeRef.get().session!!.sessionId) + assertEquals(Session.State.Crashed, scopeRef.get().session!!.status) } @Test diff --git a/sentry-android-core/src/test/java/io/sentry/android/core/SentryAndroidTest.kt b/sentry-android-core/src/test/java/io/sentry/android/core/SentryAndroidTest.kt index 990c3f4b13..cd0f8ed8c0 100644 --- a/sentry-android-core/src/test/java/io/sentry/android/core/SentryAndroidTest.kt +++ b/sentry-android-core/src/test/java/io/sentry/android/core/SentryAndroidTest.kt @@ -12,7 +12,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import io.sentry.Breadcrumb import io.sentry.Hint import io.sentry.ILogger -import io.sentry.ISentryClient import io.sentry.Sentry import io.sentry.SentryEnvelope import io.sentry.SentryLevel @@ -51,7 +50,6 @@ import org.mockito.kotlin.eq import org.mockito.kotlin.mock import org.mockito.kotlin.never import org.mockito.kotlin.spy -import org.mockito.kotlin.times import org.mockito.kotlin.verify import org.mockito.kotlin.whenever import org.robolectric.annotation.Config @@ -316,24 +314,8 @@ class SentryAndroidTest { } } - @Test - fun `init does not start a session if one is already running`() { - val client = mock() - - initSentryWithForegroundImportance(true, { options -> - options.addIntegration { hub, _ -> - hub.bindClient(client) - // usually done by LifecycleWatcher - hub.startSession() - } - }) {} - - verify(client, times(1)).captureSession(any(), any()) - } - private fun initSentryWithForegroundImportance( inForeground: Boolean, - optionsConfig: (SentryAndroidOptions) -> Unit = {}, callback: (session: Session?) -> Unit ) { val context = ContextUtilsTestHelper.createMockContext() @@ -345,7 +327,6 @@ class SentryAndroidTest { options.release = "prod" options.dsn = "https://key@sentry.io/123" options.isEnableAutoSessionTracking = true - optionsConfig(options) } var session: Session? = null diff --git a/sentry-android-ndk/sentry-native b/sentry-android-ndk/sentry-native index 0f1d664759..4ec95c0725 160000 --- a/sentry-android-ndk/sentry-native +++ b/sentry-android-ndk/sentry-native @@ -1 +1 @@ -Subproject commit 0f1d664759cba187a846a562f9d55f3c62dffaa3 +Subproject commit 4ec95c0725df5f34440db8fa8d37b4c519fce74e diff --git a/sentry-android-okhttp/build.gradle.kts b/sentry-android-okhttp/build.gradle.kts index 67a4729e56..f3eaa59303 100644 --- a/sentry-android-okhttp/build.gradle.kts +++ b/sentry-android-okhttp/build.gradle.kts @@ -24,9 +24,7 @@ android { buildTypes { getByName("debug") - getByName("release") { - consumerProguardFiles("proguard-rules.pro") - } + getByName("release") } kotlinOptions { diff --git a/sentry-android-okhttp/proguard-rules.pro b/sentry-android-okhttp/proguard-rules.pro index 9407448f6d..3f9ea4feb2 100644 --- a/sentry-android-okhttp/proguard-rules.pro +++ b/sentry-android-okhttp/proguard-rules.pro @@ -11,5 +11,3 @@ # https://raw.githubusercontent.com/square/okhttp/master/okhttp/src/jvmMain/resources/META-INF/proguard/okhttp3.pro ##---------------End: proguard configuration for OkHttp ---------- -# We keep this name to avoid the sentry-okttp module to call the old listener multiple times --keepnames class io.sentry.android.okhttp.SentryOkHttpEventListener diff --git a/sentry-android-okhttp/src/test/java/io/sentry/android/okhttp/SentryOkHttpEventListenerTest.kt b/sentry-android-okhttp/src/test/java/io/sentry/android/okhttp/SentryOkHttpEventListenerTest.kt deleted file mode 100644 index 9ed110ef7e..0000000000 --- a/sentry-android-okhttp/src/test/java/io/sentry/android/okhttp/SentryOkHttpEventListenerTest.kt +++ /dev/null @@ -1,70 +0,0 @@ -package io.sentry.android.okhttp - -import io.sentry.IHub -import io.sentry.SentryOptions -import io.sentry.SentryTracer -import io.sentry.TransactionContext -import okhttp3.EventListener -import okhttp3.OkHttpClient -import okhttp3.Request -import okhttp3.mockwebserver.MockResponse -import okhttp3.mockwebserver.MockWebServer -import okhttp3.mockwebserver.SocketPolicy -import org.mockito.kotlin.mock -import org.mockito.kotlin.whenever -import kotlin.test.Test -import kotlin.test.assertEquals - -@SuppressWarnings("Deprecated") -class SentryOkHttpEventListenerTest { - - class Fixture { - val hub = mock() - val server = MockWebServer() - lateinit var sentryTracer: SentryTracer - - @SuppressWarnings("LongParameterList") - fun getSut( - eventListener: EventListener? = null - ): OkHttpClient { - val options = SentryOptions().apply { - dsn = "https://key@sentry.io/proj" - } - whenever(hub.options).thenReturn(options) - - sentryTracer = SentryTracer(TransactionContext("name", "op"), hub) - whenever(hub.span).thenReturn(sentryTracer) - server.enqueue( - MockResponse() - .setBody("responseBody") - .setSocketPolicy(SocketPolicy.KEEP_OPEN) - .setResponseCode(200) - ) - - val builder = OkHttpClient.Builder().addInterceptor(SentryOkHttpInterceptor(hub)) - val sentryOkHttpEventListener = when { - eventListener != null -> SentryOkHttpEventListener(hub, eventListener) - else -> SentryOkHttpEventListener(hub) - } - return builder.eventListener(sentryOkHttpEventListener).build() - } - } - - private val fixture = Fixture() - - private fun getRequest(url: String = "/hello"): Request { - return Request.Builder() - .addHeader("myHeader", "myValue") - .get() - .url(fixture.server.url(url)) - .build() - } - - @Test - fun `when there are multiple SentryOkHttpEventListeners, they don't duplicate spans`() { - val sut = fixture.getSut(eventListener = SentryOkHttpEventListener(fixture.hub)) - val call = sut.newCall(getRequest()) - call.execute().close() - assertEquals(8, fixture.sentryTracer.children.size) - } -} diff --git a/sentry-okhttp/src/main/java/io/sentry/okhttp/SentryOkHttpEventListener.kt b/sentry-okhttp/src/main/java/io/sentry/okhttp/SentryOkHttpEventListener.kt index 853d9cd02a..67a8cd8b56 100644 --- a/sentry-okhttp/src/main/java/io/sentry/okhttp/SentryOkHttpEventListener.kt +++ b/sentry-okhttp/src/main/java/io/sentry/okhttp/SentryOkHttpEventListener.kt @@ -406,9 +406,6 @@ public open class SentryOkHttpEventListener( private fun canCreateEventSpan(): Boolean { // If the wrapped EventListener is ours, we shouldn't create spans, as the originalEventListener already did it - // In case SentryOkHttpEventListener from sentry-android-okhttp is used, the is check won't work so we check - // for the class name as well. - return originalEventListener !is SentryOkHttpEventListener && - "io.sentry.android.okhttp.SentryOkHttpEventListener" != originalEventListener?.javaClass?.name + return originalEventListener !is SentryOkHttpEventListener } } diff --git a/sentry/api/sentry.api b/sentry/api/sentry.api index 8c25105d82..d29b04dd7d 100644 --- a/sentry/api/sentry.api +++ b/sentry/api/sentry.api @@ -229,7 +229,6 @@ public final class io/sentry/DataCategory : java/lang/Enum { public static final field Profile Lio/sentry/DataCategory; public static final field Security Lio/sentry/DataCategory; public static final field Session Lio/sentry/DataCategory; - public static final field Span Lio/sentry/DataCategory; public static final field Transaction Lio/sentry/DataCategory; public static final field Unknown Lio/sentry/DataCategory; public static final field UserReport Lio/sentry/DataCategory; @@ -668,7 +667,6 @@ public abstract interface class io/sentry/IScope { public abstract fun clear ()V public abstract fun clearAttachments ()V public abstract fun clearBreadcrumbs ()V - public abstract fun clearSession ()V public abstract fun clearTransaction ()V public abstract fun clone ()Lio/sentry/IScope; public abstract fun endSession ()Lio/sentry/Session; @@ -1223,7 +1221,6 @@ public final class io/sentry/NoOpScope : io/sentry/IScope { public fun clear ()V public fun clearAttachments ()V public fun clearBreadcrumbs ()V - public fun clearSession ()V public fun clearTransaction ()V public fun clone ()Lio/sentry/IScope; public synthetic fun clone ()Ljava/lang/Object; @@ -1595,7 +1592,6 @@ public final class io/sentry/Scope : io/sentry/IScope { public fun clear ()V public fun clearAttachments ()V public fun clearBreadcrumbs ()V - public fun clearSession ()V public fun clearTransaction ()V public fun clone ()Lio/sentry/IScope; public synthetic fun clone ()Ljava/lang/Object; @@ -2987,7 +2983,7 @@ public final class io/sentry/TypeCheckHint { public final class io/sentry/UncaughtExceptionHandlerIntegration : io/sentry/Integration, java/io/Closeable, java/lang/Thread$UncaughtExceptionHandler { public fun ()V public fun close ()V - public fun register (Lio/sentry/IHub;Lio/sentry/SentryOptions;)V + public final fun register (Lio/sentry/IHub;Lio/sentry/SentryOptions;)V public fun uncaughtException (Ljava/lang/Thread;Ljava/lang/Throwable;)V } @@ -3143,7 +3139,6 @@ public final class io/sentry/clientreport/ClientReportRecorder : io/sentry/clien public fun recordLostEnvelope (Lio/sentry/clientreport/DiscardReason;Lio/sentry/SentryEnvelope;)V public fun recordLostEnvelopeItem (Lio/sentry/clientreport/DiscardReason;Lio/sentry/SentryEnvelopeItem;)V public fun recordLostEvent (Lio/sentry/clientreport/DiscardReason;Lio/sentry/DataCategory;)V - public fun recordLostEvent (Lio/sentry/clientreport/DiscardReason;Lio/sentry/DataCategory;J)V } public final class io/sentry/clientreport/DiscardReason : java/lang/Enum { @@ -3189,7 +3184,6 @@ public abstract interface class io/sentry/clientreport/IClientReportRecorder { public abstract fun recordLostEnvelope (Lio/sentry/clientreport/DiscardReason;Lio/sentry/SentryEnvelope;)V public abstract fun recordLostEnvelopeItem (Lio/sentry/clientreport/DiscardReason;Lio/sentry/SentryEnvelopeItem;)V public abstract fun recordLostEvent (Lio/sentry/clientreport/DiscardReason;Lio/sentry/DataCategory;)V - public abstract fun recordLostEvent (Lio/sentry/clientreport/DiscardReason;Lio/sentry/DataCategory;J)V } public abstract interface class io/sentry/clientreport/IClientReportStorage { @@ -3203,7 +3197,6 @@ public final class io/sentry/clientreport/NoOpClientReportRecorder : io/sentry/c public fun recordLostEnvelope (Lio/sentry/clientreport/DiscardReason;Lio/sentry/SentryEnvelope;)V public fun recordLostEnvelopeItem (Lio/sentry/clientreport/DiscardReason;Lio/sentry/SentryEnvelopeItem;)V public fun recordLostEvent (Lio/sentry/clientreport/DiscardReason;Lio/sentry/DataCategory;)V - public fun recordLostEvent (Lio/sentry/clientreport/DiscardReason;Lio/sentry/DataCategory;J)V } public abstract interface class io/sentry/config/PropertiesProvider { diff --git a/sentry/src/main/java/io/sentry/Baggage.java b/sentry/src/main/java/io/sentry/Baggage.java index 360e1dc7d2..8e19fceaf8 100644 --- a/sentry/src/main/java/io/sentry/Baggage.java +++ b/sentry/src/main/java/io/sentry/Baggage.java @@ -305,21 +305,11 @@ public void setUserId(final @Nullable String userId) { set(DSCKeys.USER_ID, userId); } - /** - * @deprecated has no effect and will be removed in the next major update. - */ - @Deprecated - @SuppressWarnings("InlineMeSuggester") @ApiStatus.Internal public @Nullable String getUserSegment() { return get(DSCKeys.USER_SEGMENT); } - /** - * @deprecated has no effect and will be removed in the next major update. - */ - @Deprecated - @SuppressWarnings("InlineMeSuggester") @ApiStatus.Internal public void setUserSegment(final @Nullable String userSegment) { set(DSCKeys.USER_SEGMENT, userSegment); @@ -413,10 +403,6 @@ public void setValuesFromScope( setSampled(null); } - /** - * @deprecated has no effect and will be removed in the next major update. - */ - @Deprecated private static @Nullable String getSegment(final @NotNull User user) { if (user.getSegment() != null) { return user.getSegment(); @@ -485,7 +471,6 @@ public TraceContext toTraceContext() { final String publicKey = getPublicKey(); if (traceIdString != null && publicKey != null) { - @SuppressWarnings("deprecation") final @NotNull TraceContext traceContext = new TraceContext( new SentryId(traceIdString), diff --git a/sentry/src/main/java/io/sentry/DataCategory.java b/sentry/src/main/java/io/sentry/DataCategory.java index a4eafc2bb5..c3d6520987 100644 --- a/sentry/src/main/java/io/sentry/DataCategory.java +++ b/sentry/src/main/java/io/sentry/DataCategory.java @@ -14,7 +14,6 @@ public enum DataCategory { Profile("profile"), MetricBucket("metric_bucket"), Transaction("transaction"), - Span("span"), Security("security"), UserReport("user_report"), Unknown("unknown"); diff --git a/sentry/src/main/java/io/sentry/Hub.java b/sentry/src/main/java/io/sentry/Hub.java index b993b84ebc..6b6da88f09 100644 --- a/sentry/src/main/java/io/sentry/Hub.java +++ b/sentry/src/main/java/io/sentry/Hub.java @@ -686,22 +686,10 @@ public void flush(long timeoutMillis) { options .getClientReportRecorder() .recordLostEvent(DiscardReason.BACKPRESSURE, DataCategory.Transaction); - options - .getClientReportRecorder() - .recordLostEvent( - DiscardReason.BACKPRESSURE, - DataCategory.Span, - transaction.getSpans().size() + 1); } else { options .getClientReportRecorder() .recordLostEvent(DiscardReason.SAMPLE_RATE, DataCategory.Transaction); - options - .getClientReportRecorder() - .recordLostEvent( - DiscardReason.SAMPLE_RATE, - DataCategory.Span, - transaction.getSpans().size() + 1); } } else { StackItem item = null; diff --git a/sentry/src/main/java/io/sentry/IScope.java b/sentry/src/main/java/io/sentry/IScope.java index 3064df8f79..3842fb2c3a 100644 --- a/sentry/src/main/java/io/sentry/IScope.java +++ b/sentry/src/main/java/io/sentry/IScope.java @@ -352,9 +352,6 @@ public interface IScope { @Nullable Session getSession(); - @ApiStatus.Internal - void clearSession(); - @ApiStatus.Internal void setPropagationContext(final @NotNull PropagationContext propagationContext); diff --git a/sentry/src/main/java/io/sentry/NoOpScope.java b/sentry/src/main/java/io/sentry/NoOpScope.java index ed787b0029..c756fb49a3 100644 --- a/sentry/src/main/java/io/sentry/NoOpScope.java +++ b/sentry/src/main/java/io/sentry/NoOpScope.java @@ -219,10 +219,6 @@ public void withTransaction(Scope.@NotNull IWithTransaction callback) {} return null; } - @ApiStatus.Internal - @Override - public void clearSession() {} - @ApiStatus.Internal @Override public void setPropagationContext(@NotNull PropagationContext propagationContext) {} diff --git a/sentry/src/main/java/io/sentry/Scope.java b/sentry/src/main/java/io/sentry/Scope.java index 356ee2b57c..91c9fcd8cf 100644 --- a/sentry/src/main/java/io/sentry/Scope.java +++ b/sentry/src/main/java/io/sentry/Scope.java @@ -913,12 +913,6 @@ public SentryOptions getOptions() { return session; } - @ApiStatus.Internal - @Override - public void clearSession() { - session = null; - } - @ApiStatus.Internal @Override public void setPropagationContext(final @NotNull PropagationContext propagationContext) { diff --git a/sentry/src/main/java/io/sentry/SentryClient.java b/sentry/src/main/java/io/sentry/SentryClient.java index 31d4377dbb..ea70371722 100644 --- a/sentry/src/main/java/io/sentry/SentryClient.java +++ b/sentry/src/main/java/io/sentry/SentryClient.java @@ -412,7 +412,6 @@ private SentryTransaction processTransaction( final @NotNull Hint hint, final @NotNull List eventProcessors) { for (final EventProcessor processor : eventProcessors) { - final int spanCountBeforeProcessor = transaction.getSpans().size(); try { transaction = processor.process(transaction, hint); } catch (Throwable e) { @@ -424,7 +423,6 @@ private SentryTransaction processTransaction( "An exception occurred while processing transaction by processor: %s", processor.getClass().getName()); } - final int spanCountAfterProcessor = transaction == null ? 0 : transaction.getSpans().size(); if (transaction == null) { options @@ -436,25 +434,7 @@ private SentryTransaction processTransaction( options .getClientReportRecorder() .recordLostEvent(DiscardReason.EVENT_PROCESSOR, DataCategory.Transaction); - // If we drop a transaction, we are also dropping all its spans (+1 for the root span) - options - .getClientReportRecorder() - .recordLostEvent( - DiscardReason.EVENT_PROCESSOR, DataCategory.Span, spanCountBeforeProcessor + 1); break; - } else if (spanCountAfterProcessor < spanCountBeforeProcessor) { - // If the callback removed some spans, we report it - final int droppedSpanCount = spanCountBeforeProcessor - spanCountAfterProcessor; - options - .getLogger() - .log( - SentryLevel.DEBUG, - "%d spans were dropped by a processor: %s", - droppedSpanCount, - processor.getClass().getName()); - options - .getClientReportRecorder() - .recordLostEvent(DiscardReason.EVENT_PROCESSOR, DataCategory.Span, droppedSpanCount); } } return transaction; @@ -686,9 +666,7 @@ public void captureSession(final @NotNull Session session, final @Nullable Hint return SentryId.EMPTY_ID; } - final int spanCountBeforeCallback = transaction.getSpans().size(); transaction = executeBeforeSendTransaction(transaction, hint); - final int spanCountAfterCallback = transaction == null ? 0 : transaction.getSpans().size(); if (transaction == null) { options @@ -697,24 +675,7 @@ public void captureSession(final @NotNull Session session, final @Nullable Hint options .getClientReportRecorder() .recordLostEvent(DiscardReason.BEFORE_SEND, DataCategory.Transaction); - // If we drop a transaction, we are also dropping all its spans (+1 for the root span) - options - .getClientReportRecorder() - .recordLostEvent( - DiscardReason.BEFORE_SEND, DataCategory.Span, spanCountBeforeCallback + 1); return SentryId.EMPTY_ID; - } else if (spanCountAfterCallback < spanCountBeforeCallback) { - // If the callback removed some spans, we report it - final int droppedSpanCount = spanCountBeforeCallback - spanCountAfterCallback; - options - .getLogger() - .log( - SentryLevel.DEBUG, - "%d spans were dropped by beforeSendTransaction.", - droppedSpanCount); - options - .getClientReportRecorder() - .recordLostEvent(DiscardReason.BEFORE_SEND, DataCategory.Span, droppedSpanCount); } try { diff --git a/sentry/src/main/java/io/sentry/TraceContext.java b/sentry/src/main/java/io/sentry/TraceContext.java index 56c9ee586f..ef2944a9e9 100644 --- a/sentry/src/main/java/io/sentry/TraceContext.java +++ b/sentry/src/main/java/io/sentry/TraceContext.java @@ -26,25 +26,9 @@ public final class TraceContext implements JsonUnknown, JsonSerializable { private @Nullable Map unknown; TraceContext(@NotNull SentryId traceId, @NotNull String publicKey) { - this(traceId, publicKey, null, null, null, null, null, null); + this(traceId, publicKey, null, null, null, null, null, null, null); } - TraceContext( - @NotNull SentryId traceId, - @NotNull String publicKey, - @Nullable String release, - @Nullable String environment, - @Nullable String userId, - @Nullable String transaction, - @Nullable String sampleRate, - @Nullable String sampled) { - this(traceId, publicKey, release, environment, userId, null, transaction, sampleRate, sampled); - } - - /** - * @deprecated segment has no effect and will be removed in the next major update. - */ - @Deprecated TraceContext( @NotNull SentryId traceId, @NotNull String publicKey, @@ -96,10 +80,6 @@ public final class TraceContext implements JsonUnknown, JsonSerializable { return userId; } - /** - * @deprecated has no effect and will be removed in the next major update. - */ - @Deprecated public @Nullable String getUserSegment() { return userSegment; } @@ -136,10 +116,6 @@ private TraceContextUser(final @Nullable String id, final @Nullable String segme return id; } - /** - * @deprecated has no effect and will be removed in the next major update. - */ - @Deprecated public @Nullable String getSegment() { return segment; } diff --git a/sentry/src/main/java/io/sentry/UncaughtExceptionHandlerIntegration.java b/sentry/src/main/java/io/sentry/UncaughtExceptionHandlerIntegration.java index da594e4cb4..33e1a4a815 100644 --- a/sentry/src/main/java/io/sentry/UncaughtExceptionHandlerIntegration.java +++ b/sentry/src/main/java/io/sentry/UncaughtExceptionHandlerIntegration.java @@ -43,7 +43,7 @@ public UncaughtExceptionHandlerIntegration() { } @Override - public void register(final @NotNull IHub hub, final @NotNull SentryOptions options) { + public final void register(final @NotNull IHub hub, final @NotNull SentryOptions options) { if (registered) { options .getLogger() @@ -75,14 +75,7 @@ public void register(final @NotNull IHub hub, final @NotNull SentryOptions optio "default UncaughtExceptionHandler class='" + currentHandler.getClass().getName() + "'"); - - if (currentHandler instanceof UncaughtExceptionHandlerIntegration) { - final UncaughtExceptionHandlerIntegration currentHandlerIntegration = - (UncaughtExceptionHandlerIntegration) currentHandler; - defaultExceptionHandler = currentHandlerIntegration.defaultExceptionHandler; - } else { - defaultExceptionHandler = currentHandler; - } + defaultExceptionHandler = currentHandler; } threadAdapter.setDefaultUncaughtExceptionHandler(this); diff --git a/sentry/src/main/java/io/sentry/clientreport/ClientReportRecorder.java b/sentry/src/main/java/io/sentry/clientreport/ClientReportRecorder.java index 796a17cb3c..f51287d7d9 100644 --- a/sentry/src/main/java/io/sentry/clientreport/ClientReportRecorder.java +++ b/sentry/src/main/java/io/sentry/clientreport/ClientReportRecorder.java @@ -7,8 +7,6 @@ import io.sentry.SentryItemType; import io.sentry.SentryLevel; import io.sentry.SentryOptions; -import io.sentry.protocol.SentrySpan; -import io.sentry.protocol.SentryTransaction; import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -86,19 +84,8 @@ public void recordLostEnvelopeItem( .log(SentryLevel.ERROR, "Unable to restore counts from previous client report."); } } else { - final @NotNull DataCategory itemCategory = categoryFromItemType(itemType); - if (itemCategory.equals(DataCategory.Transaction)) { - final @Nullable SentryTransaction transaction = - envelopeItem.getTransaction(options.getSerializer()); - if (transaction != null) { - final @NotNull List spans = transaction.getSpans(); - // When a transaction is dropped, we also record its spans as dropped plus one, - // since Relay extracts an additional span from the transaction. - recordLostEventInternal( - reason.getReason(), DataCategory.Span.getCategory(), spans.size() + 1L); - } - } - recordLostEventInternal(reason.getReason(), itemCategory.getCategory(), 1L); + recordLostEventInternal( + reason.getReason(), categoryFromItemType(itemType).getCategory(), 1L); } } catch (Throwable e) { options.getLogger().log(SentryLevel.ERROR, e, "Unable to record lost envelope item."); @@ -107,14 +94,8 @@ public void recordLostEnvelopeItem( @Override public void recordLostEvent(@NotNull DiscardReason reason, @NotNull DataCategory category) { - recordLostEvent(reason, category, 1); - } - - @Override - public void recordLostEvent( - @NotNull DiscardReason reason, @NotNull DataCategory category, long count) { try { - recordLostEventInternal(reason.getReason(), category.getCategory(), count); + recordLostEventInternal(reason.getReason(), category.getCategory(), 1L); } catch (Throwable e) { options.getLogger().log(SentryLevel.ERROR, e, "Unable to record lost event."); } diff --git a/sentry/src/main/java/io/sentry/clientreport/IClientReportRecorder.java b/sentry/src/main/java/io/sentry/clientreport/IClientReportRecorder.java index c3c2d2e9f6..72e23f5b8f 100644 --- a/sentry/src/main/java/io/sentry/clientreport/IClientReportRecorder.java +++ b/sentry/src/main/java/io/sentry/clientreport/IClientReportRecorder.java @@ -16,8 +16,6 @@ void recordLostEnvelopeItem( void recordLostEvent(@NotNull DiscardReason reason, @NotNull DataCategory category); - void recordLostEvent(@NotNull DiscardReason reason, @NotNull DataCategory category, long count); - @NotNull SentryEnvelope attachReportToEnvelope(@NotNull SentryEnvelope envelope); } diff --git a/sentry/src/main/java/io/sentry/clientreport/NoOpClientReportRecorder.java b/sentry/src/main/java/io/sentry/clientreport/NoOpClientReportRecorder.java index 360468e19d..64aa957680 100644 --- a/sentry/src/main/java/io/sentry/clientreport/NoOpClientReportRecorder.java +++ b/sentry/src/main/java/io/sentry/clientreport/NoOpClientReportRecorder.java @@ -25,12 +25,6 @@ public void recordLostEvent(@NotNull DiscardReason reason, @NotNull DataCategory // do nothing } - @Override - public void recordLostEvent( - @NotNull DiscardReason reason, @NotNull DataCategory category, long count) { - // do nothing - } - @Override public @NotNull SentryEnvelope attachReportToEnvelope(@NotNull SentryEnvelope envelope) { return envelope; diff --git a/sentry/src/main/java/io/sentry/metrics/MetricsHelper.java b/sentry/src/main/java/io/sentry/metrics/MetricsHelper.java index c4353c53a3..46e22ca8ad 100644 --- a/sentry/src/main/java/io/sentry/metrics/MetricsHelper.java +++ b/sentry/src/main/java/io/sentry/metrics/MetricsHelper.java @@ -1,11 +1,11 @@ package io.sentry.metrics; import io.sentry.MeasurementUnit; -import java.security.SecureRandom; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Random; import java.util.regex.Pattern; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; @@ -27,7 +27,7 @@ public final class MetricsHelper { private static final char TAGS_ESCAPE_CHAR = '\\'; private static long FLUSH_SHIFT_MS = - (long) (new SecureRandom().nextFloat() * (ROLLUP_IN_SECONDS * 1000f)); + (long) (new Random().nextFloat() * (ROLLUP_IN_SECONDS * 1000f)); public static long getTimeBucketKey(final long timestampMs) { final long seconds = timestampMs / 1000; diff --git a/sentry/src/main/java/io/sentry/protocol/User.java b/sentry/src/main/java/io/sentry/protocol/User.java index 619d870c66..1dc6af7811 100644 --- a/sentry/src/main/java/io/sentry/protocol/User.java +++ b/sentry/src/main/java/io/sentry/protocol/User.java @@ -34,11 +34,7 @@ public final class User implements JsonUnknown, JsonSerializable { /** Username of the user. */ private @Nullable String username; - /** - * @deprecated has no effect and will be removed in the next major update. Use a custom tag or - * context instead. - */ - @Deprecated private @Nullable String segment; + private @Nullable String segment; /** Remote IP address of the user. */ private @Nullable String ipAddress; @@ -228,9 +224,7 @@ public void setUsername(final @Nullable String username) { * Gets the segment of the user. * * @return the user segment. - * @deprecated has no effect and will be removed in the next major update. */ - @Deprecated public @Nullable String getSegment() { return segment; } @@ -239,9 +233,7 @@ public void setUsername(final @Nullable String username) { * Sets the segment of the user. * * @param segment the segment. - * @deprecated has no effect and will be removed in the next major update. */ - @Deprecated public void setSegment(final @Nullable String segment) { this.segment = segment; } diff --git a/sentry/src/test/java/io/sentry/HubTest.kt b/sentry/src/test/java/io/sentry/HubTest.kt index cb66736e24..8fac963e70 100644 --- a/sentry/src/test/java/io/sentry/HubTest.kt +++ b/sentry/src/test/java/io/sentry/HubTest.kt @@ -1450,16 +1450,11 @@ class HubTest { sut.bindClient(mockClient) val sentryTracer = SentryTracer(TransactionContext("name", "op", TracesSamplingDecision(false)), sut) - // Unsampled spans are not added to the transaction, so they are not recorded - sentryTracer.startChild("dropped span", "span 1").finish() sentryTracer.finish() assertClientReport( options.clientReportRecorder, - listOf( - DiscardedEvent(DiscardReason.SAMPLE_RATE.reason, DataCategory.Transaction.category, 1), - DiscardedEvent(DiscardReason.SAMPLE_RATE.reason, DataCategory.Span.category, 1) - ) + listOf(DiscardedEvent(DiscardReason.SAMPLE_RATE.reason, DataCategory.Transaction.category, 1)) ) } @@ -1477,16 +1472,11 @@ class HubTest { whenever(mockBackpressureMonitor.downsampleFactor).thenReturn(1) val sentryTracer = SentryTracer(TransactionContext("name", "op", TracesSamplingDecision(false)), sut) - // Unsampled spans are not added to the transaction, so they are not recorded - sentryTracer.startChild("dropped span", "span 1").finish() sentryTracer.finish() assertClientReport( options.clientReportRecorder, - listOf( - DiscardedEvent(DiscardReason.BACKPRESSURE.reason, DataCategory.Transaction.category, 1), - DiscardedEvent(DiscardReason.BACKPRESSURE.reason, DataCategory.Span.category, 1) - ) + listOf(DiscardedEvent(DiscardReason.BACKPRESSURE.reason, DataCategory.Transaction.category, 1)) ) } //endregion diff --git a/sentry/src/test/java/io/sentry/SentryClientTest.kt b/sentry/src/test/java/io/sentry/SentryClientTest.kt index f70d7e0584..de540bf90c 100644 --- a/sentry/src/test/java/io/sentry/SentryClientTest.kt +++ b/sentry/src/test/java/io/sentry/SentryClientTest.kt @@ -89,8 +89,7 @@ class SentryClientTest { init { whenever(factory.create(any(), any())).thenReturn(transport) whenever(hub.options).thenReturn(sentryOptions) - sentryTracer = SentryTracer(TransactionContext("a-transaction", "op", TracesSamplingDecision(true)), hub) - sentryTracer.startChild("a-span", "span 1").finish() + sentryTracer = SentryTracer(TransactionContext("a-transaction", "op"), hub) } var attachment = Attachment("hello".toByteArray(), "hello.txt", "text/plain", true) @@ -808,10 +807,7 @@ class SentryClientTest { assertClientReport( fixture.sentryOptions.clientReportRecorder, - listOf( - DiscardedEvent(DiscardReason.EVENT_PROCESSOR.reason, DataCategory.Transaction.category, 1), - DiscardedEvent(DiscardReason.EVENT_PROCESSOR.reason, DataCategory.Span.category, 2) - ) + listOf(DiscardedEvent(DiscardReason.EVENT_PROCESSOR.reason, DataCategory.Transaction.category, 1)) ) } @@ -897,10 +893,7 @@ class SentryClientTest { assertClientReport( fixture.sentryOptions.clientReportRecorder, - listOf( - DiscardedEvent(DiscardReason.BEFORE_SEND.reason, DataCategory.Transaction.category, 1), - DiscardedEvent(DiscardReason.BEFORE_SEND.reason, DataCategory.Span.category, 2) - ) + listOf(DiscardedEvent(DiscardReason.BEFORE_SEND.reason, DataCategory.Transaction.category, 1)) ) } @@ -916,36 +909,7 @@ class SentryClientTest { assertClientReport( fixture.sentryOptions.clientReportRecorder, - listOf( - DiscardedEvent(DiscardReason.EVENT_PROCESSOR.reason, DataCategory.Transaction.category, 1), - DiscardedEvent(DiscardReason.EVENT_PROCESSOR.reason, DataCategory.Span.category, 2) - ) - ) - } - - @Test - fun `span dropped by event processor is recorded`() { - fixture.sentryTracer.startChild("dropped span", "span1").finish() - fixture.sentryTracer.startChild("dropped span", "span2").finish() - val transaction = SentryTransaction(fixture.sentryTracer) - val scope = createScope() - scope.addEventProcessor(object : EventProcessor { - override fun process(transaction: SentryTransaction, hint: Hint): SentryTransaction? { - // we are removing span1 and a-span from the fixture - transaction.spans.removeIf { it.description != "span2" } - return transaction - } - }) - - fixture.getSut().captureTransaction(transaction, scope, null) - - verify(fixture.transport).send(any(), anyOrNull()) - - assertClientReport( - fixture.sentryOptions.clientReportRecorder, - listOf( - DiscardedEvent(DiscardReason.EVENT_PROCESSOR.reason, DataCategory.Span.category, 2) - ) + listOf(DiscardedEvent(DiscardReason.EVENT_PROCESSOR.reason, DataCategory.Transaction.category, 1)) ) } @@ -1005,10 +969,7 @@ class SentryClientTest { assertClientReport( fixture.sentryOptions.clientReportRecorder, - listOf( - DiscardedEvent(DiscardReason.BEFORE_SEND.reason, DataCategory.Transaction.category, 1), - DiscardedEvent(DiscardReason.BEFORE_SEND.reason, DataCategory.Span.category, 2) - ) + listOf(DiscardedEvent(DiscardReason.BEFORE_SEND.reason, DataCategory.Transaction.category, 1)) ) } @@ -1046,34 +1007,7 @@ class SentryClientTest { assertClientReport( fixture.sentryOptions.clientReportRecorder, - listOf( - DiscardedEvent(DiscardReason.BEFORE_SEND.reason, DataCategory.Transaction.category, 1), - DiscardedEvent(DiscardReason.BEFORE_SEND.reason, DataCategory.Span.category, 2) - ) - ) - } - - @Test - fun `when beforeSendTransaction drops a span, dropped span is recorded`() { - fixture.sentryTracer.startChild("dropped span", "span1").finish() - fixture.sentryTracer.startChild("dropped span", "span2").finish() - fixture.sentryOptions.setBeforeSendTransaction { t: SentryTransaction, _: Any? -> - t.apply { - // we are removing span1 and a-span from the fixture - spans.removeIf { it.description != "span2" } - } - } - - val transaction = SentryTransaction(fixture.sentryTracer) - fixture.getSut().captureTransaction(transaction, fixture.sentryTracer.traceContext()) - - verify(fixture.transport).send(any(), anyOrNull()) - - assertClientReport( - fixture.sentryOptions.clientReportRecorder, - listOf( - DiscardedEvent(DiscardReason.BEFORE_SEND.reason, DataCategory.Span.category, 2) - ) + listOf(DiscardedEvent(DiscardReason.BEFORE_SEND.reason, DataCategory.Transaction.category, 1)) ) } diff --git a/sentry/src/test/java/io/sentry/SentryTracerTest.kt b/sentry/src/test/java/io/sentry/SentryTracerTest.kt index 6bd835716e..0942768a8a 100644 --- a/sentry/src/test/java/io/sentry/SentryTracerTest.kt +++ b/sentry/src/test/java/io/sentry/SentryTracerTest.kt @@ -588,6 +588,8 @@ class SentryTracerTest { assertEquals("environment", it.environment) assertEquals("release@3.0.0", it.release) assertEquals(transaction.name, it.transaction) + // assertEquals("user-id", it.userId) + assertEquals("pro", it.userSegment) } } diff --git a/sentry/src/test/java/io/sentry/UncaughtExceptionHandlerIntegrationTest.kt b/sentry/src/test/java/io/sentry/UncaughtExceptionHandlerIntegrationTest.kt index aaa8cbe3fc..01353d5ac0 100644 --- a/sentry/src/test/java/io/sentry/UncaughtExceptionHandlerIntegrationTest.kt +++ b/sentry/src/test/java/io/sentry/UncaughtExceptionHandlerIntegrationTest.kt @@ -7,7 +7,6 @@ import io.sentry.hints.EventDropReason.MULTITHREADED_DEDUPLICATION import io.sentry.protocol.SentryId import io.sentry.util.HintUtils import org.mockito.kotlin.any -import org.mockito.kotlin.anyOrNull import org.mockito.kotlin.argThat import org.mockito.kotlin.argWhere import org.mockito.kotlin.argumentCaptor @@ -20,7 +19,6 @@ import java.io.PrintStream import java.nio.file.Files import kotlin.concurrent.thread import kotlin.test.Test -import kotlin.test.assertEquals import kotlin.test.assertNotNull import kotlin.test.assertTrue @@ -293,54 +291,4 @@ class UncaughtExceptionHandlerIntegrationTest { } ) } - - @Test - fun `multiple registrations do not cause the build-up of a tree of UncaughtExceptionHandlerIntegrations`() { - var currentDefaultHandler: Thread.UncaughtExceptionHandler? = null - - val handler = mock() - whenever(handler.defaultUncaughtExceptionHandler).thenAnswer { currentDefaultHandler } - - whenever(handler.setDefaultUncaughtExceptionHandler(anyOrNull())).then { - currentDefaultHandler = it.getArgument(0) - null - } - - val integration1 = UncaughtExceptionHandlerIntegration(handler) - integration1.register(fixture.hub, fixture.options) - - val integration2 = UncaughtExceptionHandlerIntegration(handler) - integration2.register(fixture.hub, fixture.options) - - assertEquals(currentDefaultHandler, integration2) - integration2.close() - - assertEquals(null, currentDefaultHandler) - } - - @Test - fun `multiple registrations do not cause the build-up of a tree of UncaughtExceptionHandlerIntegrations, reset to inital`() { - val initialUncaughtExceptionHandler = Thread.UncaughtExceptionHandler { _, _ -> } - - var currentDefaultHandler: Thread.UncaughtExceptionHandler? = initialUncaughtExceptionHandler - - val handler = mock() - whenever(handler.defaultUncaughtExceptionHandler).thenAnswer { currentDefaultHandler } - - whenever(handler.setDefaultUncaughtExceptionHandler(anyOrNull())).then { - currentDefaultHandler = it.getArgument(0) - null - } - - val integration1 = UncaughtExceptionHandlerIntegration(handler) - integration1.register(fixture.hub, fixture.options) - - val integration2 = UncaughtExceptionHandlerIntegration(handler) - integration2.register(fixture.hub, fixture.options) - - assertEquals(currentDefaultHandler, integration2) - integration2.close() - - assertEquals(initialUncaughtExceptionHandler, currentDefaultHandler) - } } diff --git a/sentry/src/test/java/io/sentry/clientreport/ClientReportTest.kt b/sentry/src/test/java/io/sentry/clientreport/ClientReportTest.kt index c06e8da1f6..527e1b5531 100644 --- a/sentry/src/test/java/io/sentry/clientreport/ClientReportTest.kt +++ b/sentry/src/test/java/io/sentry/clientreport/ClientReportTest.kt @@ -18,7 +18,6 @@ import io.sentry.SentryEvent import io.sentry.SentryOptions import io.sentry.SentryTracer import io.sentry.Session -import io.sentry.TracesSamplingDecision import io.sentry.TransactionContext import io.sentry.UncaughtExceptionHandlerIntegration.UncaughtExceptionHint import io.sentry.UserFeedback @@ -64,7 +63,6 @@ class ClientReportTest { val envelope = testHelper.newEnvelope( SentryEnvelopeItem.fromClientReport(opts.serializer, lostClientReport), - SentryEnvelopeItem.fromEvent(opts.serializer, SentryTransaction(transaction)), SentryEnvelopeItem.fromEvent(opts.serializer, SentryEvent()), SentryEnvelopeItem.fromSession(opts.serializer, Session("dis", User(), "env", "0.0.1")), SentryEnvelopeItem.fromUserFeedback(opts.serializer, UserFeedback(SentryId(UUID.randomUUID()))), @@ -77,12 +75,10 @@ class ClientReportTest { clientReportRecorder.recordLostEnvelope(DiscardReason.NETWORK_ERROR, envelope) val clientReportAtEnd = clientReportRecorder.resetCountsAndGenerateClientReport() - testHelper.assertTotalCount(15, clientReportAtEnd) + testHelper.assertTotalCount(13, clientReportAtEnd) testHelper.assertCountFor(DiscardReason.SAMPLE_RATE, DataCategory.Error, 3, clientReportAtEnd) testHelper.assertCountFor(DiscardReason.BEFORE_SEND, DataCategory.Error, 2, clientReportAtEnd) testHelper.assertCountFor(DiscardReason.QUEUE_OVERFLOW, DataCategory.Transaction, 1, clientReportAtEnd) - testHelper.assertCountFor(DiscardReason.NETWORK_ERROR, DataCategory.Span, 1, clientReportAtEnd) - testHelper.assertCountFor(DiscardReason.NETWORK_ERROR, DataCategory.Transaction, 1, clientReportAtEnd) testHelper.assertCountFor(DiscardReason.NETWORK_ERROR, DataCategory.Error, 1, clientReportAtEnd) testHelper.assertCountFor(DiscardReason.NETWORK_ERROR, DataCategory.UserReport, 1, clientReportAtEnd) testHelper.assertCountFor(DiscardReason.NETWORK_ERROR, DataCategory.Session, 1, clientReportAtEnd) @@ -92,29 +88,6 @@ class ClientReportTest { testHelper.assertCountFor(DiscardReason.NETWORK_ERROR, DataCategory.MetricBucket, 1, clientReportAtEnd) } - @Test - fun `lost transaction records dropped spans`() { - givenClientReportRecorder() - val hub = mock() - whenever(hub.options).thenReturn(opts) - val transaction = SentryTracer(TransactionContext("name", "op", TracesSamplingDecision(true)), hub) - transaction.startChild("lost span", "span1").finish() - transaction.startChild("lost span", "span2").finish() - transaction.startChild("lost span", "span3").finish() - transaction.startChild("lost span", "span4").finish() - - val envelope = testHelper.newEnvelope( - SentryEnvelopeItem.fromEvent(opts.serializer, SentryTransaction(transaction)) - ) - - clientReportRecorder.recordLostEnvelope(DiscardReason.NETWORK_ERROR, envelope) - - val clientReportAtEnd = clientReportRecorder.resetCountsAndGenerateClientReport() - testHelper.assertTotalCount(6, clientReportAtEnd) - testHelper.assertCountFor(DiscardReason.NETWORK_ERROR, DataCategory.Span, 5, clientReportAtEnd) - testHelper.assertCountFor(DiscardReason.NETWORK_ERROR, DataCategory.Transaction, 1, clientReportAtEnd) - } - @Test fun `lost event can be recorded`() { givenClientReportRecorder() @@ -216,7 +189,7 @@ class DropEverythingEventProcessor : EventProcessor { class ClientReportTestHelper(val options: SentryOptions) { val reasons = DiscardReason.values() - val categories = DataCategory.values() + val categories = listOf(DataCategory.Error, DataCategory.Attachment, DataCategory.Session, DataCategory.Transaction, DataCategory.UserReport) fun assertTotalCount(expectedCount: Long, clientReport: ClientReport?) { assertEquals(expectedCount, clientReport?.discardedEvents?.sumOf { it.quantity } ?: 0L)